video/rockchip: rga2: use axi safe reset
[firefly-linux-kernel-4.4.55.git] / drivers / video / fbdev / s1d13xxxfb.c
1 /* drivers/video/s1d13xxxfb.c
2  *
3  * (c) 2004 Simtec Electronics
4  * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
5  * (c) 2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
6  *
7  * Driver for Epson S1D13xxx series framebuffer chips
8  *
9  * Adapted from
10  *  linux/drivers/video/skeletonfb.c
11  *  linux/drivers/video/epson1355fb.c
12  *  linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson)
13  *
14  * TODO: - handle dual screen display (CRT and LCD at the same time).
15  *       - check_var(), mode change, etc.
16  *       - probably not SMP safe :)
17  *       - support all bitblt operations on all cards
18  *
19  * This file is subject to the terms and conditions of the GNU General Public
20  * License. See the file COPYING in the main directory of this archive for
21  * more details.
22  */
23
24 #include <linux/module.h>
25 #include <linux/platform_device.h>
26 #include <linux/delay.h>
27 #include <linux/types.h>
28 #include <linux/errno.h>
29 #include <linux/mm.h>
30 #include <linux/mman.h>
31 #include <linux/fb.h>
32 #include <linux/spinlock_types.h>
33 #include <linux/spinlock.h>
34 #include <linux/slab.h>
35 #include <linux/io.h>
36
37 #include <video/s1d13xxxfb.h>
38
39 #define PFX     "s1d13xxxfb: "
40 #define BLIT    "s1d13xxxfb_bitblt: "
41
42 /*
43  * set this to enable debugging on general functions
44  */
45 #if 0
46 #define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0)
47 #else
48 #define dbg(fmt, args...) do { } while (0)
49 #endif
50
51 /*
52  * set this to enable debugging on 2D acceleration
53  */
54 #if 0
55 #define dbg_blit(fmt, args...) do { printk(KERN_INFO BLIT fmt, ## args); } while (0)
56 #else
57 #define dbg_blit(fmt, args...) do { } while (0)
58 #endif
59
60 /*
61  * we make sure only one bitblt operation is running
62  */
63 static DEFINE_SPINLOCK(s1d13xxxfb_bitblt_lock);
64
65 /*
66  * list of card production ids
67  */
68 static const int s1d13xxxfb_prod_ids[] = {
69         S1D13505_PROD_ID,
70         S1D13506_PROD_ID,
71         S1D13806_PROD_ID,
72 };
73
74 /*
75  * List of card strings
76  */
77 static const char *s1d13xxxfb_prod_names[] = {
78         "S1D13505",
79         "S1D13506",
80         "S1D13806",
81 };
82
83 /*
84  * here we define the default struct fb_fix_screeninfo
85  */
86 static struct fb_fix_screeninfo s1d13xxxfb_fix = {
87         .id             = S1D_FBID,
88         .type           = FB_TYPE_PACKED_PIXELS,
89         .visual         = FB_VISUAL_PSEUDOCOLOR,
90         .xpanstep       = 0,
91         .ypanstep       = 1,
92         .ywrapstep      = 0,
93         .accel          = FB_ACCEL_NONE,
94 };
95
96 static inline u8
97 s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno)
98 {
99 #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
100         regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
101 #endif
102         return readb(par->regs + regno);
103 }
104
105 static inline void
106 s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value)
107 {
108 #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
109         regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
110 #endif
111         writeb(value, par->regs + regno);
112 }
113
114 static inline void
115 s1d13xxxfb_runinit(struct s1d13xxxfb_par *par,
116                         const struct s1d13xxxfb_regval *initregs,
117                         const unsigned int size)
118 {
119         int i;
120
121         for (i = 0; i < size; i++) {
122                 if ((initregs[i].addr == S1DREG_DELAYOFF) ||
123                                 (initregs[i].addr == S1DREG_DELAYON))
124                         mdelay((int)initregs[i].value);
125                 else {
126                         s1d13xxxfb_writereg(par, initregs[i].addr, initregs[i].value);
127                 }
128         }
129
130         /* make sure the hardware can cope with us */
131         mdelay(1);
132 }
133
134 static inline void
135 lcd_enable(struct s1d13xxxfb_par *par, int enable)
136 {
137         u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
138
139         if (enable)
140                 mode |= 0x01;
141         else
142                 mode &= ~0x01;
143
144         s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
145 }
146
147 static inline void
148 crt_enable(struct s1d13xxxfb_par *par, int enable)
149 {
150         u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
151
152         if (enable)
153                 mode |= 0x02;
154         else
155                 mode &= ~0x02;
156
157         s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
158 }
159
160
161 /*************************************************************
162  framebuffer control functions
163  *************************************************************/
164 static inline void
165 s1d13xxxfb_setup_pseudocolour(struct fb_info *info)
166 {
167         info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
168
169         info->var.red.length = 4;
170         info->var.green.length = 4;
171         info->var.blue.length = 4;
172 }
173
174 static inline void
175 s1d13xxxfb_setup_truecolour(struct fb_info *info)
176 {
177         info->fix.visual = FB_VISUAL_TRUECOLOR;
178         info->var.bits_per_pixel = 16;
179
180         info->var.red.length = 5;
181         info->var.red.offset = 11;
182
183         info->var.green.length = 6;
184         info->var.green.offset = 5;
185
186         info->var.blue.length = 5;
187         info->var.blue.offset = 0;
188 }
189
190 /**
191  *      s1d13xxxfb_set_par - Alters the hardware state.
192  *      @info: frame buffer structure
193  *
194  *      Using the fb_var_screeninfo in fb_info we set the depth of the
195  *      framebuffer. This function alters the par AND the
196  *      fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
197  *      fb_info since we are using that data. This means we depend on the
198  *      data in var inside fb_info to be supported by the hardware.
199  *      xxxfb_check_var is always called before xxxfb_set_par to ensure this.
200  *
201  *      XXX TODO: write proper s1d13xxxfb_check_var(), without which that
202  *      function is quite useless.
203  */
204 static int
205 s1d13xxxfb_set_par(struct fb_info *info)
206 {
207         struct s1d13xxxfb_par *s1dfb = info->par;
208         unsigned int val;
209
210         dbg("s1d13xxxfb_set_par: bpp=%d\n", info->var.bits_per_pixel);
211
212         if ((s1dfb->display & 0x01))    /* LCD */
213                 val = s1d13xxxfb_readreg(s1dfb, S1DREG_LCD_DISP_MODE);   /* read colour control */
214         else    /* CRT */
215                 val = s1d13xxxfb_readreg(s1dfb, S1DREG_CRT_DISP_MODE);   /* read colour control */
216
217         val &= ~0x07;
218
219         switch (info->var.bits_per_pixel) {
220                 case 4:
221                         dbg("pseudo colour 4\n");
222                         s1d13xxxfb_setup_pseudocolour(info);
223                         val |= 2;
224                         break;
225                 case 8:
226                         dbg("pseudo colour 8\n");
227                         s1d13xxxfb_setup_pseudocolour(info);
228                         val |= 3;
229                         break;
230                 case 16:
231                         dbg("true colour\n");
232                         s1d13xxxfb_setup_truecolour(info);
233                         val |= 5;
234                         break;
235
236                 default:
237                         dbg("bpp not supported!\n");
238                         return -EINVAL;
239         }
240
241         dbg("writing %02x to display mode register\n", val);
242
243         if ((s1dfb->display & 0x01))    /* LCD */
244                 s1d13xxxfb_writereg(s1dfb, S1DREG_LCD_DISP_MODE, val);
245         else    /* CRT */
246                 s1d13xxxfb_writereg(s1dfb, S1DREG_CRT_DISP_MODE, val);
247
248         info->fix.line_length  = info->var.xres * info->var.bits_per_pixel;
249         info->fix.line_length /= 8;
250
251         dbg("setting line_length to %d\n", info->fix.line_length);
252
253         dbg("done setup\n");
254
255         return 0;
256 }
257
258 /**
259  *      s1d13xxxfb_setcolreg - sets a color register.
260  *      @regno: Which register in the CLUT we are programming
261  *      @red: The red value which can be up to 16 bits wide
262  *      @green: The green value which can be up to 16 bits wide
263  *      @blue:  The blue value which can be up to 16 bits wide.
264  *      @transp: If supported the alpha value which can be up to 16 bits wide.
265  *      @info: frame buffer info structure
266  *
267  *      Returns negative errno on error, or zero on success.
268  */
269 static int
270 s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
271                         u_int transp, struct fb_info *info)
272 {
273         struct s1d13xxxfb_par *s1dfb = info->par;
274         unsigned int pseudo_val;
275
276         if (regno >= S1D_PALETTE_SIZE)
277                 return -EINVAL;
278
279         dbg("s1d13xxxfb_setcolreg: %d: rgb=%d,%d,%d, tr=%d\n",
280                     regno, red, green, blue, transp);
281
282         if (info->var.grayscale)
283                 red = green = blue = (19595*red + 38470*green + 7471*blue) >> 16;
284
285         switch (info->fix.visual) {
286                 case FB_VISUAL_TRUECOLOR:
287                         if (regno >= 16)
288                                 return -EINVAL;
289
290                         /* deal with creating pseudo-palette entries */
291
292                         pseudo_val  = (red   >> 11) << info->var.red.offset;
293                         pseudo_val |= (green >> 10) << info->var.green.offset;
294                         pseudo_val |= (blue  >> 11) << info->var.blue.offset;
295
296                         dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",
297                                     regno, pseudo_val);
298
299 #if defined(CONFIG_PLAT_MAPPI)
300                         ((u32 *)info->pseudo_palette)[regno] = cpu_to_le16(pseudo_val);
301 #else
302                         ((u32 *)info->pseudo_palette)[regno] = pseudo_val;
303 #endif
304
305                         break;
306                 case FB_VISUAL_PSEUDOCOLOR:
307                         s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_ADDR, regno);
308                         s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, red);
309                         s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, green);
310                         s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, blue);
311
312                         break;
313                 default:
314                         return -ENOSYS;
315         }
316
317         dbg("s1d13xxxfb_setcolreg: done\n");
318
319         return 0;
320 }
321
322 /**
323  *      s1d13xxxfb_blank - blanks the display.
324  *      @blank_mode: the blank mode we want.
325  *      @info: frame buffer structure that represents a single frame buffer
326  *
327  *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
328  *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
329  *      video mode which doesn't support it. Implements VESA suspend
330  *      and powerdown modes on hardware that supports disabling hsync/vsync:
331  *      blank_mode == 2: suspend vsync
332  *      blank_mode == 3: suspend hsync
333  *      blank_mode == 4: powerdown
334  *
335  *      Returns negative errno on error, or zero on success.
336  */
337 static int
338 s1d13xxxfb_blank(int blank_mode, struct fb_info *info)
339 {
340         struct s1d13xxxfb_par *par = info->par;
341
342         dbg("s1d13xxxfb_blank: blank=%d, info=%p\n", blank_mode, info);
343
344         switch (blank_mode) {
345                 case FB_BLANK_UNBLANK:
346                 case FB_BLANK_NORMAL:
347                         if ((par->display & 0x01) != 0)
348                                 lcd_enable(par, 1);
349                         if ((par->display & 0x02) != 0)
350                                 crt_enable(par, 1);
351                         break;
352                 case FB_BLANK_VSYNC_SUSPEND:
353                 case FB_BLANK_HSYNC_SUSPEND:
354                         break;
355                 case FB_BLANK_POWERDOWN:
356                         lcd_enable(par, 0);
357                         crt_enable(par, 0);
358                         break;
359                 default:
360                         return -EINVAL;
361         }
362
363         /* let fbcon do a soft blank for us */
364         return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
365 }
366
367 /**
368  *      s1d13xxxfb_pan_display - Pans the display.
369  *      @var: frame buffer variable screen structure
370  *      @info: frame buffer structure that represents a single frame buffer
371  *
372  *      Pan (or wrap, depending on the `vmode' field) the display using the
373  *      `yoffset' field of the `var' structure (`xoffset'  not yet supported).
374  *      If the values don't fit, return -EINVAL.
375  *
376  *      Returns negative errno on error, or zero on success.
377  */
378 static int
379 s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
380 {
381         struct s1d13xxxfb_par *par = info->par;
382         u32 start;
383
384         if (var->xoffset != 0)  /* not yet ... */
385                 return -EINVAL;
386
387         if (var->yoffset + info->var.yres > info->var.yres_virtual)
388                 return -EINVAL;
389
390         start = (info->fix.line_length >> 1) * var->yoffset;
391
392         if ((par->display & 0x01)) {
393                 /* LCD */
394                 s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START0, (start & 0xff));
395                 s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START1, ((start >> 8) & 0xff));
396                 s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START2, ((start >> 16) & 0x0f));
397         } else {
398                 /* CRT */
399                 s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START0, (start & 0xff));
400                 s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START1, ((start >> 8) & 0xff));
401                 s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START2, ((start >> 16) & 0x0f));
402         }
403
404         return 0;
405 }
406
407 /************************************************************
408  functions to handle bitblt acceleration
409  ************************************************************/
410
411 /**
412  *      bltbit_wait_bitclear - waits for change in register value
413  *      @info : frambuffer structure
414  *      @bit  : value currently in register
415  *      @timeout : ...
416  *
417  *      waits until value changes FROM bit
418  *
419  */
420 static u8
421 bltbit_wait_bitclear(struct fb_info *info, u8 bit, int timeout)
422 {
423         while (s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit) {
424                 udelay(10);
425                 if (!--timeout) {
426                         dbg_blit("wait_bitclear timeout\n");
427                         break;
428                 }
429         }
430
431         return timeout;
432 }
433
434 /*
435  *      s1d13xxxfb_bitblt_copyarea - accelerated copyarea function
436  *      @info : framebuffer structure
437  *      @area : fb_copyarea structure
438  *
439  *      supports (atleast) S1D13506
440  *
441  */
442 static void
443 s1d13xxxfb_bitblt_copyarea(struct fb_info *info, const struct fb_copyarea *area)
444 {
445         u32 dst, src;
446         u32 stride;
447         u16 reverse = 0;
448         u16 sx = area->sx, sy = area->sy;
449         u16 dx = area->dx, dy = area->dy;
450         u16 width = area->width, height = area->height;
451         u16 bpp;
452
453         spin_lock(&s1d13xxxfb_bitblt_lock);
454
455         /* bytes per xres line */
456         bpp = (info->var.bits_per_pixel >> 3);
457         stride = bpp * info->var.xres;
458
459         /* reverse, calculate the last pixel in rectangle */
460         if ((dy > sy) || ((dy == sy) && (dx >= sx))) {
461                 dst = (((dy + height - 1) * stride) + (bpp * (dx + width - 1)));
462                 src = (((sy + height - 1) * stride) + (bpp * (sx + width - 1)));
463                 reverse = 1;
464         /* not reverse, calculate the first pixel in rectangle */
465         } else { /* (y * xres) + (bpp * x) */
466                 dst = (dy * stride) + (bpp * dx);
467                 src = (sy * stride) + (bpp * sx);
468         }
469
470         /* set source address */
471         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff));
472         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff);
473         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff);
474
475         /* set destination address */
476         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff));
477         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff);
478         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff);
479
480         /* program height and width */
481         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, (width & 0xff) - 1);
482         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (width >> 8));
483
484         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, (height & 0xff) - 1);
485         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (height >> 8));
486
487         /* negative direction ROP */
488         if (reverse == 1) {
489                 dbg_blit("(copyarea) negative rop\n");
490                 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x03);
491         } else /* positive direction ROP */ {
492                 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x02);
493                 dbg_blit("(copyarea) positive rop\n");
494         }
495
496         /* set for rectangel mode and not linear */
497         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0);
498
499         /* setup the bpp 1 = 16bpp, 0 = 8bpp*/
500         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (bpp >> 1));
501
502         /* set words per xres */
503         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (stride >> 1) & 0xff);
504         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (stride >> 9));
505
506         dbg_blit("(copyarea) dx=%d, dy=%d\n", dx, dy);
507         dbg_blit("(copyarea) sx=%d, sy=%d\n", sx, sy);
508         dbg_blit("(copyarea) width=%d, height=%d\n", width - 1, height - 1);
509         dbg_blit("(copyarea) stride=%d\n", stride);
510         dbg_blit("(copyarea) bpp=%d=0x0%d, mem_offset1=%d, mem_offset2=%d\n", bpp, (bpp >> 1),
511                 (stride >> 1) & 0xff, stride >> 9);
512
513         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CC_EXP, 0x0c);
514
515         /* initialize the engine */
516         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80);
517
518         /* wait to complete */
519         bltbit_wait_bitclear(info, 0x80, 8000);
520
521         spin_unlock(&s1d13xxxfb_bitblt_lock);
522 }
523
524 /**
525  *
526  *      s1d13xxxfb_bitblt_solidfill - accelerated solidfill function
527  *      @info : framebuffer structure
528  *      @rect : fb_fillrect structure
529  *
530  *      supports (atleast 13506)
531  *
532  **/
533 static void
534 s1d13xxxfb_bitblt_solidfill(struct fb_info *info, const struct fb_fillrect *rect)
535 {
536         u32 screen_stride, dest;
537         u32 fg;
538         u16 bpp = (info->var.bits_per_pixel >> 3);
539
540         /* grab spinlock */
541         spin_lock(&s1d13xxxfb_bitblt_lock);
542
543         /* bytes per x width */
544         screen_stride = (bpp * info->var.xres);
545
546         /* bytes to starting point */
547         dest = ((rect->dy * screen_stride) + (bpp * rect->dx));
548
549         dbg_blit("(solidfill) dx=%d, dy=%d, stride=%d, dest=%d\n"
550                  "(solidfill) : rect_width=%d, rect_height=%d\n",
551                                 rect->dx, rect->dy, screen_stride, dest,
552                                 rect->width - 1, rect->height - 1);
553
554         dbg_blit("(solidfill) : xres=%d, yres=%d, bpp=%d\n",
555                                 info->var.xres, info->var.yres,
556                                 info->var.bits_per_pixel);
557         dbg_blit("(solidfill) : rop=%d\n", rect->rop);
558
559         /* We split the destination into the three registers */
560         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dest & 0x00ff));
561         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, ((dest >> 8) & 0x00ff));
562         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, ((dest >> 16) & 0x00ff));
563
564         /* give information regarding rectangel width */
565         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, ((rect->width) & 0x00ff) - 1);
566         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (rect->width >> 8));
567
568         /* give information regarding rectangel height */
569         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, ((rect->height) & 0x00ff) - 1);
570         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (rect->height >> 8));
571
572         if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
573                 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
574                 fg = ((u32 *)info->pseudo_palette)[rect->color];
575                 dbg_blit("(solidfill) truecolor/directcolor\n");
576                 dbg_blit("(solidfill) pseudo_palette[%d] = %d\n", rect->color, fg);
577         } else {
578                 fg = rect->color;
579                 dbg_blit("(solidfill) color = %d\n", rect->color);
580         }
581
582         /* set foreground color */
583         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC0, (fg & 0xff));
584         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC1, (fg >> 8) & 0xff);
585
586         /* set rectangual region of memory (rectangle and not linear) */
587         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0);
588
589         /* set operation mode SOLID_FILL */
590         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, BBLT_SOLID_FILL);
591
592         /* set bits per pixel (1 = 16bpp, 0 = 8bpp) */
593         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (info->var.bits_per_pixel >> 4));
594
595         /* set the memory offset for the bblt in word sizes */
596         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (screen_stride >> 1) & 0x00ff);
597         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (screen_stride >> 9));
598
599         /* and away we go.... */
600         s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80);
601
602         /* wait until its done */
603         bltbit_wait_bitclear(info, 0x80, 8000);
604
605         /* let others play */
606         spin_unlock(&s1d13xxxfb_bitblt_lock);
607 }
608
609 /* framebuffer information structures */
610 static struct fb_ops s1d13xxxfb_fbops = {
611         .owner          = THIS_MODULE,
612         .fb_set_par     = s1d13xxxfb_set_par,
613         .fb_setcolreg   = s1d13xxxfb_setcolreg,
614         .fb_blank       = s1d13xxxfb_blank,
615
616         .fb_pan_display = s1d13xxxfb_pan_display,
617
618         /* gets replaced at chip detection time */
619         .fb_fillrect    = cfb_fillrect,
620         .fb_copyarea    = cfb_copyarea,
621         .fb_imageblit   = cfb_imageblit,
622 };
623
624 static int s1d13xxxfb_width_tab[2][4] = {
625         {4, 8, 16, -1},
626         {9, 12, 18, -1},
627 };
628
629 /**
630  *      s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to
631  *      hardware setup.
632  *      @info: frame buffer structure
633  *
634  *      We setup the framebuffer structures according to the current
635  *      hardware setup. On some machines, the BIOS will have filled
636  *      the chip registers with such info, on others, these values will
637  *      have been written in some init procedure. In any case, the
638  *      software values needs to match the hardware ones. This is what
639  *      this function ensures.
640  *
641  *      Note: some of the hardcoded values here might need some love to
642  *      work on various chips, and might need to no longer be hardcoded.
643  */
644 static void s1d13xxxfb_fetch_hw_state(struct fb_info *info)
645 {
646         struct fb_var_screeninfo *var = &info->var;
647         struct fb_fix_screeninfo *fix = &info->fix;
648         struct s1d13xxxfb_par *par = info->par;
649         u8 panel, display;
650         u16 offset;
651         u32 xres, yres;
652         u32 xres_virtual, yres_virtual;
653         int bpp, lcd_bpp;
654         int is_color, is_dual, is_tft;
655         int lcd_enabled, crt_enabled;
656
657         fix->type = FB_TYPE_PACKED_PIXELS;
658
659         /* general info */
660         par->display = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
661         crt_enabled = (par->display & 0x02) != 0;
662         lcd_enabled = (par->display & 0x01) != 0;
663
664         if (lcd_enabled && crt_enabled)
665                 printk(KERN_WARNING PFX "Warning: LCD and CRT detected, using LCD\n");
666
667         if (lcd_enabled)
668                 display = s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_MODE);
669         else    /* CRT */
670                 display = s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_MODE);
671
672         bpp = display & 0x07;
673
674         switch (bpp) {
675                 case 2: /* 4 bpp */
676                 case 3: /* 8 bpp */
677                         var->bits_per_pixel = 8;
678                         var->red.offset = var->green.offset = var->blue.offset = 0;
679                         var->red.length = var->green.length = var->blue.length = 8;
680                         break;
681                 case 5: /* 16 bpp */
682                         s1d13xxxfb_setup_truecolour(info);
683                         break;
684                 default:
685                         dbg("bpp: %i\n", bpp);
686         }
687         fb_alloc_cmap(&info->cmap, 256, 0);
688
689         /* LCD info */
690         panel = s1d13xxxfb_readreg(par, S1DREG_PANEL_TYPE);
691         is_color = (panel & 0x04) != 0;
692         is_dual = (panel & 0x02) != 0;
693         is_tft = (panel & 0x01) != 0;
694         lcd_bpp = s1d13xxxfb_width_tab[is_tft][(panel >> 4) & 3];
695
696         if (lcd_enabled) {
697                 xres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_HWIDTH) + 1) * 8;
698                 yres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT0) +
699                         ((s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT1) & 0x03) << 8) + 1);
700
701                 offset = (s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF0) +
702                         ((s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF1) & 0x7) << 8));
703         } else { /* crt */
704                 xres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_HWIDTH) + 1) * 8;
705                 yres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT0) +
706                         ((s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT1) & 0x03) << 8) + 1);
707
708                 offset = (s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF0) +
709                         ((s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF1) & 0x7) << 8));
710         }
711         xres_virtual = offset * 16 / var->bits_per_pixel;
712         yres_virtual = fix->smem_len / (offset * 2);
713
714         var->xres               = xres;
715         var->yres               = yres;
716         var->xres_virtual       = xres_virtual;
717         var->yres_virtual       = yres_virtual;
718         var->xoffset            = var->yoffset = 0;
719
720         fix->line_length        = offset * 2;
721
722         var->grayscale          = !is_color;
723
724         var->activate           = FB_ACTIVATE_NOW;
725
726         dbg(PFX "bpp=%d, lcd_bpp=%d, "
727                 "crt_enabled=%d, lcd_enabled=%d\n",
728                 var->bits_per_pixel, lcd_bpp, crt_enabled, lcd_enabled);
729         dbg(PFX "xres=%d, yres=%d, vxres=%d, vyres=%d "
730                 "is_color=%d, is_dual=%d, is_tft=%d\n",
731                 xres, yres, xres_virtual, yres_virtual, is_color, is_dual, is_tft);
732 }
733
734
735 static int
736 s1d13xxxfb_remove(struct platform_device *pdev)
737 {
738         struct fb_info *info = platform_get_drvdata(pdev);
739         struct s1d13xxxfb_par *par = NULL;
740
741         if (info) {
742                 par = info->par;
743                 if (par && par->regs) {
744                         /* disable output & enable powersave */
745                         s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, 0x00);
746                         s1d13xxxfb_writereg(par, S1DREG_PS_CNF, 0x11);
747                         iounmap(par->regs);
748                 }
749
750                 fb_dealloc_cmap(&info->cmap);
751
752                 if (info->screen_base)
753                         iounmap(info->screen_base);
754
755                 framebuffer_release(info);
756         }
757
758         release_mem_region(pdev->resource[0].start,
759                         pdev->resource[0].end - pdev->resource[0].start +1);
760         release_mem_region(pdev->resource[1].start,
761                         pdev->resource[1].end - pdev->resource[1].start +1);
762         return 0;
763 }
764
765 static int s1d13xxxfb_probe(struct platform_device *pdev)
766 {
767         struct s1d13xxxfb_par *default_par;
768         struct fb_info *info;
769         struct s1d13xxxfb_pdata *pdata = NULL;
770         int ret = 0;
771         int i;
772         u8 revision, prod_id;
773
774         dbg("probe called: device is %p\n", pdev);
775
776         printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
777
778         /* enable platform-dependent hardware glue, if any */
779         if (dev_get_platdata(&pdev->dev))
780                 pdata = dev_get_platdata(&pdev->dev);
781
782         if (pdata && pdata->platform_init_video)
783                 pdata->platform_init_video();
784
785         if (pdev->num_resources != 2) {
786                 dev_err(&pdev->dev, "invalid num_resources: %i\n",
787                        pdev->num_resources);
788                 ret = -ENODEV;
789                 goto bail;
790         }
791
792         /* resource[0] is VRAM, resource[1] is registers */
793         if (pdev->resource[0].flags != IORESOURCE_MEM
794                         || pdev->resource[1].flags != IORESOURCE_MEM) {
795                 dev_err(&pdev->dev, "invalid resource type\n");
796                 ret = -ENODEV;
797                 goto bail;
798         }
799
800         if (!request_mem_region(pdev->resource[0].start,
801                 pdev->resource[0].end - pdev->resource[0].start +1, "s1d13xxxfb mem")) {
802                 dev_dbg(&pdev->dev, "request_mem_region failed\n");
803                 ret = -EBUSY;
804                 goto bail;
805         }
806
807         if (!request_mem_region(pdev->resource[1].start,
808                 pdev->resource[1].end - pdev->resource[1].start +1, "s1d13xxxfb regs")) {
809                 dev_dbg(&pdev->dev, "request_mem_region failed\n");
810                 ret = -EBUSY;
811                 goto bail;
812         }
813
814         info = framebuffer_alloc(sizeof(struct s1d13xxxfb_par) + sizeof(u32) * 256, &pdev->dev);
815         if (!info) {
816                 ret = -ENOMEM;
817                 goto bail;
818         }
819
820         platform_set_drvdata(pdev, info);
821         default_par = info->par;
822         default_par->regs = ioremap_nocache(pdev->resource[1].start,
823                         pdev->resource[1].end - pdev->resource[1].start +1);
824         if (!default_par->regs) {
825                 printk(KERN_ERR PFX "unable to map registers\n");
826                 ret = -ENOMEM;
827                 goto bail;
828         }
829         info->pseudo_palette = default_par->pseudo_palette;
830
831         info->screen_base = ioremap_nocache(pdev->resource[0].start,
832                         pdev->resource[0].end - pdev->resource[0].start +1);
833
834         if (!info->screen_base) {
835                 printk(KERN_ERR PFX "unable to map framebuffer\n");
836                 ret = -ENOMEM;
837                 goto bail;
838         }
839
840         /* production id is top 6 bits */
841         prod_id = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
842         /* revision id is lower 2 bits */
843         revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) & 0x3;
844         ret = -ENODEV;
845
846         for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_prod_ids); i++) {
847                 if (prod_id == s1d13xxxfb_prod_ids[i]) {
848                         /* looks like we got it in our list */
849                         default_par->prod_id = prod_id;
850                         default_par->revision = revision;
851                         ret = 0;
852                         break;
853                 }
854         }
855
856         if (!ret) {
857                 printk(KERN_INFO PFX "chip production id %i = %s\n",
858                         prod_id, s1d13xxxfb_prod_names[i]);
859                 printk(KERN_INFO PFX "chip revision %i\n", revision);
860         } else {
861                 printk(KERN_INFO PFX
862                         "unknown chip production id %i, revision %i\n",
863                         prod_id, revision);
864                 printk(KERN_INFO PFX "please contact maintainer\n");
865                 goto bail;
866         }
867
868         info->fix = s1d13xxxfb_fix;
869         info->fix.mmio_start = pdev->resource[1].start;
870         info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start + 1;
871         info->fix.smem_start = pdev->resource[0].start;
872         info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start + 1;
873
874         printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n",
875                default_par->regs, info->fix.smem_len / 1024, info->screen_base);
876
877         info->par = default_par;
878         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
879         info->fbops = &s1d13xxxfb_fbops;
880
881         switch(prod_id) {
882         case S1D13506_PROD_ID:  /* activate acceleration */
883                 s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill;
884                 s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea;
885                 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
886                         FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
887                 break;
888         default:
889                 break;
890         }
891
892         /* perform "manual" chip initialization, if needed */
893         if (pdata && pdata->initregs)
894                 s1d13xxxfb_runinit(info->par, pdata->initregs, pdata->initregssize);
895
896         s1d13xxxfb_fetch_hw_state(info);
897
898         if (register_framebuffer(info) < 0) {
899                 ret = -EINVAL;
900                 goto bail;
901         }
902
903         fb_info(info, "%s frame buffer device\n", info->fix.id);
904
905         return 0;
906
907 bail:
908         s1d13xxxfb_remove(pdev);
909         return ret;
910
911 }
912
913 #ifdef CONFIG_PM
914 static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state)
915 {
916         struct fb_info *info = platform_get_drvdata(dev);
917         struct s1d13xxxfb_par *s1dfb = info->par;
918         struct s1d13xxxfb_pdata *pdata = NULL;
919
920         /* disable display */
921         lcd_enable(s1dfb, 0);
922         crt_enable(s1dfb, 0);
923
924         if (dev_get_platdata(&dev->dev))
925                 pdata = dev_get_platdata(&dev->dev);
926
927 #if 0
928         if (!s1dfb->disp_save)
929                 s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL);
930
931         if (!s1dfb->disp_save) {
932                 printk(KERN_ERR PFX "no memory to save screen");
933                 return -ENOMEM;
934         }
935
936         memcpy_fromio(s1dfb->disp_save, info->screen_base, info->fix.smem_len);
937 #else
938         s1dfb->disp_save = NULL;
939 #endif
940
941         if (!s1dfb->regs_save)
942                 s1dfb->regs_save = kmalloc(info->fix.mmio_len, GFP_KERNEL);
943
944         if (!s1dfb->regs_save) {
945                 printk(KERN_ERR PFX "no memory to save registers");
946                 return -ENOMEM;
947         }
948
949         /* backup all registers */
950         memcpy_fromio(s1dfb->regs_save, s1dfb->regs, info->fix.mmio_len);
951
952         /* now activate power save mode */
953         s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x11);
954
955         if (pdata && pdata->platform_suspend_video)
956                 return pdata->platform_suspend_video();
957         else
958                 return 0;
959 }
960
961 static int s1d13xxxfb_resume(struct platform_device *dev)
962 {
963         struct fb_info *info = platform_get_drvdata(dev);
964         struct s1d13xxxfb_par *s1dfb = info->par;
965         struct s1d13xxxfb_pdata *pdata = NULL;
966
967         /* awaken the chip */
968         s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
969
970         /* do not let go until SDRAM "wakes up" */
971         while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01))
972                 udelay(10);
973
974         if (dev_get_platdata(&dev->dev))
975                 pdata = dev_get_platdata(&dev->dev);
976
977         if (s1dfb->regs_save) {
978                 /* will write RO regs, *should* get away with it :) */
979                 memcpy_toio(s1dfb->regs, s1dfb->regs_save, info->fix.mmio_len);
980                 kfree(s1dfb->regs_save);
981         }
982
983         if (s1dfb->disp_save) {
984                 memcpy_toio(info->screen_base, s1dfb->disp_save,
985                                 info->fix.smem_len);
986                 kfree(s1dfb->disp_save);        /* XXX kmalloc()'d when? */
987         }
988
989         if ((s1dfb->display & 0x01) != 0)
990                 lcd_enable(s1dfb, 1);
991         if ((s1dfb->display & 0x02) != 0)
992                 crt_enable(s1dfb, 1);
993
994         if (pdata && pdata->platform_resume_video)
995                 return pdata->platform_resume_video();
996         else
997                 return 0;
998 }
999 #endif /* CONFIG_PM */
1000
1001 static struct platform_driver s1d13xxxfb_driver = {
1002         .probe          = s1d13xxxfb_probe,
1003         .remove         = s1d13xxxfb_remove,
1004 #ifdef CONFIG_PM
1005         .suspend        = s1d13xxxfb_suspend,
1006         .resume         = s1d13xxxfb_resume,
1007 #endif
1008         .driver         = {
1009                 .name   = S1D_DEVICENAME,
1010         },
1011 };
1012
1013
1014 static int __init
1015 s1d13xxxfb_init(void)
1016 {
1017
1018 #ifndef MODULE
1019         if (fb_get_options("s1d13xxxfb", NULL))
1020                 return -ENODEV;
1021 #endif
1022
1023         return platform_driver_register(&s1d13xxxfb_driver);
1024 }
1025
1026
1027 static void __exit
1028 s1d13xxxfb_exit(void)
1029 {
1030         platform_driver_unregister(&s1d13xxxfb_driver);
1031 }
1032
1033 module_init(s1d13xxxfb_init);
1034 module_exit(s1d13xxxfb_exit);
1035
1036
1037 MODULE_LICENSE("GPL");
1038 MODULE_DESCRIPTION("Framebuffer driver for S1D13xxx devices");
1039 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Thibaut VARENE <varenet@parisc-linux.org>");