[PATCH] mark struct file_operations const 6
[linux-2.6] / drivers / video / mbx / mbxfb.c
1 /*
2  *  linux/drivers/video/mbx/mbxfb.c
3  *
4  *  Copyright (C) 2006 8D Technologies inc
5  *  Raphael Assenat <raph@8d.com>
6  *      - Added video overlay support
7  *      - Various improvements
8  *
9  *  Copyright (C) 2006 Compulab, Ltd.
10  *  Mike Rapoport <mike@compulab.co.il>
11  *      - Creation of driver
12  *
13  *   Based on pxafb.c
14  *
15  * This file is subject to the terms and conditions of the GNU General Public
16  * License.  See the file COPYING in the main directory of this archive for
17  * more details.
18  *
19  *   Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver
20  *
21  */
22
23 #include <linux/delay.h>
24 #include <linux/fb.h>
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/uaccess.h>
29
30 #include <asm/io.h>
31
32 #include <video/mbxfb.h>
33
34 #include "regs.h"
35 #include "reg_bits.h"
36
37 static unsigned long virt_base_2700;
38
39 #define write_reg(val, reg) do { writel((val), (reg)); } while(0)
40
41 /* Without this delay, the graphics appears somehow scaled and
42  * there is a lot of jitter in scanlines. This delay is probably
43  * needed only after setting some specific register(s) somewhere,
44  * not all over the place... */
45 #define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0)
46
47 #define MIN_XRES        16
48 #define MIN_YRES        16
49 #define MAX_XRES        2048
50 #define MAX_YRES        2048
51
52 #define MAX_PALETTES    16
53
54 /* FIXME: take care of different chip revisions with different sizes
55    of ODFB */
56 #define MEMORY_OFFSET   0x60000
57
58 struct mbxfb_info {
59         struct device *dev;
60
61         struct resource *fb_res;
62         struct resource *fb_req;
63
64         struct resource *reg_res;
65         struct resource *reg_req;
66
67         void __iomem *fb_virt_addr;
68         unsigned long fb_phys_addr;
69
70         void __iomem *reg_virt_addr;
71         unsigned long reg_phys_addr;
72
73         int (*platform_probe) (struct fb_info * fb);
74         int (*platform_remove) (struct fb_info * fb);
75
76         u32 pseudo_palette[MAX_PALETTES];
77 #ifdef CONFIG_FB_MBX_DEBUG
78         void *debugfs_data;
79 #endif
80
81 };
82
83 static struct fb_var_screeninfo mbxfb_default __devinitdata = {
84         .xres = 640,
85         .yres = 480,
86         .xres_virtual = 640,
87         .yres_virtual = 480,
88         .bits_per_pixel = 16,
89         .red = {11, 5, 0},
90         .green = {5, 6, 0},
91         .blue = {0, 5, 0},
92         .activate = FB_ACTIVATE_TEST,
93         .height = -1,
94         .width = -1,
95         .pixclock = 40000,
96         .left_margin = 48,
97         .right_margin = 16,
98         .upper_margin = 33,
99         .lower_margin = 10,
100         .hsync_len = 96,
101         .vsync_len = 2,
102         .vmode = FB_VMODE_NONINTERLACED,
103         .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
104 };
105
106 static struct fb_fix_screeninfo mbxfb_fix  __devinitdata = {
107         .id = "MBX",
108         .type = FB_TYPE_PACKED_PIXELS,
109         .visual = FB_VISUAL_TRUECOLOR,
110         .xpanstep = 0,
111         .ypanstep = 0,
112         .ywrapstep = 0,
113         .accel = FB_ACCEL_NONE,
114 };
115
116 struct pixclock_div {
117         u8 m;
118         u8 n;
119         u8 p;
120 };
121
122 static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps,
123                                        struct pixclock_div *div)
124 {
125         u8 m, n, p;
126         unsigned int err = 0;
127         unsigned int min_err = ~0x0;
128         unsigned int clk;
129         unsigned int best_clk = 0;
130         unsigned int ref_clk = 13000;   /* FIXME: take from platform data */
131         unsigned int pixclock;
132
133         /* convert pixclock to KHz */
134         pixclock = PICOS2KHZ(pixclock_ps);
135
136         /* PLL output freq = (ref_clk * M) / (N * 2^P)
137          *
138          * M: 1 to 63
139          * N: 1 to 7
140          * P: 0 to 7
141          */
142
143         /* RAPH: When N==1, the resulting pixel clock appears to
144          * get divided by 2. Preventing N=1 by starting the following
145          * loop at 2 prevents this. Is this a bug with my chip
146          * revision or something I dont understand? */
147         for (m = 1; m < 64; m++) {
148                 for (n = 2; n < 8; n++) {
149                         for (p = 0; p < 8; p++) {
150                                 clk = (ref_clk * m) / (n * (1 << p));
151                                 err = (clk > pixclock) ? (clk - pixclock) :
152                                         (pixclock - clk);
153                                 if (err < min_err) {
154                                         min_err = err;
155                                         best_clk = clk;
156                                         div->m = m;
157                                         div->n = n;
158                                         div->p = p;
159                                 }
160                         }
161                 }
162         }
163         return KHZ2PICOS(best_clk);
164 }
165
166 static int mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
167                            u_int trans, struct fb_info *info)
168 {
169         u32 val, ret = 1;
170
171         if (regno < MAX_PALETTES) {
172                 u32 *pal = info->pseudo_palette;
173
174                 val = (red & 0xf800) | ((green & 0xfc00) >> 5) |
175                         ((blue & 0xf800) >> 11);
176                 pal[regno] = val;
177                 ret = 0;
178         }
179
180         return ret;
181 }
182
183 static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
184 {
185         struct pixclock_div div;
186
187         var->pixclock = mbxfb_get_pixclock(var->pixclock, &div);
188
189         if (var->xres < MIN_XRES)
190                 var->xres = MIN_XRES;
191         if (var->yres < MIN_YRES)
192                 var->yres = MIN_YRES;
193         if (var->xres > MAX_XRES)
194                 return -EINVAL;
195         if (var->yres > MAX_YRES)
196                 return -EINVAL;
197         var->xres_virtual = max(var->xres_virtual, var->xres);
198         var->yres_virtual = max(var->yres_virtual, var->yres);
199
200         switch (var->bits_per_pixel) {
201                 /* 8 bits-per-pixel is not supported yet */
202         case 8:
203                 return -EINVAL;
204         case 16:
205                 var->green.length = (var->green.length == 5) ? 5 : 6;
206                 var->red.length = 5;
207                 var->blue.length = 5;
208                 var->transp.length = 6 - var->green.length;
209                 var->blue.offset = 0;
210                 var->green.offset = 5;
211                 var->red.offset = 5 + var->green.length;
212                 var->transp.offset = (5 + var->red.offset) & 15;
213                 break;
214         case 24:                /* RGB 888   */
215         case 32:                /* RGBA 8888 */
216                 var->red.offset = 16;
217                 var->red.length = 8;
218                 var->green.offset = 8;
219                 var->green.length = 8;
220                 var->blue.offset = 0;
221                 var->blue.length = 8;
222                 var->transp.length = var->bits_per_pixel - 24;
223                 var->transp.offset = (var->transp.length) ? 24 : 0;
224                 break;
225         }
226         var->red.msb_right = 0;
227         var->green.msb_right = 0;
228         var->blue.msb_right = 0;
229         var->transp.msb_right = 0;
230
231         return 0;
232 }
233
234 static int mbxfb_set_par(struct fb_info *info)
235 {
236         struct fb_var_screeninfo *var = &info->var;
237         struct pixclock_div div;
238         ushort hbps, ht, hfps, has;
239         ushort vbps, vt, vfps, vas;
240         u32 gsctrl = readl(GSCTRL);
241         u32 gsadr = readl(GSADR);
242
243         info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
244
245         /* setup color mode */
246         gsctrl &= ~(FMsk(GSCTRL_GPIXFMT));
247         /* FIXME: add *WORKING* support for 8-bits per color */
248         if (info->var.bits_per_pixel == 8) {
249                 return -EINVAL;
250         } else {
251                 fb_dealloc_cmap(&info->cmap);
252                 gsctrl &= ~GSCTRL_LUT_EN;
253
254                 info->fix.visual = FB_VISUAL_TRUECOLOR;
255                 switch (info->var.bits_per_pixel) {
256                 case 16:
257                         if (info->var.green.length == 5)
258                                 gsctrl |= GSCTRL_GPIXFMT_ARGB1555;
259                         else
260                                 gsctrl |= GSCTRL_GPIXFMT_RGB565;
261                         break;
262                 case 24:
263                         gsctrl |= GSCTRL_GPIXFMT_RGB888;
264                         break;
265                 case 32:
266                         gsctrl |= GSCTRL_GPIXFMT_ARGB8888;
267                         break;
268                 }
269         }
270
271         /* setup resolution */
272         gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT));
273         gsctrl |= Gsctrl_Width(info->var.xres) |
274                 Gsctrl_Height(info->var.yres);
275         write_reg_dly(gsctrl, GSCTRL);
276
277         gsadr &= ~(FMsk(GSADR_SRCSTRIDE));
278         gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel /
279                                  (8 * 16) - 1);
280         write_reg_dly(gsadr, GSADR);
281
282         /* setup timings */
283         var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div);
284
285         write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
286                 Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL);
287
288         hbps = var->hsync_len;
289         has = hbps + var->left_margin;
290         hfps = has + var->xres;
291         ht = hfps + var->right_margin;
292
293         vbps = var->vsync_len;
294         vas = vbps + var->upper_margin;
295         vfps = vas + var->yres;
296         vt = vfps + var->lower_margin;
297
298         write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
299         write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
300         write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
301         write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
302
303         write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
304         write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
305         write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
306         write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
307         write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
308
309         write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
310
311         write_reg_dly(DINTRE_VEVENT0_EN, DINTRE);
312
313         return 0;
314 }
315
316 static int mbxfb_blank(int blank, struct fb_info *info)
317 {
318         switch (blank) {
319         case FB_BLANK_POWERDOWN:
320         case FB_BLANK_VSYNC_SUSPEND:
321         case FB_BLANK_HSYNC_SUSPEND:
322         case FB_BLANK_NORMAL:
323                 write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
324                 write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
325                 write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
326                 break;
327         case FB_BLANK_UNBLANK:
328                 write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
329                 write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
330                 break;
331         }
332         return 0;
333 }
334
335 static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
336 {
337         u32 vsctrl, vbbase, vscadr, vsadr;
338         u32 sssize, spoctrl, svctrl, shctrl;
339         u32 vubase, vvbase;
340         u32 vovrclk;
341
342         if (set->scaled_width==0 || set->scaled_height==0)
343                 return -EINVAL;
344
345         /* read registers which have reserved bits
346          * so we can write them back as-is. */
347         vovrclk = readl(VOVRCLK);
348         vsctrl = readl(VSCTRL);
349         vscadr = readl(VSCADR);
350         vubase = readl(VUBASE);
351         vvbase = readl(VVBASE);
352
353         spoctrl = readl(SPOCTRL);
354         sssize = readl(SSSIZE);
355
356
357         vbbase = Vbbase_Glalpha(set->alpha);
358
359         vsctrl &= ~(    FMsk(VSCTRL_VSWIDTH) |
360                                         FMsk(VSCTRL_VSHEIGHT) |
361                                         FMsk(VSCTRL_VPIXFMT) |
362                                         VSCTRL_GAMMA_EN | VSCTRL_CSC_EN |
363                                         VSCTRL_COSITED );
364         vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) |
365                                 VSCTRL_CSC_EN;
366
367         vscadr &= ~(VSCADR_STR_EN | VSCADR_COLKEY_EN | VSCADR_COLKEYSRC |
368                                 FMsk(VSCADR_BLEND_M) | FMsk(VSCADR_BLEND_POS) |
369                                 FMsk(VSCADR_VBASE_ADR) );
370         vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR));
371         vvbase &= ~(FMsk(VVBASE_VBASE_ADR));
372
373         switch (set->fmt)
374         {
375                 case MBXFB_FMT_YUV12:
376                         vsctrl |= VSCTRL_VPIXFMT_YUV12;
377
378                         set->Y_stride = ((set->width) + 0xf ) & ~0xf;
379
380                         break;
381                 case MBXFB_FMT_UY0VY1:
382                         vsctrl |= VSCTRL_VPIXFMT_UY0VY1;
383                         set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
384                         break;
385                 case MBXFB_FMT_VY0UY1:
386                         vsctrl |= VSCTRL_VPIXFMT_VY0UY1;
387                         set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
388                         break;
389                 case MBXFB_FMT_Y0UY1V:
390                         vsctrl |= VSCTRL_VPIXFMT_Y0UY1V;
391                         set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
392                         break;
393                 case MBXFB_FMT_Y0VY1U:
394                         vsctrl |= VSCTRL_VPIXFMT_Y0VY1U;
395                         set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
396                         break;
397                 default:
398                         return -EINVAL;
399         }
400
401         /* VSCTRL has the bits which sets the Video Pixel Format.
402          * When passing from a packed to planar format,
403          * if we write VSCTRL first, VVBASE and VUBASE would
404          * be zero if we would not set them here. (And then,
405          * the chips hangs and only a reset seems to fix it).
406          *
407          * If course, the values calculated here have no meaning
408          * for packed formats.
409          */
410         set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7;
411                 set->U_offset = set->height * set->Y_stride;
412                 set->V_offset = set->U_offset +
413                                                 set->height * set->UV_stride;
414         vubase |= Vubase_Ubase_Adr(
415                         (0x60000 + set->mem_offset + set->U_offset)>>3);
416         vvbase |= Vvbase_Vbase_Adr(
417                         (0x60000 + set->mem_offset + set->V_offset)>>3);
418
419
420         vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_GLOB |
421                 Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4);
422
423         if (set->enable)
424                 vscadr |= VSCADR_STR_EN;
425
426
427         vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) |
428                 Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y);
429
430         sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT));
431         sssize = Sssize_Sc_Width(set->scaled_width-1) |
432                         Sssize_Sc_Height(set->scaled_height-1);
433
434         spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP |
435                         SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C |
436                         FMsk(SPOCTRL_VORDER) | FMsk(SPOCTRL_VPITCH));
437         spoctrl = Spoctrl_Vpitch((set->height<<11)/set->scaled_height)
438                                                         | SPOCTRL_VORDER_2TAP;
439
440         /* Bypass horiz/vert scaler when same size */
441         if (set->scaled_width == set->width)
442                 spoctrl |= SPOCTRL_H_SC_BP;
443         if (set->scaled_height == set->height)
444                 spoctrl |= SPOCTRL_V_SC_BP;
445
446         svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
447
448         shctrl = Shctrl_Hinitial(4<<11)
449                         | Shctrl_Hpitch((set->width<<11)/set->scaled_width);
450
451         /* Video plane registers */
452         write_reg(vsctrl, VSCTRL);
453         write_reg(vbbase, VBBASE);
454         write_reg(vscadr, VSCADR);
455         write_reg(vubase, VUBASE);
456         write_reg(vvbase, VVBASE);
457         write_reg(vsadr, VSADR);
458
459         /* Video scaler registers */
460         write_reg(sssize, SSSIZE);
461         write_reg(spoctrl, SPOCTRL);
462         write_reg(svctrl, SVCTRL);
463         write_reg(shctrl, SHCTRL);
464
465         /* RAPH: Using those coefficients, the scaled
466          * image is quite blurry. I dont know how
467          * to improve them ; The chip documentation
468          * was not helpful.. */
469         write_reg(0x21212121, VSCOEFF0);
470         write_reg(0x21212121, VSCOEFF1);
471         write_reg(0x21212121, VSCOEFF2);
472         write_reg(0x21212121, VSCOEFF3);
473         write_reg(0x21212121, VSCOEFF4);
474         write_reg(0x00000000, HSCOEFF0);
475         write_reg(0x00000000, HSCOEFF1);
476         write_reg(0x00000000, HSCOEFF2);
477         write_reg(0x03020201, HSCOEFF3);
478         write_reg(0x09070604, HSCOEFF4);
479         write_reg(0x0f0e0c0a, HSCOEFF5);
480         write_reg(0x15141211, HSCOEFF6);
481         write_reg(0x19181716, HSCOEFF7);
482         write_reg(0x00000019, HSCOEFF8);
483
484         /* Clock */
485         if (set->enable)
486                 vovrclk |= 1;
487         else
488                 vovrclk &= ~1;
489
490         write_reg(vovrclk, VOVRCLK);
491
492         return 0;
493 }
494
495 static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd,
496                                 unsigned long arg)
497 {
498         struct mbxfb_overlaySetup setup;
499         int res;
500
501         if (cmd == MBXFB_IOCX_OVERLAY)
502         {
503                 if (copy_from_user(&setup, (void __user*)arg,
504                                         sizeof(struct mbxfb_overlaySetup)))
505                         return -EFAULT;
506
507                 res = mbxfb_setupOverlay(&setup);
508                 if (res)
509                         return res;
510
511                 if (copy_to_user((void __user*)arg, &setup,
512                                         sizeof(struct mbxfb_overlaySetup)))
513                         return -EFAULT;
514
515                 return 0;
516         }
517         return -EINVAL;
518 }
519
520 static struct fb_ops mbxfb_ops = {
521         .owner = THIS_MODULE,
522         .fb_check_var = mbxfb_check_var,
523         .fb_set_par = mbxfb_set_par,
524         .fb_setcolreg = mbxfb_setcolreg,
525         .fb_fillrect = cfb_fillrect,
526         .fb_copyarea = cfb_copyarea,
527         .fb_imageblit = cfb_imageblit,
528         .fb_blank = mbxfb_blank,
529         .fb_ioctl = mbxfb_ioctl,
530 };
531
532 /*
533   Enable external SDRAM controller. Assume that all clocks are active
534   by now.
535 */
536 static void __devinit setup_memc(struct fb_info *fbi)
537 {
538         unsigned long tmp;
539         int i;
540
541         /* FIXME: use platfrom specific parameters */
542         /* setup SDRAM controller */
543         write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
544                 LMCFG_LMA_TS),
545                LMCFG);
546
547         write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
548
549         /* setup SDRAM timings */
550         write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
551                 Lmtim_Trc(9) | Lmtim_Tdpl(2)),
552                LMTIM);
553         /* setup SDRAM refresh rate */
554         write_reg_dly(0xc2b, LMREFRESH);
555         /* setup SDRAM type parameters */
556         write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
557                 LMTYPE_COLSZ_8),
558                LMTYPE);
559         /* enable memory controller */
560         write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
561
562         /* perform dummy reads */
563         for ( i = 0; i < 16; i++ ) {
564                 tmp = readl(fbi->screen_base);
565         }
566 }
567
568 static void enable_clocks(struct fb_info *fbi)
569 {
570         /* enable clocks */
571         write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC);
572         write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC);
573         write_reg_dly(0x00000000, CLKSLEEP);
574
575         /* PLL output = (Frefclk * M) / (N * 2^P )
576          *
577          * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz!
578          * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz
579          * */
580         write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) |
581                 CORE_PLL_EN),
582                COREPLL);
583
584         write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
585                 DISP_PLL_EN),
586                DISPPLL);
587
588         write_reg_dly(0x00000000, VOVRCLK);
589         write_reg_dly(PIXCLK_EN, PIXCLK);
590         write_reg_dly(MEMCLK_EN, MEMCLK);
591         write_reg_dly(0x00000006, M24CLK);
592         write_reg_dly(0x00000006, MBXCLK);
593         write_reg_dly(SDCLK_EN, SDCLK);
594         write_reg_dly(0x00000001, PIXCLKDIV);
595 }
596
597 static void __devinit setup_graphics(struct fb_info *fbi)
598 {
599         unsigned long gsctrl;
600
601         gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres) |
602                 Gsctrl_Height(fbi->var.yres);
603         switch (fbi->var.bits_per_pixel) {
604         case 16:
605                 if (fbi->var.green.length == 5)
606                         gsctrl |= GSCTRL_GPIXFMT_ARGB1555;
607                 else
608                         gsctrl |= GSCTRL_GPIXFMT_RGB565;
609                 break;
610         case 24:
611                 gsctrl |= GSCTRL_GPIXFMT_RGB888;
612                 break;
613         case 32:
614                 gsctrl |= GSCTRL_GPIXFMT_ARGB8888;
615                 break;
616         }
617
618         write_reg_dly(gsctrl, GSCTRL);
619         write_reg_dly(0x00000000, GBBASE);
620         write_reg_dly(0x00ffffff, GDRCTRL);
621         write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
622         write_reg_dly(0x00000000, GPLUT);
623 }
624
625 static void __devinit setup_display(struct fb_info *fbi)
626 {
627         unsigned long dsctrl = 0;
628
629         dsctrl = DSCTRL_BLNK_POL;
630         if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
631                 dsctrl |= DSCTRL_HS_POL;
632         if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
633                 dsctrl |= DSCTRL_VS_POL;
634         write_reg_dly(dsctrl, DSCTRL);
635         write_reg_dly(0xd0303010, DMCTRL);
636         write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
637 }
638
639 static void __devinit enable_controller(struct fb_info *fbi)
640 {
641         write_reg_dly(SYSRST_RST, SYSRST);
642
643
644         enable_clocks(fbi);
645         setup_memc(fbi);
646         setup_graphics(fbi);
647         setup_display(fbi);
648 }
649
650 #ifdef CONFIG_PM
651 /*
652  * Power management hooks.  Note that we won't be called from IRQ context,
653  * unlike the blank functions above, so we may sleep.
654  */
655 static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
656 {
657         /* make frame buffer memory enter self-refresh mode */
658         write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
659         while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM)
660                 ; /* empty statement */
661
662         /* reset the device, since it's initial state is 'mostly sleeping' */
663         write_reg_dly(SYSRST_RST, SYSRST);
664         return 0;
665 }
666
667 static int mbxfb_resume(struct platform_device *dev)
668 {
669         struct fb_info *fbi = platform_get_drvdata(dev);
670
671         enable_clocks(fbi);
672 /*      setup_graphics(fbi); */
673 /*      setup_display(fbi); */
674
675         write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
676         return 0;
677 }
678 #else
679 #define mbxfb_suspend   NULL
680 #define mbxfb_resume    NULL
681 #endif
682
683 /* debugfs entries */
684 #ifndef CONFIG_FB_MBX_DEBUG
685 #define mbxfb_debugfs_init(x)   do {} while(0)
686 #define mbxfb_debugfs_remove(x) do {} while(0)
687 #endif
688
689 #define res_size(_r) (((_r)->end - (_r)->start) + 1)
690
691 static int __devinit mbxfb_probe(struct platform_device *dev)
692 {
693         int ret;
694         struct fb_info *fbi;
695         struct mbxfb_info *mfbi;
696         struct mbxfb_platform_data *pdata;
697
698         dev_dbg(dev, "mbxfb_probe\n");
699
700         pdata = dev->dev.platform_data;
701         if (!pdata) {
702                 dev_err(&dev->dev, "platform data is required\n");
703                 return -EINVAL;
704         }
705
706         fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev);
707         if (fbi == NULL) {
708                 dev_err(&dev->dev, "framebuffer_alloc failed\n");
709                 return -ENOMEM;
710         }
711
712         mfbi = fbi->par;
713         fbi->pseudo_palette = mfbi->pseudo_palette;
714
715
716         if (pdata->probe)
717                 mfbi->platform_probe = pdata->probe;
718         if (pdata->remove)
719                 mfbi->platform_remove = pdata->remove;
720
721         mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
722         mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
723
724         if (!mfbi->fb_res || !mfbi->reg_res) {
725                 dev_err(&dev->dev, "no resources found\n");
726                 ret = -ENODEV;
727                 goto err1;
728         }
729
730         mfbi->fb_req = request_mem_region(mfbi->fb_res->start,
731                                           res_size(mfbi->fb_res), dev->name);
732         if (mfbi->fb_req == NULL) {
733                 dev_err(&dev->dev, "failed to claim framebuffer memory\n");
734                 ret = -EINVAL;
735                 goto err1;
736         }
737         mfbi->fb_phys_addr = mfbi->fb_res->start;
738
739         mfbi->reg_req = request_mem_region(mfbi->reg_res->start,
740                                            res_size(mfbi->reg_res), dev->name);
741         if (mfbi->reg_req == NULL) {
742                 dev_err(&dev->dev, "failed to claim Marathon registers\n");
743                 ret = -EINVAL;
744                 goto err2;
745         }
746         mfbi->reg_phys_addr = mfbi->reg_res->start;
747
748         mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr,
749                                               res_size(mfbi->reg_req));
750         if (!mfbi->reg_virt_addr) {
751                 dev_err(&dev->dev, "failed to ioremap Marathon registers\n");
752                 ret = -EINVAL;
753                 goto err3;
754         }
755         virt_base_2700 = (unsigned long)mfbi->reg_virt_addr;
756
757         mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr,
758                                              res_size(mfbi->fb_req));
759         if (!mfbi->reg_virt_addr) {
760                 dev_err(&dev->dev, "failed to ioremap frame buffer\n");
761                 ret = -EINVAL;
762                 goto err4;
763         }
764
765         fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
766         fbi->screen_size = pdata->memsize;
767         fbi->fbops = &mbxfb_ops;
768
769         fbi->var = mbxfb_default;
770         fbi->fix = mbxfb_fix;
771         fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000;
772         fbi->fix.smem_len = pdata->memsize;
773         fbi->fix.line_length = mbxfb_default.xres_virtual *
774                                         mbxfb_default.bits_per_pixel / 8;
775
776         ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
777         if (ret < 0) {
778                 dev_err(&dev->dev, "fb_alloc_cmap failed\n");
779                 ret = -EINVAL;
780                 goto err5;
781         }
782
783         platform_set_drvdata(dev, fbi);
784
785         printk(KERN_INFO "fb%d: mbx frame buffer device\n", fbi->node);
786
787         if (mfbi->platform_probe)
788                 mfbi->platform_probe(fbi);
789
790         enable_controller(fbi);
791
792         mbxfb_debugfs_init(fbi);
793
794         ret = register_framebuffer(fbi);
795         if (ret < 0) {
796                 dev_err(&dev->dev, "register_framebuffer failed\n");
797                 ret = -EINVAL;
798                 goto err6;
799         }
800
801         return 0;
802
803 err6:
804         fb_dealloc_cmap(&fbi->cmap);
805 err5:
806         iounmap(mfbi->fb_virt_addr);
807 err4:
808         iounmap(mfbi->reg_virt_addr);
809 err3:
810         release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res));
811 err2:
812         release_mem_region(mfbi->fb_res->start, res_size(mfbi->fb_res));
813 err1:
814         framebuffer_release(fbi);
815
816         return ret;
817 }
818
819 static int __devexit mbxfb_remove(struct platform_device *dev)
820 {
821         struct fb_info *fbi = platform_get_drvdata(dev);
822
823         write_reg_dly(SYSRST_RST, SYSRST);
824
825         mbxfb_debugfs_remove(fbi);
826
827         if (fbi) {
828                 struct mbxfb_info *mfbi = fbi->par;
829
830                 unregister_framebuffer(fbi);
831                 if (mfbi) {
832                         if (mfbi->platform_remove)
833                                 mfbi->platform_remove(fbi);
834
835                         if (mfbi->fb_virt_addr)
836                                 iounmap(mfbi->fb_virt_addr);
837                         if (mfbi->reg_virt_addr)
838                                 iounmap(mfbi->reg_virt_addr);
839                         if (mfbi->reg_req)
840                                 release_mem_region(mfbi->reg_req->start,
841                                                    res_size(mfbi->reg_req));
842                         if (mfbi->fb_req)
843                                 release_mem_region(mfbi->fb_req->start,
844                                                    res_size(mfbi->fb_req));
845                 }
846                 framebuffer_release(fbi);
847         }
848
849         return 0;
850 }
851
852 static struct platform_driver mbxfb_driver = {
853         .probe = mbxfb_probe,
854         .remove = mbxfb_remove,
855         .suspend = mbxfb_suspend,
856         .resume = mbxfb_resume,
857         .driver = {
858                 .name = "mbx-fb",
859         },
860 };
861
862 int __devinit mbxfb_init(void)
863 {
864         return platform_driver_register(&mbxfb_driver);
865 }
866
867 static void __devexit mbxfb_exit(void)
868 {
869         platform_driver_unregister(&mbxfb_driver);
870 }
871
872 module_init(mbxfb_init);
873 module_exit(mbxfb_exit);
874
875 MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
876 MODULE_AUTHOR("Mike Rapoport, Compulab");
877 MODULE_LICENSE("GPL");