2 * linux/drivers/video/mbx/mbxfb.c
4 * Copyright (C) 2006-2007 8D Technologies inc
5 * Raphael Assenat <raph@8d.com>
6 * - Added video overlay support
7 * - Various improvements
9 * Copyright (C) 2006 Compulab, Ltd.
10 * Mike Rapoport <mike@compulab.co.il>
11 * - Creation of driver
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
19 * Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver
23 #include <linux/delay.h>
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/uaccess.h>
31 #include <video/mbxfb.h>
36 static void __iomem
*virt_base_2700
;
38 #define write_reg(val, reg) do { writel((val), (reg)); } while(0)
40 /* Without this delay, the graphics appears somehow scaled and
41 * there is a lot of jitter in scanlines. This delay is probably
42 * needed only after setting some specific register(s) somewhere,
43 * not all over the place... */
44 #define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0)
51 #define MAX_PALETTES 16
53 /* FIXME: take care of different chip revisions with different sizes
55 #define MEMORY_OFFSET 0x60000
60 struct resource
*fb_res
;
61 struct resource
*fb_req
;
63 struct resource
*reg_res
;
64 struct resource
*reg_req
;
66 void __iomem
*fb_virt_addr
;
67 unsigned long fb_phys_addr
;
69 void __iomem
*reg_virt_addr
;
70 unsigned long reg_phys_addr
;
72 int (*platform_probe
) (struct fb_info
* fb
);
73 int (*platform_remove
) (struct fb_info
* fb
);
75 u32 pseudo_palette
[MAX_PALETTES
];
76 #ifdef CONFIG_FB_MBX_DEBUG
82 static struct fb_var_screeninfo mbxfb_default
= {
91 .activate
= FB_ACTIVATE_TEST
,
101 .vmode
= FB_VMODE_NONINTERLACED
,
102 .sync
= FB_SYNC_HOR_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
105 static struct fb_fix_screeninfo mbxfb_fix
= {
107 .type
= FB_TYPE_PACKED_PIXELS
,
108 .visual
= FB_VISUAL_TRUECOLOR
,
112 .accel
= FB_ACCEL_NONE
,
115 struct pixclock_div
{
121 static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps
,
122 struct pixclock_div
*div
)
125 unsigned int err
= 0;
126 unsigned int min_err
= ~0x0;
128 unsigned int best_clk
= 0;
129 unsigned int ref_clk
= 13000; /* FIXME: take from platform data */
130 unsigned int pixclock
;
132 /* convert pixclock to KHz */
133 pixclock
= PICOS2KHZ(pixclock_ps
);
135 /* PLL output freq = (ref_clk * M) / (N * 2^P)
142 /* RAPH: When N==1, the resulting pixel clock appears to
143 * get divided by 2. Preventing N=1 by starting the following
144 * loop at 2 prevents this. Is this a bug with my chip
145 * revision or something I dont understand? */
146 for (m
= 1; m
< 64; m
++) {
147 for (n
= 2; n
< 8; n
++) {
148 for (p
= 0; p
< 8; p
++) {
149 clk
= (ref_clk
* m
) / (n
* (1 << p
));
150 err
= (clk
> pixclock
) ? (clk
- pixclock
) :
162 return KHZ2PICOS(best_clk
);
165 static int mbxfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
166 u_int trans
, struct fb_info
*info
)
170 if (regno
< MAX_PALETTES
) {
171 u32
*pal
= info
->pseudo_palette
;
173 val
= (red
& 0xf800) | ((green
& 0xfc00) >> 5) |
174 ((blue
& 0xf800) >> 11);
182 static int mbxfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
184 struct pixclock_div div
;
186 var
->pixclock
= mbxfb_get_pixclock(var
->pixclock
, &div
);
188 if (var
->xres
< MIN_XRES
)
189 var
->xres
= MIN_XRES
;
190 if (var
->yres
< MIN_YRES
)
191 var
->yres
= MIN_YRES
;
192 if (var
->xres
> MAX_XRES
)
194 if (var
->yres
> MAX_YRES
)
196 var
->xres_virtual
= max(var
->xres_virtual
, var
->xres
);
197 var
->yres_virtual
= max(var
->yres_virtual
, var
->yres
);
199 switch (var
->bits_per_pixel
) {
200 /* 8 bits-per-pixel is not supported yet */
204 var
->green
.length
= (var
->green
.length
== 5) ? 5 : 6;
206 var
->blue
.length
= 5;
207 var
->transp
.length
= 6 - var
->green
.length
;
208 var
->blue
.offset
= 0;
209 var
->green
.offset
= 5;
210 var
->red
.offset
= 5 + var
->green
.length
;
211 var
->transp
.offset
= (5 + var
->red
.offset
) & 15;
213 case 24: /* RGB 888 */
214 case 32: /* RGBA 8888 */
215 var
->red
.offset
= 16;
217 var
->green
.offset
= 8;
218 var
->green
.length
= 8;
219 var
->blue
.offset
= 0;
220 var
->blue
.length
= 8;
221 var
->transp
.length
= var
->bits_per_pixel
- 24;
222 var
->transp
.offset
= (var
->transp
.length
) ? 24 : 0;
225 var
->red
.msb_right
= 0;
226 var
->green
.msb_right
= 0;
227 var
->blue
.msb_right
= 0;
228 var
->transp
.msb_right
= 0;
233 static int mbxfb_set_par(struct fb_info
*info
)
235 struct fb_var_screeninfo
*var
= &info
->var
;
236 struct pixclock_div div
;
237 ushort hbps
, ht
, hfps
, has
;
238 ushort vbps
, vt
, vfps
, vas
;
239 u32 gsctrl
= readl(GSCTRL
);
240 u32 gsadr
= readl(GSADR
);
242 info
->fix
.line_length
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
244 /* setup color mode */
245 gsctrl
&= ~(FMsk(GSCTRL_GPIXFMT
));
246 /* FIXME: add *WORKING* support for 8-bits per color */
247 if (info
->var
.bits_per_pixel
== 8) {
250 fb_dealloc_cmap(&info
->cmap
);
251 gsctrl
&= ~GSCTRL_LUT_EN
;
253 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
254 switch (info
->var
.bits_per_pixel
) {
256 if (info
->var
.green
.length
== 5)
257 gsctrl
|= GSCTRL_GPIXFMT_ARGB1555
;
259 gsctrl
|= GSCTRL_GPIXFMT_RGB565
;
262 gsctrl
|= GSCTRL_GPIXFMT_RGB888
;
265 gsctrl
|= GSCTRL_GPIXFMT_ARGB8888
;
270 /* setup resolution */
271 gsctrl
&= ~(FMsk(GSCTRL_GSWIDTH
) | FMsk(GSCTRL_GSHEIGHT
));
272 gsctrl
|= Gsctrl_Width(info
->var
.xres
) |
273 Gsctrl_Height(info
->var
.yres
);
274 write_reg_dly(gsctrl
, GSCTRL
);
276 gsadr
&= ~(FMsk(GSADR_SRCSTRIDE
));
277 gsadr
|= Gsadr_Srcstride(info
->var
.xres
* info
->var
.bits_per_pixel
/
279 write_reg_dly(gsadr
, GSADR
);
282 var
->pixclock
= mbxfb_get_pixclock(info
->var
.pixclock
, &div
);
284 write_reg_dly((Disp_Pll_M(div
.m
) | Disp_Pll_N(div
.n
) |
285 Disp_Pll_P(div
.p
) | DISP_PLL_EN
), DISPPLL
);
287 hbps
= var
->hsync_len
;
288 has
= hbps
+ var
->left_margin
;
289 hfps
= has
+ var
->xres
;
290 ht
= hfps
+ var
->right_margin
;
292 vbps
= var
->vsync_len
;
293 vas
= vbps
+ var
->upper_margin
;
294 vfps
= vas
+ var
->yres
;
295 vt
= vfps
+ var
->lower_margin
;
297 write_reg_dly((Dht01_Hbps(hbps
) | Dht01_Ht(ht
)), DHT01
);
298 write_reg_dly((Dht02_Hlbs(has
) | Dht02_Has(has
)), DHT02
);
299 write_reg_dly((Dht03_Hfps(hfps
) | Dht03_Hrbs(hfps
)), DHT03
);
300 write_reg_dly((Dhdet_Hdes(has
) | Dhdet_Hdef(hfps
)), DHDET
);
302 write_reg_dly((Dvt01_Vbps(vbps
) | Dvt01_Vt(vt
)), DVT01
);
303 write_reg_dly((Dvt02_Vtbs(vas
) | Dvt02_Vas(vas
)), DVT02
);
304 write_reg_dly((Dvt03_Vfps(vfps
) | Dvt03_Vbbs(vfps
)), DVT03
);
305 write_reg_dly((Dvdet_Vdes(vas
) | Dvdet_Vdef(vfps
)), DVDET
);
306 write_reg_dly((Dvectrl_Vevent(vfps
) | Dvectrl_Vfetch(vbps
)), DVECTRL
);
308 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
310 write_reg_dly(DINTRE_VEVENT0_EN
, DINTRE
);
315 static int mbxfb_blank(int blank
, struct fb_info
*info
)
318 case FB_BLANK_POWERDOWN
:
319 case FB_BLANK_VSYNC_SUSPEND
:
320 case FB_BLANK_HSYNC_SUSPEND
:
321 case FB_BLANK_NORMAL
:
322 write_reg_dly((readl(DSCTRL
) & ~DSCTRL_SYNCGEN_EN
), DSCTRL
);
323 write_reg_dly((readl(PIXCLK
) & ~PIXCLK_EN
), PIXCLK
);
324 write_reg_dly((readl(VOVRCLK
) & ~VOVRCLK_EN
), VOVRCLK
);
326 case FB_BLANK_UNBLANK
:
327 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
328 write_reg_dly((readl(PIXCLK
) | PIXCLK_EN
), PIXCLK
);
334 static int mbxfb_setupOverlay(struct mbxfb_overlaySetup
*set
)
336 u32 vsctrl
, vscadr
, vsadr
;
337 u32 sssize
, spoctrl
, shctrl
;
341 if (set
->scaled_width
==0 || set
->scaled_height
==0)
344 /* read registers which have reserved bits
345 * so we can write them back as-is. */
346 vovrclk
= readl(VOVRCLK
);
347 vsctrl
= readl(VSCTRL
);
348 vscadr
= readl(VSCADR
);
349 vubase
= readl(VUBASE
);
350 vvbase
= readl(VVBASE
);
351 shctrl
= readl(SHCTRL
);
353 spoctrl
= readl(SPOCTRL
);
354 sssize
= readl(SSSIZE
);
356 vsctrl
&= ~( FMsk(VSCTRL_VSWIDTH
) |
357 FMsk(VSCTRL_VSHEIGHT
) |
358 FMsk(VSCTRL_VPIXFMT
) |
359 VSCTRL_GAMMA_EN
| VSCTRL_CSC_EN
|
361 vsctrl
|= Vsctrl_Width(set
->width
) | Vsctrl_Height(set
->height
) |
364 vscadr
&= ~(VSCADR_STR_EN
| FMsk(VSCADR_VBASE_ADR
) );
365 vubase
&= ~(VUBASE_UVHALFSTR
| FMsk(VUBASE_UBASE_ADR
));
366 vvbase
&= ~(FMsk(VVBASE_VBASE_ADR
));
369 case MBXFB_FMT_YUV16
:
370 vsctrl
|= VSCTRL_VPIXFMT_YUV12
;
372 set
->Y_stride
= ((set
->width
) + 0xf ) & ~0xf;
374 case MBXFB_FMT_YUV12
:
375 vsctrl
|= VSCTRL_VPIXFMT_YUV12
;
377 set
->Y_stride
= ((set
->width
) + 0xf ) & ~0xf;
378 vubase
|= VUBASE_UVHALFSTR
;
381 case MBXFB_FMT_UY0VY1
:
382 vsctrl
|= VSCTRL_VPIXFMT_UY0VY1
;
383 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
385 case MBXFB_FMT_VY0UY1
:
386 vsctrl
|= VSCTRL_VPIXFMT_VY0UY1
;
387 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
389 case MBXFB_FMT_Y0UY1V
:
390 vsctrl
|= VSCTRL_VPIXFMT_Y0UY1V
;
391 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
393 case MBXFB_FMT_Y0VY1U
:
394 vsctrl
|= VSCTRL_VPIXFMT_Y0VY1U
;
395 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
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).
407 * If course, the values calculated here have no meaning
408 * for packed formats.
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);
420 vscadr
|= Vscadr_Vbase_Adr((0x60000 + set
->mem_offset
)>>4);
423 vscadr
|= VSCADR_STR_EN
;
426 vsadr
= Vsadr_Srcstride((set
->Y_stride
)/16-1) |
427 Vsadr_Xstart(set
->x
) | Vsadr_Ystart(set
->y
);
429 sssize
&= ~(FMsk(SSSIZE_SC_WIDTH
) | FMsk(SSSIZE_SC_HEIGHT
));
430 sssize
= Sssize_Sc_Width(set
->scaled_width
-1) |
431 Sssize_Sc_Height(set
->scaled_height
-1);
433 spoctrl
&= ~(SPOCTRL_H_SC_BP
| SPOCTRL_V_SC_BP
|
434 SPOCTRL_HV_SC_OR
| SPOCTRL_VS_UR_C
|
435 FMsk(SPOCTRL_VPITCH
));
436 spoctrl
|= Spoctrl_Vpitch((set
->height
<<11)/set
->scaled_height
);
438 /* Bypass horiz/vert scaler when same size */
439 if (set
->scaled_width
== set
->width
)
440 spoctrl
|= SPOCTRL_H_SC_BP
;
441 if (set
->scaled_height
== set
->height
)
442 spoctrl
|= SPOCTRL_V_SC_BP
;
444 shctrl
&= ~(FMsk(SHCTRL_HPITCH
) | SHCTRL_HDECIM
);
445 shctrl
|= Shctrl_Hpitch((set
->width
<<11)/set
->scaled_width
);
447 /* Video plane registers */
448 write_reg(vsctrl
, VSCTRL
);
449 write_reg(vscadr
, VSCADR
);
450 write_reg(vubase
, VUBASE
);
451 write_reg(vvbase
, VVBASE
);
452 write_reg(vsadr
, VSADR
);
454 /* Video scaler registers */
455 write_reg(sssize
, SSSIZE
);
456 write_reg(spoctrl
, SPOCTRL
);
457 write_reg(shctrl
, SHCTRL
);
465 write_reg(vovrclk
, VOVRCLK
);
470 static int mbxfb_ioctl_planeorder(struct mbxfb_planeorder
*porder
)
472 unsigned long gscadr
, vscadr
;
474 if (porder
->bottom
== porder
->top
)
477 gscadr
= readl(GSCADR
);
478 vscadr
= readl(VSCADR
);
480 gscadr
&= ~(FMsk(GSCADR_BLEND_POS
));
481 vscadr
&= ~(FMsk(VSCADR_BLEND_POS
));
483 switch (porder
->bottom
) {
484 case MBXFB_PLANE_GRAPHICS
:
485 gscadr
|= GSCADR_BLEND_GFX
;
487 case MBXFB_PLANE_VIDEO
:
488 vscadr
|= VSCADR_BLEND_GFX
;
494 switch (porder
->top
) {
495 case MBXFB_PLANE_GRAPHICS
:
496 gscadr
|= GSCADR_BLEND_VID
;
498 case MBXFB_PLANE_VIDEO
:
499 vscadr
|= GSCADR_BLEND_VID
;
505 write_reg_dly(vscadr
, VSCADR
);
506 write_reg_dly(gscadr
, GSCADR
);
512 static int mbxfb_ioctl_alphactl(struct mbxfb_alphaCtl
*alpha
)
514 unsigned long vscadr
, vbbase
, vcmsk
;
515 unsigned long gscadr
, gbbase
, gdrctrl
;
517 vbbase
= Vbbase_Glalpha(alpha
->overlay_global_alpha
) |
518 Vbbase_Colkey(alpha
->overlay_colorkey
);
520 gbbase
= Gbbase_Glalpha(alpha
->graphics_global_alpha
) |
521 Gbbase_Colkey(alpha
->graphics_colorkey
);
523 vcmsk
= readl(VCMSK
);
524 vcmsk
&= ~(FMsk(VCMSK_COLKEY_M
));
525 vcmsk
|= Vcmsk_colkey_m(alpha
->overlay_colorkey_mask
);
527 gdrctrl
= readl(GDRCTRL
);
528 gdrctrl
&= ~(FMsk(GDRCTRL_COLKEYM
));
529 gdrctrl
|= Gdrctrl_Colkeym(alpha
->graphics_colorkey_mask
);
531 vscadr
= readl(VSCADR
);
532 vscadr
&= ~(FMsk(VSCADR_BLEND_M
) | VSCADR_COLKEYSRC
| VSCADR_COLKEY_EN
);
534 gscadr
= readl(GSCADR
);
535 gscadr
&= ~(FMsk(GSCADR_BLEND_M
) | GSCADR_COLKEY_EN
| GSCADR_COLKEYSRC
);
537 switch (alpha
->overlay_colorkey_mode
) {
538 case MBXFB_COLORKEY_DISABLED
:
540 case MBXFB_COLORKEY_PREVIOUS
:
541 vscadr
|= VSCADR_COLKEY_EN
;
543 case MBXFB_COLORKEY_CURRENT
:
544 vscadr
|= VSCADR_COLKEY_EN
| VSCADR_COLKEYSRC
;
550 switch (alpha
->overlay_blend_mode
) {
551 case MBXFB_ALPHABLEND_NONE
:
552 vscadr
|= VSCADR_BLEND_NONE
;
554 case MBXFB_ALPHABLEND_GLOBAL
:
555 vscadr
|= VSCADR_BLEND_GLOB
;
557 case MBXFB_ALPHABLEND_PIXEL
:
558 vscadr
|= VSCADR_BLEND_PIX
;
564 switch (alpha
->graphics_colorkey_mode
) {
565 case MBXFB_COLORKEY_DISABLED
:
567 case MBXFB_COLORKEY_PREVIOUS
:
568 gscadr
|= GSCADR_COLKEY_EN
;
570 case MBXFB_COLORKEY_CURRENT
:
571 gscadr
|= GSCADR_COLKEY_EN
| GSCADR_COLKEYSRC
;
577 switch (alpha
->graphics_blend_mode
) {
578 case MBXFB_ALPHABLEND_NONE
:
579 gscadr
|= GSCADR_BLEND_NONE
;
581 case MBXFB_ALPHABLEND_GLOBAL
:
582 gscadr
|= GSCADR_BLEND_GLOB
;
584 case MBXFB_ALPHABLEND_PIXEL
:
585 gscadr
|= GSCADR_BLEND_PIX
;
591 write_reg_dly(vbbase
, VBBASE
);
592 write_reg_dly(gbbase
, GBBASE
);
593 write_reg_dly(vcmsk
, VCMSK
);
594 write_reg_dly(gdrctrl
, GDRCTRL
);
595 write_reg_dly(gscadr
, GSCADR
);
596 write_reg_dly(vscadr
, VSCADR
);
601 static int mbxfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
604 struct mbxfb_overlaySetup setup
;
605 struct mbxfb_planeorder porder
;
606 struct mbxfb_alphaCtl alpha
;
607 struct mbxfb_reg reg
;
613 case MBXFB_IOCX_OVERLAY
:
614 if (copy_from_user(&setup
, (void __user
*)arg
,
615 sizeof(struct mbxfb_overlaySetup
)))
618 res
= mbxfb_setupOverlay(&setup
);
622 if (copy_to_user((void __user
*)arg
, &setup
,
623 sizeof(struct mbxfb_overlaySetup
)))
628 case MBXFB_IOCS_PLANEORDER
:
629 if (copy_from_user(&porder
, (void __user
*)arg
,
630 sizeof(struct mbxfb_planeorder
)))
633 return mbxfb_ioctl_planeorder(&porder
);
635 case MBXFB_IOCS_ALPHA
:
636 if (copy_from_user(&alpha
, (void __user
*)arg
,
637 sizeof(struct mbxfb_alphaCtl
)))
640 return mbxfb_ioctl_alphactl(&alpha
);
643 if (copy_from_user(®
, (void __user
*)arg
,
644 sizeof(struct mbxfb_reg
)))
647 if (reg
.addr
>= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
650 tmp
= readl(virt_base_2700
+ reg
.addr
);
652 tmp
|= reg
.val
& reg
.mask
;
653 writel(tmp
, virt_base_2700
+ reg
.addr
);
657 if (copy_from_user(®
, (void __user
*)arg
,
658 sizeof(struct mbxfb_reg
)))
661 if (reg
.addr
>= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
663 reg
.val
= readl(virt_base_2700
+ reg
.addr
);
665 if (copy_to_user((void __user
*)arg
, ®
,
666 sizeof(struct mbxfb_reg
)))
674 static struct fb_ops mbxfb_ops
= {
675 .owner
= THIS_MODULE
,
676 .fb_check_var
= mbxfb_check_var
,
677 .fb_set_par
= mbxfb_set_par
,
678 .fb_setcolreg
= mbxfb_setcolreg
,
679 .fb_fillrect
= cfb_fillrect
,
680 .fb_copyarea
= cfb_copyarea
,
681 .fb_imageblit
= cfb_imageblit
,
682 .fb_blank
= mbxfb_blank
,
683 .fb_ioctl
= mbxfb_ioctl
,
687 Enable external SDRAM controller. Assume that all clocks are active
690 static void setup_memc(struct fb_info
*fbi
)
695 /* FIXME: use platform specific parameters */
696 /* setup SDRAM controller */
697 write_reg_dly((LMCFG_LMC_DS
| LMCFG_LMC_TS
| LMCFG_LMD_TS
|
701 write_reg_dly(LMPWR_MC_PWR_ACT
, LMPWR
);
703 /* setup SDRAM timings */
704 write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
705 Lmtim_Trc(9) | Lmtim_Tdpl(2)),
707 /* setup SDRAM refresh rate */
708 write_reg_dly(0xc2b, LMREFRESH
);
709 /* setup SDRAM type parameters */
710 write_reg_dly((LMTYPE_CASLAT_3
| LMTYPE_BKSZ_2
| LMTYPE_ROWSZ_11
|
713 /* enable memory controller */
714 write_reg_dly(LMPWR_MC_PWR_ACT
, LMPWR
);
715 /* perform dummy reads */
716 for ( i
= 0; i
< 16; i
++ ) {
717 tmp
= readl(fbi
->screen_base
);
721 static void enable_clocks(struct fb_info
*fbi
)
724 write_reg_dly(SYSCLKSRC_PLL_2
, SYSCLKSRC
);
725 write_reg_dly(PIXCLKSRC_PLL_1
, PIXCLKSRC
);
726 write_reg_dly(0x00000000, CLKSLEEP
);
728 /* PLL output = (Frefclk * M) / (N * 2^P )
730 * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz!
731 * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz
733 write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) |
737 write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
741 write_reg_dly(0x00000000, VOVRCLK
);
742 write_reg_dly(PIXCLK_EN
, PIXCLK
);
743 write_reg_dly(MEMCLK_EN
, MEMCLK
);
744 write_reg_dly(0x00000001, M24CLK
);
745 write_reg_dly(0x00000001, MBXCLK
);
746 write_reg_dly(SDCLK_EN
, SDCLK
);
747 write_reg_dly(0x00000001, PIXCLKDIV
);
750 static void setup_graphics(struct fb_info
*fbi
)
752 unsigned long gsctrl
;
753 unsigned long vscadr
;
755 gsctrl
= GSCTRL_GAMMA_EN
| Gsctrl_Width(fbi
->var
.xres
) |
756 Gsctrl_Height(fbi
->var
.yres
);
757 switch (fbi
->var
.bits_per_pixel
) {
759 if (fbi
->var
.green
.length
== 5)
760 gsctrl
|= GSCTRL_GPIXFMT_ARGB1555
;
762 gsctrl
|= GSCTRL_GPIXFMT_RGB565
;
765 gsctrl
|= GSCTRL_GPIXFMT_RGB888
;
768 gsctrl
|= GSCTRL_GPIXFMT_ARGB8888
;
772 write_reg_dly(gsctrl
, GSCTRL
);
773 write_reg_dly(0x00000000, GBBASE
);
774 write_reg_dly(0x00ffffff, GDRCTRL
);
775 write_reg_dly((GSCADR_STR_EN
| Gscadr_Gbase_Adr(0x6000)), GSCADR
);
776 write_reg_dly(0x00000000, GPLUT
);
778 vscadr
= readl(VSCADR
);
779 vscadr
&= ~(FMsk(VSCADR_BLEND_POS
) | FMsk(VSCADR_BLEND_M
));
780 vscadr
|= VSCADR_BLEND_VID
| VSCADR_BLEND_NONE
;
781 write_reg_dly(vscadr
, VSCADR
);
784 static void setup_display(struct fb_info
*fbi
)
786 unsigned long dsctrl
= 0;
788 dsctrl
= DSCTRL_BLNK_POL
;
789 if (fbi
->var
.sync
& FB_SYNC_HOR_HIGH_ACT
)
790 dsctrl
|= DSCTRL_HS_POL
;
791 if (fbi
->var
.sync
& FB_SYNC_VERT_HIGH_ACT
)
792 dsctrl
|= DSCTRL_VS_POL
;
793 write_reg_dly(dsctrl
, DSCTRL
);
794 write_reg_dly(0xd0303010, DMCTRL
);
795 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
798 static void enable_controller(struct fb_info
*fbi
)
802 write_reg_dly(SYSRST_RST
, SYSRST
);
804 /* setup a timeout, raise drive strength */
805 write_reg_dly(0xffffff0c, SYSCFG
);
812 shctrl
= readl(SHCTRL
);
813 shctrl
&= ~(FMsk(SHCTRL_HINITIAL
));
814 shctrl
|= Shctrl_Hinitial(4<<11);
815 writel(shctrl
, SHCTRL
);
817 svctrl
= Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
818 writel(svctrl
, SVCTRL
);
820 writel(SPOCTRL_H_SC_BP
| SPOCTRL_V_SC_BP
| SPOCTRL_VORDER_4TAP
823 /* Those coefficients are good for scaling up. For scaling
824 * down, the application has to calculate them. */
825 write_reg(0xff000100, VSCOEFF0
);
826 write_reg(0xfdfcfdfe, VSCOEFF1
);
827 write_reg(0x170d0500, VSCOEFF2
);
828 write_reg(0x3d372d22, VSCOEFF3
);
829 write_reg(0x00000040, VSCOEFF4
);
831 write_reg(0xff010100, HSCOEFF0
);
832 write_reg(0x00000000, HSCOEFF1
);
833 write_reg(0x02010000, HSCOEFF2
);
834 write_reg(0x01020302, HSCOEFF3
);
835 write_reg(0xf9fbfe00, HSCOEFF4
);
836 write_reg(0xfbf7f6f7, HSCOEFF5
);
837 write_reg(0x1c110700, HSCOEFF6
);
838 write_reg(0x3e393127, HSCOEFF7
);
839 write_reg(0x00000040, HSCOEFF8
);
845 * Power management hooks. Note that we won't be called from IRQ context,
846 * unlike the blank functions above, so we may sleep.
848 static int mbxfb_suspend(struct platform_device
*dev
, pm_message_t state
)
850 /* make frame buffer memory enter self-refresh mode */
851 write_reg_dly(LMPWR_MC_PWR_SRM
, LMPWR
);
852 while (readl(LMPWRSTAT
) != LMPWRSTAT_MC_PWR_SRM
)
853 ; /* empty statement */
855 /* reset the device, since it's initial state is 'mostly sleeping' */
856 write_reg_dly(SYSRST_RST
, SYSRST
);
860 static int mbxfb_resume(struct platform_device
*dev
)
862 struct fb_info
*fbi
= platform_get_drvdata(dev
);
865 /* setup_graphics(fbi); */
866 /* setup_display(fbi); */
868 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
872 #define mbxfb_suspend NULL
873 #define mbxfb_resume NULL
876 /* debugfs entries */
877 #ifndef CONFIG_FB_MBX_DEBUG
878 #define mbxfb_debugfs_init(x) do {} while(0)
879 #define mbxfb_debugfs_remove(x) do {} while(0)
881 #include "mbxdebugfs.c"
884 #define res_size(_r) (((_r)->end - (_r)->start) + 1)
886 static int mbxfb_probe(struct platform_device
*dev
)
890 struct mbxfb_info
*mfbi
;
891 struct mbxfb_platform_data
*pdata
;
893 dev_dbg(&dev
->dev
, "mbxfb_probe\n");
895 pdata
= dev_get_platdata(&dev
->dev
);
897 dev_err(&dev
->dev
, "platform data is required\n");
901 fbi
= framebuffer_alloc(sizeof(struct mbxfb_info
), &dev
->dev
);
903 dev_err(&dev
->dev
, "framebuffer_alloc failed\n");
908 fbi
->pseudo_palette
= mfbi
->pseudo_palette
;
912 mfbi
->platform_probe
= pdata
->probe
;
914 mfbi
->platform_remove
= pdata
->remove
;
916 mfbi
->fb_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
917 mfbi
->reg_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 1);
919 if (!mfbi
->fb_res
|| !mfbi
->reg_res
) {
920 dev_err(&dev
->dev
, "no resources found\n");
925 mfbi
->fb_req
= request_mem_region(mfbi
->fb_res
->start
,
926 res_size(mfbi
->fb_res
), dev
->name
);
927 if (mfbi
->fb_req
== NULL
) {
928 dev_err(&dev
->dev
, "failed to claim framebuffer memory\n");
932 mfbi
->fb_phys_addr
= mfbi
->fb_res
->start
;
934 mfbi
->reg_req
= request_mem_region(mfbi
->reg_res
->start
,
935 res_size(mfbi
->reg_res
), dev
->name
);
936 if (mfbi
->reg_req
== NULL
) {
937 dev_err(&dev
->dev
, "failed to claim Marathon registers\n");
941 mfbi
->reg_phys_addr
= mfbi
->reg_res
->start
;
943 mfbi
->reg_virt_addr
= devm_ioremap_nocache(&dev
->dev
,
945 res_size(mfbi
->reg_req
));
946 if (!mfbi
->reg_virt_addr
) {
947 dev_err(&dev
->dev
, "failed to ioremap Marathon registers\n");
951 virt_base_2700
= mfbi
->reg_virt_addr
;
953 mfbi
->fb_virt_addr
= devm_ioremap_nocache(&dev
->dev
, mfbi
->fb_phys_addr
,
954 res_size(mfbi
->fb_req
));
955 if (!mfbi
->fb_virt_addr
) {
956 dev_err(&dev
->dev
, "failed to ioremap frame buffer\n");
961 fbi
->screen_base
= (char __iomem
*)(mfbi
->fb_virt_addr
+ 0x60000);
962 fbi
->screen_size
= pdata
->memsize
;
963 fbi
->fbops
= &mbxfb_ops
;
965 fbi
->var
= mbxfb_default
;
966 fbi
->fix
= mbxfb_fix
;
967 fbi
->fix
.smem_start
= mfbi
->fb_phys_addr
+ 0x60000;
968 fbi
->fix
.smem_len
= pdata
->memsize
;
969 fbi
->fix
.line_length
= mbxfb_default
.xres_virtual
*
970 mbxfb_default
.bits_per_pixel
/ 8;
972 ret
= fb_alloc_cmap(&fbi
->cmap
, 256, 0);
974 dev_err(&dev
->dev
, "fb_alloc_cmap failed\n");
979 platform_set_drvdata(dev
, fbi
);
981 fb_info(fbi
, "mbx frame buffer device\n");
983 if (mfbi
->platform_probe
)
984 mfbi
->platform_probe(fbi
);
986 enable_controller(fbi
);
988 mbxfb_debugfs_init(fbi
);
990 ret
= register_framebuffer(fbi
);
992 dev_err(&dev
->dev
, "register_framebuffer failed\n");
1000 fb_dealloc_cmap(&fbi
->cmap
);
1002 release_mem_region(mfbi
->reg_res
->start
, res_size(mfbi
->reg_res
));
1004 release_mem_region(mfbi
->fb_res
->start
, res_size(mfbi
->fb_res
));
1006 framebuffer_release(fbi
);
1011 static int mbxfb_remove(struct platform_device
*dev
)
1013 struct fb_info
*fbi
= platform_get_drvdata(dev
);
1015 write_reg_dly(SYSRST_RST
, SYSRST
);
1017 mbxfb_debugfs_remove(fbi
);
1020 struct mbxfb_info
*mfbi
= fbi
->par
;
1022 unregister_framebuffer(fbi
);
1024 if (mfbi
->platform_remove
)
1025 mfbi
->platform_remove(fbi
);
1029 release_mem_region(mfbi
->reg_req
->start
,
1030 res_size(mfbi
->reg_req
));
1032 release_mem_region(mfbi
->fb_req
->start
,
1033 res_size(mfbi
->fb_req
));
1035 framebuffer_release(fbi
);
1041 static struct platform_driver mbxfb_driver
= {
1042 .probe
= mbxfb_probe
,
1043 .remove
= mbxfb_remove
,
1044 .suspend
= mbxfb_suspend
,
1045 .resume
= mbxfb_resume
,
1051 module_platform_driver(mbxfb_driver
);
1053 MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
1054 MODULE_AUTHOR("Mike Rapoport, Compulab");
1055 MODULE_LICENSE("GPL");