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>
32 #include <video/mbxfb.h>
37 static unsigned long virt_base_2700
;
39 #define write_reg(val, reg) do { writel((val), (reg)); } while(0)
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)
52 #define MAX_PALETTES 16
54 #define MEMORY_OFFSET 0x60000
59 struct resource
*fb_res
;
60 struct resource
*fb_req
;
62 struct resource
*reg_res
;
63 struct resource
*reg_req
;
65 void __iomem
*fb_virt_addr
;
66 unsigned long fb_phys_addr
;
68 void __iomem
*reg_virt_addr
;
69 unsigned long reg_phys_addr
;
71 int (*platform_probe
) (struct fb_info
* fb
);
72 int (*platform_remove
) (struct fb_info
* fb
);
74 u32 pseudo_palette
[MAX_PALETTES
];
75 #ifdef CONFIG_FB_MBX_DEBUG
81 static struct fb_var_screeninfo mbxfb_default __devinitdata
= {
90 .activate
= FB_ACTIVATE_TEST
,
100 .vmode
= FB_VMODE_NONINTERLACED
,
101 .sync
= FB_SYNC_HOR_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
104 static struct fb_fix_screeninfo mbxfb_fix __devinitdata
= {
106 .type
= FB_TYPE_PACKED_PIXELS
,
107 .visual
= FB_VISUAL_TRUECOLOR
,
111 .accel
= FB_ACCEL_NONE
,
114 struct pixclock_div
{
120 static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps
,
121 struct pixclock_div
*div
)
124 unsigned int err
= 0;
125 unsigned int min_err
= ~0x0;
127 unsigned int best_clk
= 0;
128 unsigned int ref_clk
= 13000;
129 unsigned int pixclock
;
131 /* convert pixclock to KHz */
132 pixclock
= PICOS2KHZ(pixclock_ps
);
134 /* PLL output freq = (ref_clk * M) / (N * 2^P)
141 /* RAPH: When N==1, the resulting pixel clock appears to
142 * get divided by 2. Preventing N=1 by starting the following
143 * loop at 2 prevents this. Is this a bug with my chip
144 * revision or something I dont understand? */
145 for (m
= 1; m
< 64; m
++) {
146 for (n
= 2; n
< 8; n
++) {
147 for (p
= 0; p
< 8; p
++) {
148 clk
= (ref_clk
* m
) / (n
* (1 << p
));
149 err
= (clk
> pixclock
) ? (clk
- pixclock
) :
161 return KHZ2PICOS(best_clk
);
164 static int mbxfb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
165 u_int trans
, struct fb_info
*info
)
169 if (regno
< MAX_PALETTES
) {
170 u32
*pal
= info
->pseudo_palette
;
172 val
= (red
& 0xf800) | ((green
& 0xfc00) >> 5) |
173 ((blue
& 0xf800) >> 11);
181 static int mbxfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
183 struct pixclock_div div
;
185 var
->pixclock
= mbxfb_get_pixclock(var
->pixclock
, &div
);
187 if (var
->xres
< MIN_XRES
)
188 var
->xres
= MIN_XRES
;
189 if (var
->yres
< MIN_YRES
)
190 var
->yres
= MIN_YRES
;
191 if (var
->xres
> MAX_XRES
)
193 if (var
->yres
> MAX_YRES
)
195 var
->xres_virtual
= max(var
->xres_virtual
, var
->xres
);
196 var
->yres_virtual
= max(var
->yres_virtual
, var
->yres
);
198 switch (var
->bits_per_pixel
) {
199 /* 8 bits-per-pixel is not supported yet */
203 var
->green
.length
= (var
->green
.length
== 5) ? 5 : 6;
205 var
->blue
.length
= 5;
206 var
->transp
.length
= 6 - var
->green
.length
;
207 var
->blue
.offset
= 0;
208 var
->green
.offset
= 5;
209 var
->red
.offset
= 5 + var
->green
.length
;
210 var
->transp
.offset
= (5 + var
->red
.offset
) & 15;
212 case 24: /* RGB 888 */
213 case 32: /* RGBA 8888 */
214 var
->red
.offset
= 16;
216 var
->green
.offset
= 8;
217 var
->green
.length
= 8;
218 var
->blue
.offset
= 0;
219 var
->blue
.length
= 8;
220 var
->transp
.length
= var
->bits_per_pixel
- 24;
221 var
->transp
.offset
= (var
->transp
.length
) ? 24 : 0;
224 var
->red
.msb_right
= 0;
225 var
->green
.msb_right
= 0;
226 var
->blue
.msb_right
= 0;
227 var
->transp
.msb_right
= 0;
232 static int mbxfb_set_par(struct fb_info
*info
)
234 struct fb_var_screeninfo
*var
= &info
->var
;
235 struct pixclock_div div
;
236 ushort hbps
, ht
, hfps
, has
;
237 ushort vbps
, vt
, vfps
, vas
;
238 u32 gsctrl
= readl(GSCTRL
);
239 u32 gsadr
= readl(GSADR
);
241 info
->fix
.line_length
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
243 /* setup color mode */
244 gsctrl
&= ~(FMsk(GSCTRL_GPIXFMT
));
245 if (info
->var
.bits_per_pixel
== 8) {
248 fb_dealloc_cmap(&info
->cmap
);
249 gsctrl
&= ~GSCTRL_LUT_EN
;
251 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
252 switch (info
->var
.bits_per_pixel
) {
254 if (info
->var
.green
.length
== 5)
255 gsctrl
|= GSCTRL_GPIXFMT_ARGB1555
;
257 gsctrl
|= GSCTRL_GPIXFMT_RGB565
;
260 gsctrl
|= GSCTRL_GPIXFMT_RGB888
;
263 gsctrl
|= GSCTRL_GPIXFMT_ARGB8888
;
268 /* setup resolution */
269 gsctrl
&= ~(FMsk(GSCTRL_GSWIDTH
) | FMsk(GSCTRL_GSHEIGHT
));
270 gsctrl
|= Gsctrl_Width(info
->var
.xres
) |
271 Gsctrl_Height(info
->var
.yres
);
272 write_reg_dly(gsctrl
, GSCTRL
);
274 gsadr
&= ~(FMsk(GSADR_SRCSTRIDE
));
275 gsadr
|= Gsadr_Srcstride(info
->var
.xres
* info
->var
.bits_per_pixel
/
277 write_reg_dly(gsadr
, GSADR
);
280 var
->pixclock
= mbxfb_get_pixclock(info
->var
.pixclock
, &div
);
282 write_reg_dly((Disp_Pll_M(div
.m
) | Disp_Pll_N(div
.n
) |
283 Disp_Pll_P(div
.p
) | DISP_PLL_EN
), DISPPLL
);
285 hbps
= var
->hsync_len
;
286 has
= hbps
+ var
->left_margin
;
287 hfps
= has
+ var
->xres
;
288 ht
= hfps
+ var
->right_margin
;
290 vbps
= var
->vsync_len
;
291 vas
= vbps
+ var
->upper_margin
;
292 vfps
= vas
+ var
->yres
;
293 vt
= vfps
+ var
->lower_margin
;
295 write_reg_dly((Dht01_Hbps(hbps
) | Dht01_Ht(ht
)), DHT01
);
296 write_reg_dly((Dht02_Hlbs(has
) | Dht02_Has(has
)), DHT02
);
297 write_reg_dly((Dht03_Hfps(hfps
) | Dht03_Hrbs(hfps
)), DHT03
);
298 write_reg_dly((Dhdet_Hdes(has
) | Dhdet_Hdef(hfps
)), DHDET
);
300 write_reg_dly((Dvt01_Vbps(vbps
) | Dvt01_Vt(vt
)), DVT01
);
301 write_reg_dly((Dvt02_Vtbs(vas
) | Dvt02_Vas(vas
)), DVT02
);
302 write_reg_dly((Dvt03_Vfps(vfps
) | Dvt03_Vbbs(vfps
)), DVT03
);
303 write_reg_dly((Dvdet_Vdes(vas
) | Dvdet_Vdef(vfps
)), DVDET
);
304 write_reg_dly((Dvectrl_Vevent(vfps
) | Dvectrl_Vfetch(vbps
)), DVECTRL
);
306 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
308 write_reg_dly(DINTRE_VEVENT0_EN
, DINTRE
);
313 static int mbxfb_blank(int blank
, struct fb_info
*info
)
316 case FB_BLANK_POWERDOWN
:
317 case FB_BLANK_VSYNC_SUSPEND
:
318 case FB_BLANK_HSYNC_SUSPEND
:
319 case FB_BLANK_NORMAL
:
320 write_reg_dly((readl(DSCTRL
) & ~DSCTRL_SYNCGEN_EN
), DSCTRL
);
321 write_reg_dly((readl(PIXCLK
) & ~PIXCLK_EN
), PIXCLK
);
322 write_reg_dly((readl(VOVRCLK
) & ~VOVRCLK_EN
), VOVRCLK
);
324 case FB_BLANK_UNBLANK
:
325 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
326 write_reg_dly((readl(PIXCLK
) | PIXCLK_EN
), PIXCLK
);
332 static int mbxfb_setupOverlay(struct mbxfb_overlaySetup
*set
)
334 u32 vsctrl
, vscadr
, vsadr
;
335 u32 sssize
, spoctrl
, shctrl
;
339 if (set
->scaled_width
==0 || set
->scaled_height
==0)
342 /* read registers which have reserved bits
343 * so we can write them back as-is. */
344 vovrclk
= readl(VOVRCLK
);
345 vsctrl
= readl(VSCTRL
);
346 vscadr
= readl(VSCADR
);
347 vubase
= readl(VUBASE
);
348 vvbase
= readl(VVBASE
);
349 shctrl
= readl(SHCTRL
);
351 spoctrl
= readl(SPOCTRL
);
352 sssize
= readl(SSSIZE
);
354 vsctrl
&= ~( FMsk(VSCTRL_VSWIDTH
) |
355 FMsk(VSCTRL_VSHEIGHT
) |
356 FMsk(VSCTRL_VPIXFMT
) |
357 VSCTRL_GAMMA_EN
| VSCTRL_CSC_EN
|
359 vsctrl
|= Vsctrl_Width(set
->width
) | Vsctrl_Height(set
->height
) |
362 vscadr
&= ~(VSCADR_STR_EN
| FMsk(VSCADR_VBASE_ADR
) );
363 vubase
&= ~(VUBASE_UVHALFSTR
| FMsk(VUBASE_UBASE_ADR
));
364 vvbase
&= ~(FMsk(VVBASE_VBASE_ADR
));
367 case MBXFB_FMT_YUV16
:
368 vsctrl
|= VSCTRL_VPIXFMT_YUV12
;
370 set
->Y_stride
= ((set
->width
) + 0xf ) & ~0xf;
372 case MBXFB_FMT_YUV12
:
373 vsctrl
|= VSCTRL_VPIXFMT_YUV12
;
375 set
->Y_stride
= ((set
->width
) + 0xf ) & ~0xf;
376 vubase
|= VUBASE_UVHALFSTR
;
379 case MBXFB_FMT_UY0VY1
:
380 vsctrl
|= VSCTRL_VPIXFMT_UY0VY1
;
381 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
383 case MBXFB_FMT_VY0UY1
:
384 vsctrl
|= VSCTRL_VPIXFMT_VY0UY1
;
385 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
387 case MBXFB_FMT_Y0UY1V
:
388 vsctrl
|= VSCTRL_VPIXFMT_Y0UY1V
;
389 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
391 case MBXFB_FMT_Y0VY1U
:
392 vsctrl
|= VSCTRL_VPIXFMT_Y0VY1U
;
393 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
399 /* VSCTRL has the bits which sets the Video Pixel Format.
400 * When passing from a packed to planar format,
401 * if we write VSCTRL first, VVBASE and VUBASE would
402 * be zero if we would not set them here. (And then,
403 * the chips hangs and only a reset seems to fix it).
405 * If course, the values calculated here have no meaning
406 * for packed formats.
408 set
->UV_stride
= ((set
->width
/2) + 0x7 ) & ~0x7;
409 set
->U_offset
= set
->height
* set
->Y_stride
;
410 set
->V_offset
= set
->U_offset
+
411 set
->height
* set
->UV_stride
;
412 vubase
|= Vubase_Ubase_Adr(
413 (0x60000 + set
->mem_offset
+ set
->U_offset
)>>3);
414 vvbase
|= Vvbase_Vbase_Adr(
415 (0x60000 + set
->mem_offset
+ set
->V_offset
)>>3);
418 vscadr
|= Vscadr_Vbase_Adr((0x60000 + set
->mem_offset
)>>4);
421 vscadr
|= VSCADR_STR_EN
;
424 vsadr
= Vsadr_Srcstride((set
->Y_stride
)/16-1) |
425 Vsadr_Xstart(set
->x
) | Vsadr_Ystart(set
->y
);
427 sssize
&= ~(FMsk(SSSIZE_SC_WIDTH
) | FMsk(SSSIZE_SC_HEIGHT
));
428 sssize
= Sssize_Sc_Width(set
->scaled_width
-1) |
429 Sssize_Sc_Height(set
->scaled_height
-1);
431 spoctrl
&= ~(SPOCTRL_H_SC_BP
| SPOCTRL_V_SC_BP
|
432 SPOCTRL_HV_SC_OR
| SPOCTRL_VS_UR_C
|
433 FMsk(SPOCTRL_VPITCH
));
434 spoctrl
|= Spoctrl_Vpitch((set
->height
<<11)/set
->scaled_height
);
436 /* Bypass horiz/vert scaler when same size */
437 if (set
->scaled_width
== set
->width
)
438 spoctrl
|= SPOCTRL_H_SC_BP
;
439 if (set
->scaled_height
== set
->height
)
440 spoctrl
|= SPOCTRL_V_SC_BP
;
442 shctrl
&= ~(FMsk(SHCTRL_HPITCH
) | SHCTRL_HDECIM
);
443 shctrl
|= Shctrl_Hpitch((set
->width
<<11)/set
->scaled_width
);
445 /* Video plane registers */
446 write_reg(vsctrl
, VSCTRL
);
447 write_reg(vscadr
, VSCADR
);
448 write_reg(vubase
, VUBASE
);
449 write_reg(vvbase
, VVBASE
);
450 write_reg(vsadr
, VSADR
);
452 /* Video scaler registers */
453 write_reg(sssize
, SSSIZE
);
454 write_reg(spoctrl
, SPOCTRL
);
455 write_reg(shctrl
, SHCTRL
);
463 write_reg(vovrclk
, VOVRCLK
);
468 static int mbxfb_ioctl_planeorder(struct mbxfb_planeorder
*porder
)
470 unsigned long gscadr
, vscadr
;
472 if (porder
->bottom
== porder
->top
)
475 gscadr
= readl(GSCADR
);
476 vscadr
= readl(VSCADR
);
478 gscadr
&= ~(FMsk(GSCADR_BLEND_POS
));
479 vscadr
&= ~(FMsk(VSCADR_BLEND_POS
));
481 switch (porder
->bottom
) {
482 case MBXFB_PLANE_GRAPHICS
:
483 gscadr
|= GSCADR_BLEND_GFX
;
485 case MBXFB_PLANE_VIDEO
:
486 vscadr
|= VSCADR_BLEND_GFX
;
492 switch (porder
->top
) {
493 case MBXFB_PLANE_GRAPHICS
:
494 gscadr
|= GSCADR_BLEND_VID
;
496 case MBXFB_PLANE_VIDEO
:
497 vscadr
|= GSCADR_BLEND_VID
;
503 write_reg_dly(vscadr
, VSCADR
);
504 write_reg_dly(gscadr
, GSCADR
);
510 static int mbxfb_ioctl_alphactl(struct mbxfb_alphaCtl
*alpha
)
512 unsigned long vscadr
, vbbase
, vcmsk
;
513 unsigned long gscadr
, gbbase
, gdrctrl
;
515 vbbase
= Vbbase_Glalpha(alpha
->overlay_global_alpha
) |
516 Vbbase_Colkey(alpha
->overlay_colorkey
);
518 gbbase
= Gbbase_Glalpha(alpha
->graphics_global_alpha
) |
519 Gbbase_Colkey(alpha
->graphics_colorkey
);
521 vcmsk
= readl(VCMSK
);
522 vcmsk
&= ~(FMsk(VCMSK_COLKEY_M
));
523 vcmsk
|= Vcmsk_colkey_m(alpha
->overlay_colorkey_mask
);
525 gdrctrl
= readl(GDRCTRL
);
526 gdrctrl
&= ~(FMsk(GDRCTRL_COLKEYM
));
527 gdrctrl
|= Gdrctrl_Colkeym(alpha
->graphics_colorkey_mask
);
529 vscadr
= readl(VSCADR
);
530 vscadr
&= ~(FMsk(VSCADR_BLEND_M
) | VSCADR_COLKEYSRC
| VSCADR_COLKEY_EN
);
532 gscadr
= readl(GSCADR
);
533 gscadr
&= ~(FMsk(GSCADR_BLEND_M
) | GSCADR_COLKEY_EN
| GSCADR_COLKEYSRC
);
535 switch (alpha
->overlay_colorkey_mode
) {
536 case MBXFB_COLORKEY_DISABLED
:
538 case MBXFB_COLORKEY_PREVIOUS
:
539 vscadr
|= VSCADR_COLKEY_EN
;
541 case MBXFB_COLORKEY_CURRENT
:
542 vscadr
|= VSCADR_COLKEY_EN
| VSCADR_COLKEYSRC
;
548 switch (alpha
->overlay_blend_mode
) {
549 case MBXFB_ALPHABLEND_NONE
:
550 vscadr
|= VSCADR_BLEND_NONE
;
552 case MBXFB_ALPHABLEND_GLOBAL
:
553 vscadr
|= VSCADR_BLEND_GLOB
;
555 case MBXFB_ALPHABLEND_PIXEL
:
556 vscadr
|= VSCADR_BLEND_PIX
;
562 switch (alpha
->graphics_colorkey_mode
) {
563 case MBXFB_COLORKEY_DISABLED
:
565 case MBXFB_COLORKEY_PREVIOUS
:
566 gscadr
|= GSCADR_COLKEY_EN
;
568 case MBXFB_COLORKEY_CURRENT
:
569 gscadr
|= GSCADR_COLKEY_EN
| GSCADR_COLKEYSRC
;
575 switch (alpha
->graphics_blend_mode
) {
576 case MBXFB_ALPHABLEND_NONE
:
577 gscadr
|= GSCADR_BLEND_NONE
;
579 case MBXFB_ALPHABLEND_GLOBAL
:
580 gscadr
|= GSCADR_BLEND_GLOB
;
582 case MBXFB_ALPHABLEND_PIXEL
:
583 gscadr
|= GSCADR_BLEND_PIX
;
589 write_reg_dly(vbbase
, VBBASE
);
590 write_reg_dly(gbbase
, GBBASE
);
591 write_reg_dly(vcmsk
, VCMSK
);
592 write_reg_dly(gdrctrl
, GDRCTRL
);
593 write_reg_dly(gscadr
, GSCADR
);
594 write_reg_dly(vscadr
, VSCADR
);
599 static int mbxfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
602 struct mbxfb_overlaySetup setup
;
603 struct mbxfb_planeorder porder
;
604 struct mbxfb_alphaCtl alpha
;
605 struct mbxfb_reg reg
;
611 case MBXFB_IOCX_OVERLAY
:
612 if (copy_from_user(&setup
, (void __user
*)arg
,
613 sizeof(struct mbxfb_overlaySetup
)))
616 res
= mbxfb_setupOverlay(&setup
);
620 if (copy_to_user((void __user
*)arg
, &setup
,
621 sizeof(struct mbxfb_overlaySetup
)))
626 case MBXFB_IOCS_PLANEORDER
:
627 if (copy_from_user(&porder
, (void __user
*)arg
,
628 sizeof(struct mbxfb_planeorder
)))
631 return mbxfb_ioctl_planeorder(&porder
);
633 case MBXFB_IOCS_ALPHA
:
634 if (copy_from_user(&alpha
, (void __user
*)arg
,
635 sizeof(struct mbxfb_alphaCtl
)))
638 return mbxfb_ioctl_alphactl(&alpha
);
641 if (copy_from_user(®
, (void __user
*)arg
,
642 sizeof(struct mbxfb_reg
)))
645 if (reg
.addr
>= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
648 tmp
= readl(virt_base_2700
+ reg
.addr
);
650 tmp
|= reg
.val
& reg
.mask
;
651 writel(tmp
, virt_base_2700
+ reg
.addr
);
655 if (copy_from_user(®
, (void __user
*)arg
,
656 sizeof(struct mbxfb_reg
)))
659 if (reg
.addr
>= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
661 reg
.val
= readl(virt_base_2700
+ reg
.addr
);
663 if (copy_to_user((void __user
*)arg
, ®
,
664 sizeof(struct mbxfb_reg
)))
672 static struct fb_ops mbxfb_ops
= {
673 .owner
= THIS_MODULE
,
674 .fb_check_var
= mbxfb_check_var
,
675 .fb_set_par
= mbxfb_set_par
,
676 .fb_setcolreg
= mbxfb_setcolreg
,
677 .fb_fillrect
= cfb_fillrect
,
678 .fb_copyarea
= cfb_copyarea
,
679 .fb_imageblit
= cfb_imageblit
,
680 .fb_blank
= mbxfb_blank
,
681 .fb_ioctl
= mbxfb_ioctl
,
685 Enable external SDRAM controller. Assume that all clocks are active
688 static void __devinit
setup_memc(struct fb_info
*fbi
)
693 /* setup SDRAM controller */
694 write_reg_dly((LMCFG_LMC_DS
| LMCFG_LMC_TS
| LMCFG_LMD_TS
|
698 write_reg_dly(LMPWR_MC_PWR_ACT
, LMPWR
);
700 /* setup SDRAM timings */
701 write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
702 Lmtim_Trc(9) | Lmtim_Tdpl(2)),
704 /* setup SDRAM refresh rate */
705 write_reg_dly(0xc2b, LMREFRESH
);
706 /* setup SDRAM type parameters */
707 write_reg_dly((LMTYPE_CASLAT_3
| LMTYPE_BKSZ_2
| LMTYPE_ROWSZ_11
|
710 /* enable memory controller */
711 write_reg_dly(LMPWR_MC_PWR_ACT
, LMPWR
);
712 /* perform dummy reads */
713 for ( i
= 0; i
< 16; i
++ ) {
714 tmp
= readl(fbi
->screen_base
);
718 static void enable_clocks(struct fb_info
*fbi
)
721 write_reg_dly(SYSCLKSRC_PLL_2
, SYSCLKSRC
);
722 write_reg_dly(PIXCLKSRC_PLL_1
, PIXCLKSRC
);
723 write_reg_dly(0x00000000, CLKSLEEP
);
725 /* PLL output = (Frefclk * M) / (N * 2^P )
727 * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz!
728 * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz
730 write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) |
734 write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
738 write_reg_dly(0x00000000, VOVRCLK
);
739 write_reg_dly(PIXCLK_EN
, PIXCLK
);
740 write_reg_dly(MEMCLK_EN
, MEMCLK
);
741 write_reg_dly(0x00000001, M24CLK
);
742 write_reg_dly(0x00000001, MBXCLK
);
743 write_reg_dly(SDCLK_EN
, SDCLK
);
744 write_reg_dly(0x00000001, PIXCLKDIV
);
747 static void __devinit
setup_graphics(struct fb_info
*fbi
)
749 unsigned long gsctrl
;
750 unsigned long vscadr
;
752 gsctrl
= GSCTRL_GAMMA_EN
| Gsctrl_Width(fbi
->var
.xres
) |
753 Gsctrl_Height(fbi
->var
.yres
);
754 switch (fbi
->var
.bits_per_pixel
) {
756 if (fbi
->var
.green
.length
== 5)
757 gsctrl
|= GSCTRL_GPIXFMT_ARGB1555
;
759 gsctrl
|= GSCTRL_GPIXFMT_RGB565
;
762 gsctrl
|= GSCTRL_GPIXFMT_RGB888
;
765 gsctrl
|= GSCTRL_GPIXFMT_ARGB8888
;
769 write_reg_dly(gsctrl
, GSCTRL
);
770 write_reg_dly(0x00000000, GBBASE
);
771 write_reg_dly(0x00ffffff, GDRCTRL
);
772 write_reg_dly((GSCADR_STR_EN
| Gscadr_Gbase_Adr(0x6000)), GSCADR
);
773 write_reg_dly(0x00000000, GPLUT
);
775 vscadr
= readl(VSCADR
);
776 vscadr
&= ~(FMsk(VSCADR_BLEND_POS
) | FMsk(VSCADR_BLEND_M
));
777 vscadr
|= VSCADR_BLEND_VID
| VSCADR_BLEND_NONE
;
778 write_reg_dly(vscadr
, VSCADR
);
781 static void __devinit
setup_display(struct fb_info
*fbi
)
783 unsigned long dsctrl
= 0;
785 dsctrl
= DSCTRL_BLNK_POL
;
786 if (fbi
->var
.sync
& FB_SYNC_HOR_HIGH_ACT
)
787 dsctrl
|= DSCTRL_HS_POL
;
788 if (fbi
->var
.sync
& FB_SYNC_VERT_HIGH_ACT
)
789 dsctrl
|= DSCTRL_VS_POL
;
790 write_reg_dly(dsctrl
, DSCTRL
);
791 write_reg_dly(0xd0303010, DMCTRL
);
792 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
795 static void __devinit
enable_controller(struct fb_info
*fbi
)
799 write_reg_dly(SYSRST_RST
, SYSRST
);
801 /* setup a timeout, raise drive strength */
802 write_reg_dly(0xffffff0c, SYSCFG
);
809 shctrl
= readl(SHCTRL
);
810 shctrl
&= ~(FMsk(SHCTRL_HINITIAL
));
811 shctrl
|= Shctrl_Hinitial(4<<11);
812 writel(shctrl
, SHCTRL
);
814 svctrl
= Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
815 writel(svctrl
, SVCTRL
);
817 writel(SPOCTRL_H_SC_BP
| SPOCTRL_V_SC_BP
| SPOCTRL_VORDER_4TAP
820 /* Those coefficients are good for scaling up. For scaling
821 * down, the application has to calculate them. */
822 write_reg(0xff000100, VSCOEFF0
);
823 write_reg(0xfdfcfdfe, VSCOEFF1
);
824 write_reg(0x170d0500, VSCOEFF2
);
825 write_reg(0x3d372d22, VSCOEFF3
);
826 write_reg(0x00000040, VSCOEFF4
);
828 write_reg(0xff010100, HSCOEFF0
);
829 write_reg(0x00000000, HSCOEFF1
);
830 write_reg(0x02010000, HSCOEFF2
);
831 write_reg(0x01020302, HSCOEFF3
);
832 write_reg(0xf9fbfe00, HSCOEFF4
);
833 write_reg(0xfbf7f6f7, HSCOEFF5
);
834 write_reg(0x1c110700, HSCOEFF6
);
835 write_reg(0x3e393127, HSCOEFF7
);
836 write_reg(0x00000040, HSCOEFF8
);
842 * Power management hooks. Note that we won't be called from IRQ context,
843 * unlike the blank functions above, so we may sleep.
845 static int mbxfb_suspend(struct platform_device
*dev
, pm_message_t state
)
847 /* make frame buffer memory enter self-refresh mode */
848 write_reg_dly(LMPWR_MC_PWR_SRM
, LMPWR
);
849 while (LMPWRSTAT
!= LMPWRSTAT_MC_PWR_SRM
)
850 ; /* empty statement */
852 /* reset the device, since it's initial state is 'mostly sleeping' */
853 write_reg_dly(SYSRST_RST
, SYSRST
);
857 static int mbxfb_resume(struct platform_device
*dev
)
859 struct fb_info
*fbi
= platform_get_drvdata(dev
);
862 /* setup_graphics(fbi); */
863 /* setup_display(fbi); */
865 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
869 #define mbxfb_suspend NULL
870 #define mbxfb_resume NULL
873 /* debugfs entries */
874 #ifndef CONFIG_FB_MBX_DEBUG
875 #define mbxfb_debugfs_init(x) do {} while(0)
876 #define mbxfb_debugfs_remove(x) do {} while(0)
879 #define res_size(_r) (((_r)->end - (_r)->start) + 1)
881 static int __devinit
mbxfb_probe(struct platform_device
*dev
)
885 struct mbxfb_info
*mfbi
;
886 struct mbxfb_platform_data
*pdata
;
888 dev_dbg(&dev
->dev
, "mbxfb_probe\n");
890 pdata
= dev
->dev
.platform_data
;
892 dev_err(&dev
->dev
, "platform data is required\n");
896 fbi
= framebuffer_alloc(sizeof(struct mbxfb_info
), &dev
->dev
);
898 dev_err(&dev
->dev
, "framebuffer_alloc failed\n");
903 fbi
->pseudo_palette
= mfbi
->pseudo_palette
;
907 mfbi
->platform_probe
= pdata
->probe
;
909 mfbi
->platform_remove
= pdata
->remove
;
911 mfbi
->fb_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
912 mfbi
->reg_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 1);
914 if (!mfbi
->fb_res
|| !mfbi
->reg_res
) {
915 dev_err(&dev
->dev
, "no resources found\n");
920 mfbi
->fb_req
= request_mem_region(mfbi
->fb_res
->start
,
921 res_size(mfbi
->fb_res
), dev
->name
);
922 if (mfbi
->fb_req
== NULL
) {
923 dev_err(&dev
->dev
, "failed to claim framebuffer memory\n");
927 mfbi
->fb_phys_addr
= mfbi
->fb_res
->start
;
929 mfbi
->reg_req
= request_mem_region(mfbi
->reg_res
->start
,
930 res_size(mfbi
->reg_res
), dev
->name
);
931 if (mfbi
->reg_req
== NULL
) {
932 dev_err(&dev
->dev
, "failed to claim Marathon registers\n");
936 mfbi
->reg_phys_addr
= mfbi
->reg_res
->start
;
938 mfbi
->reg_virt_addr
= ioremap_nocache(mfbi
->reg_phys_addr
,
939 res_size(mfbi
->reg_req
));
940 if (!mfbi
->reg_virt_addr
) {
941 dev_err(&dev
->dev
, "failed to ioremap Marathon registers\n");
945 virt_base_2700
= (unsigned long)mfbi
->reg_virt_addr
;
947 mfbi
->fb_virt_addr
= ioremap_nocache(mfbi
->fb_phys_addr
,
948 res_size(mfbi
->fb_req
));
949 if (!mfbi
->reg_virt_addr
) {
950 dev_err(&dev
->dev
, "failed to ioremap frame buffer\n");
955 fbi
->screen_base
= (char __iomem
*)(mfbi
->fb_virt_addr
+ 0x60000);
956 fbi
->screen_size
= pdata
->memsize
;
957 fbi
->fbops
= &mbxfb_ops
;
959 fbi
->var
= mbxfb_default
;
960 fbi
->fix
= mbxfb_fix
;
961 fbi
->fix
.smem_start
= mfbi
->fb_phys_addr
+ 0x60000;
962 fbi
->fix
.smem_len
= pdata
->memsize
;
963 fbi
->fix
.line_length
= mbxfb_default
.xres_virtual
*
964 mbxfb_default
.bits_per_pixel
/ 8;
966 ret
= fb_alloc_cmap(&fbi
->cmap
, 256, 0);
968 dev_err(&dev
->dev
, "fb_alloc_cmap failed\n");
973 platform_set_drvdata(dev
, fbi
);
975 printk(KERN_INFO
"fb%d: mbx frame buffer device\n", fbi
->node
);
977 if (mfbi
->platform_probe
)
978 mfbi
->platform_probe(fbi
);
980 enable_controller(fbi
);
982 mbxfb_debugfs_init(fbi
);
984 ret
= register_framebuffer(fbi
);
986 dev_err(&dev
->dev
, "register_framebuffer failed\n");
994 fb_dealloc_cmap(&fbi
->cmap
);
996 iounmap(mfbi
->fb_virt_addr
);
998 iounmap(mfbi
->reg_virt_addr
);
1000 release_mem_region(mfbi
->reg_res
->start
, res_size(mfbi
->reg_res
));
1002 release_mem_region(mfbi
->fb_res
->start
, res_size(mfbi
->fb_res
));
1004 framebuffer_release(fbi
);
1009 static int __devexit
mbxfb_remove(struct platform_device
*dev
)
1011 struct fb_info
*fbi
= platform_get_drvdata(dev
);
1013 write_reg_dly(SYSRST_RST
, SYSRST
);
1015 mbxfb_debugfs_remove(fbi
);
1018 struct mbxfb_info
*mfbi
= fbi
->par
;
1020 unregister_framebuffer(fbi
);
1022 if (mfbi
->platform_remove
)
1023 mfbi
->platform_remove(fbi
);
1025 if (mfbi
->fb_virt_addr
)
1026 iounmap(mfbi
->fb_virt_addr
);
1027 if (mfbi
->reg_virt_addr
)
1028 iounmap(mfbi
->reg_virt_addr
);
1030 release_mem_region(mfbi
->reg_req
->start
,
1031 res_size(mfbi
->reg_req
));
1033 release_mem_region(mfbi
->fb_req
->start
,
1034 res_size(mfbi
->fb_req
));
1036 framebuffer_release(fbi
);
1042 static struct platform_driver mbxfb_driver
= {
1043 .probe
= mbxfb_probe
,
1044 .remove
= mbxfb_remove
,
1045 .suspend
= mbxfb_suspend
,
1046 .resume
= mbxfb_resume
,
1052 int __devinit
mbxfb_init(void)
1054 return platform_driver_register(&mbxfb_driver
);
1057 static void __devexit
mbxfb_exit(void)
1059 platform_driver_unregister(&mbxfb_driver
);
1062 module_init(mbxfb_init
);
1063 module_exit(mbxfb_exit
);
1065 MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
1066 MODULE_AUTHOR("Mike Rapoport, Compulab");
1067 MODULE_LICENSE("GPL");