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 /* FIXME: take care of different chip revisions with different sizes
56 #define MEMORY_OFFSET 0x60000
61 struct resource
*fb_res
;
62 struct resource
*fb_req
;
64 struct resource
*reg_res
;
65 struct resource
*reg_req
;
67 void __iomem
*fb_virt_addr
;
68 unsigned long fb_phys_addr
;
70 void __iomem
*reg_virt_addr
;
71 unsigned long reg_phys_addr
;
73 int (*platform_probe
) (struct fb_info
* fb
);
74 int (*platform_remove
) (struct fb_info
* fb
);
76 u32 pseudo_palette
[MAX_PALETTES
];
77 #ifdef CONFIG_FB_MBX_DEBUG
83 static struct fb_var_screeninfo mbxfb_default __devinitdata
= {
92 .activate
= FB_ACTIVATE_TEST
,
102 .vmode
= FB_VMODE_NONINTERLACED
,
103 .sync
= FB_SYNC_HOR_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
106 static struct fb_fix_screeninfo mbxfb_fix __devinitdata
= {
108 .type
= FB_TYPE_PACKED_PIXELS
,
109 .visual
= FB_VISUAL_TRUECOLOR
,
113 .accel
= FB_ACCEL_NONE
,
116 struct pixclock_div
{
122 static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps
,
123 struct pixclock_div
*div
)
126 unsigned int err
= 0;
127 unsigned int min_err
= ~0x0;
129 unsigned int best_clk
= 0;
130 unsigned int ref_clk
= 13000; /* FIXME: take from platform data */
131 unsigned int pixclock
;
133 /* convert pixclock to KHz */
134 pixclock
= PICOS2KHZ(pixclock_ps
);
136 /* PLL output freq = (ref_clk * M) / (N * 2^P)
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
) :
163 return KHZ2PICOS(best_clk
);
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
)
171 if (regno
< MAX_PALETTES
) {
172 u32
*pal
= info
->pseudo_palette
;
174 val
= (red
& 0xf800) | ((green
& 0xfc00) >> 5) |
175 ((blue
& 0xf800) >> 11);
183 static int mbxfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
185 struct pixclock_div div
;
187 var
->pixclock
= mbxfb_get_pixclock(var
->pixclock
, &div
);
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
)
195 if (var
->yres
> MAX_YRES
)
197 var
->xres_virtual
= max(var
->xres_virtual
, var
->xres
);
198 var
->yres_virtual
= max(var
->yres_virtual
, var
->yres
);
200 switch (var
->bits_per_pixel
) {
201 /* 8 bits-per-pixel is not supported yet */
205 var
->green
.length
= (var
->green
.length
== 5) ? 5 : 6;
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;
214 case 24: /* RGB 888 */
215 case 32: /* RGBA 8888 */
216 var
->red
.offset
= 16;
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;
226 var
->red
.msb_right
= 0;
227 var
->green
.msb_right
= 0;
228 var
->blue
.msb_right
= 0;
229 var
->transp
.msb_right
= 0;
234 static int mbxfb_set_par(struct fb_info
*info
)
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
);
243 info
->fix
.line_length
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
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) {
251 fb_dealloc_cmap(&info
->cmap
);
252 gsctrl
&= ~GSCTRL_LUT_EN
;
254 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
255 switch (info
->var
.bits_per_pixel
) {
257 if (info
->var
.green
.length
== 5)
258 gsctrl
|= GSCTRL_GPIXFMT_ARGB1555
;
260 gsctrl
|= GSCTRL_GPIXFMT_RGB565
;
263 gsctrl
|= GSCTRL_GPIXFMT_RGB888
;
266 gsctrl
|= GSCTRL_GPIXFMT_ARGB8888
;
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
);
277 gsadr
&= ~(FMsk(GSADR_SRCSTRIDE
));
278 gsadr
|= Gsadr_Srcstride(info
->var
.xres
* info
->var
.bits_per_pixel
/
280 write_reg_dly(gsadr
, GSADR
);
283 var
->pixclock
= mbxfb_get_pixclock(info
->var
.pixclock
, &div
);
285 write_reg_dly((Disp_Pll_M(div
.m
) | Disp_Pll_N(div
.n
) |
286 Disp_Pll_P(div
.p
) | DISP_PLL_EN
), DISPPLL
);
288 hbps
= var
->hsync_len
;
289 has
= hbps
+ var
->left_margin
;
290 hfps
= has
+ var
->xres
;
291 ht
= hfps
+ var
->right_margin
;
293 vbps
= var
->vsync_len
;
294 vas
= vbps
+ var
->upper_margin
;
295 vfps
= vas
+ var
->yres
;
296 vt
= vfps
+ var
->lower_margin
;
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
);
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
);
309 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
311 write_reg_dly(DINTRE_VEVENT0_EN
, DINTRE
);
316 static int mbxfb_blank(int blank
, struct fb_info
*info
)
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
);
327 case FB_BLANK_UNBLANK
:
328 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
329 write_reg_dly((readl(PIXCLK
) | PIXCLK_EN
), PIXCLK
);
335 static int mbxfb_setupOverlay(struct mbxfb_overlaySetup
*set
)
337 u32 vsctrl
, vscadr
, vsadr
;
338 u32 sssize
, spoctrl
, shctrl
;
342 if (set
->scaled_width
==0 || set
->scaled_height
==0)
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 shctrl
= readl(SHCTRL
);
354 spoctrl
= readl(SPOCTRL
);
355 sssize
= readl(SSSIZE
);
357 vsctrl
&= ~( FMsk(VSCTRL_VSWIDTH
) |
358 FMsk(VSCTRL_VSHEIGHT
) |
359 FMsk(VSCTRL_VPIXFMT
) |
360 VSCTRL_GAMMA_EN
| VSCTRL_CSC_EN
|
362 vsctrl
|= Vsctrl_Width(set
->width
) | Vsctrl_Height(set
->height
) |
365 vscadr
&= ~(VSCADR_STR_EN
| FMsk(VSCADR_VBASE_ADR
) );
366 vubase
&= ~(VUBASE_UVHALFSTR
| FMsk(VUBASE_UBASE_ADR
));
367 vvbase
&= ~(FMsk(VVBASE_VBASE_ADR
));
370 case MBXFB_FMT_YUV16
:
371 vsctrl
|= VSCTRL_VPIXFMT_YUV12
;
373 set
->Y_stride
= ((set
->width
) + 0xf ) & ~0xf;
375 case MBXFB_FMT_YUV12
:
376 vsctrl
|= VSCTRL_VPIXFMT_YUV12
;
378 set
->Y_stride
= ((set
->width
) + 0xf ) & ~0xf;
379 vubase
|= VUBASE_UVHALFSTR
;
382 case MBXFB_FMT_UY0VY1
:
383 vsctrl
|= VSCTRL_VPIXFMT_UY0VY1
;
384 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
386 case MBXFB_FMT_VY0UY1
:
387 vsctrl
|= VSCTRL_VPIXFMT_VY0UY1
;
388 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
390 case MBXFB_FMT_Y0UY1V
:
391 vsctrl
|= VSCTRL_VPIXFMT_Y0UY1V
;
392 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
394 case MBXFB_FMT_Y0VY1U
:
395 vsctrl
|= VSCTRL_VPIXFMT_Y0VY1U
;
396 set
->Y_stride
= (set
->width
*2 + 0xf ) & ~0xf;
402 /* VSCTRL has the bits which sets the Video Pixel Format.
403 * When passing from a packed to planar format,
404 * if we write VSCTRL first, VVBASE and VUBASE would
405 * be zero if we would not set them here. (And then,
406 * the chips hangs and only a reset seems to fix it).
408 * If course, the values calculated here have no meaning
409 * for packed formats.
411 set
->UV_stride
= ((set
->width
/2) + 0x7 ) & ~0x7;
412 set
->U_offset
= set
->height
* set
->Y_stride
;
413 set
->V_offset
= set
->U_offset
+
414 set
->height
* set
->UV_stride
;
415 vubase
|= Vubase_Ubase_Adr(
416 (0x60000 + set
->mem_offset
+ set
->U_offset
)>>3);
417 vvbase
|= Vvbase_Vbase_Adr(
418 (0x60000 + set
->mem_offset
+ set
->V_offset
)>>3);
421 vscadr
|= Vscadr_Vbase_Adr((0x60000 + set
->mem_offset
)>>4);
424 vscadr
|= VSCADR_STR_EN
;
427 vsadr
= Vsadr_Srcstride((set
->Y_stride
)/16-1) |
428 Vsadr_Xstart(set
->x
) | Vsadr_Ystart(set
->y
);
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);
434 spoctrl
&= ~(SPOCTRL_H_SC_BP
| SPOCTRL_V_SC_BP
|
435 SPOCTRL_HV_SC_OR
| SPOCTRL_VS_UR_C
|
436 FMsk(SPOCTRL_VPITCH
));
437 spoctrl
|= Spoctrl_Vpitch((set
->height
<<11)/set
->scaled_height
);
439 /* Bypass horiz/vert scaler when same size */
440 if (set
->scaled_width
== set
->width
)
441 spoctrl
|= SPOCTRL_H_SC_BP
;
442 if (set
->scaled_height
== set
->height
)
443 spoctrl
|= SPOCTRL_V_SC_BP
;
445 shctrl
&= ~(FMsk(SHCTRL_HPITCH
) | SHCTRL_HDECIM
);
446 shctrl
|= Shctrl_Hpitch((set
->width
<<11)/set
->scaled_width
);
448 /* Video plane registers */
449 write_reg(vsctrl
, VSCTRL
);
450 write_reg(vscadr
, VSCADR
);
451 write_reg(vubase
, VUBASE
);
452 write_reg(vvbase
, VVBASE
);
453 write_reg(vsadr
, VSADR
);
455 /* Video scaler registers */
456 write_reg(sssize
, SSSIZE
);
457 write_reg(spoctrl
, SPOCTRL
);
458 write_reg(shctrl
, SHCTRL
);
466 write_reg(vovrclk
, VOVRCLK
);
471 static int mbxfb_ioctl_planeorder(struct mbxfb_planeorder
*porder
)
473 unsigned long gscadr
, vscadr
;
475 if (porder
->bottom
== porder
->top
)
478 gscadr
= readl(GSCADR
);
479 vscadr
= readl(VSCADR
);
481 gscadr
&= ~(FMsk(GSCADR_BLEND_POS
));
482 vscadr
&= ~(FMsk(VSCADR_BLEND_POS
));
484 switch (porder
->bottom
) {
485 case MBXFB_PLANE_GRAPHICS
:
486 gscadr
|= GSCADR_BLEND_GFX
;
488 case MBXFB_PLANE_VIDEO
:
489 vscadr
|= VSCADR_BLEND_GFX
;
495 switch (porder
->top
) {
496 case MBXFB_PLANE_GRAPHICS
:
497 gscadr
|= GSCADR_BLEND_VID
;
499 case MBXFB_PLANE_VIDEO
:
500 vscadr
|= GSCADR_BLEND_VID
;
506 write_reg_dly(vscadr
, VSCADR
);
507 write_reg_dly(gscadr
, GSCADR
);
513 static int mbxfb_ioctl_alphactl(struct mbxfb_alphaCtl
*alpha
)
515 unsigned long vscadr
, vbbase
, vcmsk
;
516 unsigned long gscadr
, gbbase
, gdrctrl
;
518 vbbase
= Vbbase_Glalpha(alpha
->overlay_global_alpha
) |
519 Vbbase_Colkey(alpha
->overlay_colorkey
);
521 gbbase
= Gbbase_Glalpha(alpha
->graphics_global_alpha
) |
522 Gbbase_Colkey(alpha
->graphics_colorkey
);
524 vcmsk
= readl(VCMSK
);
525 vcmsk
&= ~(FMsk(VCMSK_COLKEY_M
));
526 vcmsk
|= Vcmsk_colkey_m(alpha
->overlay_colorkey_mask
);
528 gdrctrl
= readl(GDRCTRL
);
529 gdrctrl
&= ~(FMsk(GDRCTRL_COLKEYM
));
530 gdrctrl
|= Gdrctrl_Colkeym(alpha
->graphics_colorkey_mask
);
532 vscadr
= readl(VSCADR
);
533 vscadr
&= ~(FMsk(VSCADR_BLEND_M
) | VSCADR_COLKEYSRC
| VSCADR_COLKEY_EN
);
535 gscadr
= readl(GSCADR
);
536 gscadr
&= ~(FMsk(GSCADR_BLEND_M
) | GSCADR_COLKEY_EN
| GSCADR_COLKEYSRC
);
538 switch (alpha
->overlay_colorkey_mode
) {
539 case MBXFB_COLORKEY_DISABLED
:
541 case MBXFB_COLORKEY_PREVIOUS
:
542 vscadr
|= VSCADR_COLKEY_EN
;
544 case MBXFB_COLORKEY_CURRENT
:
545 vscadr
|= VSCADR_COLKEY_EN
| VSCADR_COLKEYSRC
;
551 switch (alpha
->overlay_blend_mode
) {
552 case MBXFB_ALPHABLEND_NONE
:
553 vscadr
|= VSCADR_BLEND_NONE
;
555 case MBXFB_ALPHABLEND_GLOBAL
:
556 vscadr
|= VSCADR_BLEND_GLOB
;
558 case MBXFB_ALPHABLEND_PIXEL
:
559 vscadr
|= VSCADR_BLEND_PIX
;
565 switch (alpha
->graphics_colorkey_mode
) {
566 case MBXFB_COLORKEY_DISABLED
:
568 case MBXFB_COLORKEY_PREVIOUS
:
569 gscadr
|= GSCADR_COLKEY_EN
;
571 case MBXFB_COLORKEY_CURRENT
:
572 gscadr
|= GSCADR_COLKEY_EN
| GSCADR_COLKEYSRC
;
578 switch (alpha
->graphics_blend_mode
) {
579 case MBXFB_ALPHABLEND_NONE
:
580 gscadr
|= GSCADR_BLEND_NONE
;
582 case MBXFB_ALPHABLEND_GLOBAL
:
583 gscadr
|= GSCADR_BLEND_GLOB
;
585 case MBXFB_ALPHABLEND_PIXEL
:
586 gscadr
|= GSCADR_BLEND_PIX
;
592 write_reg_dly(vbbase
, VBBASE
);
593 write_reg_dly(gbbase
, GBBASE
);
594 write_reg_dly(vcmsk
, VCMSK
);
595 write_reg_dly(gdrctrl
, GDRCTRL
);
596 write_reg_dly(gscadr
, GSCADR
);
597 write_reg_dly(vscadr
, VSCADR
);
602 static int mbxfb_ioctl(struct fb_info
*info
, unsigned int cmd
,
605 struct mbxfb_overlaySetup setup
;
606 struct mbxfb_planeorder porder
;
607 struct mbxfb_alphaCtl alpha
;
608 struct mbxfb_reg reg
;
614 case MBXFB_IOCX_OVERLAY
:
615 if (copy_from_user(&setup
, (void __user
*)arg
,
616 sizeof(struct mbxfb_overlaySetup
)))
619 res
= mbxfb_setupOverlay(&setup
);
623 if (copy_to_user((void __user
*)arg
, &setup
,
624 sizeof(struct mbxfb_overlaySetup
)))
629 case MBXFB_IOCS_PLANEORDER
:
630 if (copy_from_user(&porder
, (void __user
*)arg
,
631 sizeof(struct mbxfb_planeorder
)))
634 return mbxfb_ioctl_planeorder(&porder
);
636 case MBXFB_IOCS_ALPHA
:
637 if (copy_from_user(&alpha
, (void __user
*)arg
,
638 sizeof(struct mbxfb_alphaCtl
)))
641 return mbxfb_ioctl_alphactl(&alpha
);
644 if (copy_from_user(®
, (void __user
*)arg
,
645 sizeof(struct mbxfb_reg
)))
648 if (reg
.addr
>= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
651 tmp
= readl(virt_base_2700
+ reg
.addr
);
653 tmp
|= reg
.val
& reg
.mask
;
654 writel(tmp
, virt_base_2700
+ reg
.addr
);
658 if (copy_from_user(®
, (void __user
*)arg
,
659 sizeof(struct mbxfb_reg
)))
662 if (reg
.addr
>= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */
664 reg
.val
= readl(virt_base_2700
+ reg
.addr
);
666 if (copy_to_user((void __user
*)arg
, ®
,
667 sizeof(struct mbxfb_reg
)))
675 static struct fb_ops mbxfb_ops
= {
676 .owner
= THIS_MODULE
,
677 .fb_check_var
= mbxfb_check_var
,
678 .fb_set_par
= mbxfb_set_par
,
679 .fb_setcolreg
= mbxfb_setcolreg
,
680 .fb_fillrect
= cfb_fillrect
,
681 .fb_copyarea
= cfb_copyarea
,
682 .fb_imageblit
= cfb_imageblit
,
683 .fb_blank
= mbxfb_blank
,
684 .fb_ioctl
= mbxfb_ioctl
,
688 Enable external SDRAM controller. Assume that all clocks are active
691 static void __devinit
setup_memc(struct fb_info
*fbi
)
696 /* FIXME: use platfrom specific parameters */
697 /* setup SDRAM controller */
698 write_reg_dly((LMCFG_LMC_DS
| LMCFG_LMC_TS
| LMCFG_LMD_TS
|
702 write_reg_dly(LMPWR_MC_PWR_ACT
, LMPWR
);
704 /* setup SDRAM timings */
705 write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
706 Lmtim_Trc(9) | Lmtim_Tdpl(2)),
708 /* setup SDRAM refresh rate */
709 write_reg_dly(0xc2b, LMREFRESH
);
710 /* setup SDRAM type parameters */
711 write_reg_dly((LMTYPE_CASLAT_3
| LMTYPE_BKSZ_2
| LMTYPE_ROWSZ_11
|
714 /* enable memory controller */
715 write_reg_dly(LMPWR_MC_PWR_ACT
, LMPWR
);
716 /* perform dummy reads */
717 for ( i
= 0; i
< 16; i
++ ) {
718 tmp
= readl(fbi
->screen_base
);
722 static void enable_clocks(struct fb_info
*fbi
)
725 write_reg_dly(SYSCLKSRC_PLL_2
, SYSCLKSRC
);
726 write_reg_dly(PIXCLKSRC_PLL_1
, PIXCLKSRC
);
727 write_reg_dly(0x00000000, CLKSLEEP
);
729 /* PLL output = (Frefclk * M) / (N * 2^P )
731 * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz!
732 * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz
734 write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) |
738 write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
742 write_reg_dly(0x00000000, VOVRCLK
);
743 write_reg_dly(PIXCLK_EN
, PIXCLK
);
744 write_reg_dly(MEMCLK_EN
, MEMCLK
);
745 write_reg_dly(0x00000001, M24CLK
);
746 write_reg_dly(0x00000001, MBXCLK
);
747 write_reg_dly(SDCLK_EN
, SDCLK
);
748 write_reg_dly(0x00000001, PIXCLKDIV
);
751 static void __devinit
setup_graphics(struct fb_info
*fbi
)
753 unsigned long gsctrl
;
754 unsigned long vscadr
;
756 gsctrl
= GSCTRL_GAMMA_EN
| Gsctrl_Width(fbi
->var
.xres
) |
757 Gsctrl_Height(fbi
->var
.yres
);
758 switch (fbi
->var
.bits_per_pixel
) {
760 if (fbi
->var
.green
.length
== 5)
761 gsctrl
|= GSCTRL_GPIXFMT_ARGB1555
;
763 gsctrl
|= GSCTRL_GPIXFMT_RGB565
;
766 gsctrl
|= GSCTRL_GPIXFMT_RGB888
;
769 gsctrl
|= GSCTRL_GPIXFMT_ARGB8888
;
773 write_reg_dly(gsctrl
, GSCTRL
);
774 write_reg_dly(0x00000000, GBBASE
);
775 write_reg_dly(0x00ffffff, GDRCTRL
);
776 write_reg_dly((GSCADR_STR_EN
| Gscadr_Gbase_Adr(0x6000)), GSCADR
);
777 write_reg_dly(0x00000000, GPLUT
);
779 vscadr
= readl(VSCADR
);
780 vscadr
&= ~(FMsk(VSCADR_BLEND_POS
) | FMsk(VSCADR_BLEND_M
));
781 vscadr
|= VSCADR_BLEND_VID
| VSCADR_BLEND_NONE
;
782 write_reg_dly(vscadr
, VSCADR
);
785 static void __devinit
setup_display(struct fb_info
*fbi
)
787 unsigned long dsctrl
= 0;
789 dsctrl
= DSCTRL_BLNK_POL
;
790 if (fbi
->var
.sync
& FB_SYNC_HOR_HIGH_ACT
)
791 dsctrl
|= DSCTRL_HS_POL
;
792 if (fbi
->var
.sync
& FB_SYNC_VERT_HIGH_ACT
)
793 dsctrl
|= DSCTRL_VS_POL
;
794 write_reg_dly(dsctrl
, DSCTRL
);
795 write_reg_dly(0xd0303010, DMCTRL
);
796 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
799 static void __devinit
enable_controller(struct fb_info
*fbi
)
803 write_reg_dly(SYSRST_RST
, SYSRST
);
805 /* setup a timeout, raise drive strength */
806 write_reg_dly(0xffffff0c, SYSCFG
);
813 shctrl
= readl(SHCTRL
);
814 shctrl
&= ~(FMsk(SHCTRL_HINITIAL
));
815 shctrl
|= Shctrl_Hinitial(4<<11);
816 writel(shctrl
, SHCTRL
);
818 svctrl
= Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
819 writel(svctrl
, SVCTRL
);
821 writel(SPOCTRL_H_SC_BP
| SPOCTRL_V_SC_BP
| SPOCTRL_VORDER_4TAP
824 /* Those coefficients are good for scaling up. For scaling
825 * down, the application has to calculate them. */
826 write_reg(0xff000100, VSCOEFF0
);
827 write_reg(0xfdfcfdfe, VSCOEFF1
);
828 write_reg(0x170d0500, VSCOEFF2
);
829 write_reg(0x3d372d22, VSCOEFF3
);
830 write_reg(0x00000040, VSCOEFF4
);
832 write_reg(0xff010100, HSCOEFF0
);
833 write_reg(0x00000000, HSCOEFF1
);
834 write_reg(0x02010000, HSCOEFF2
);
835 write_reg(0x01020302, HSCOEFF3
);
836 write_reg(0xf9fbfe00, HSCOEFF4
);
837 write_reg(0xfbf7f6f7, HSCOEFF5
);
838 write_reg(0x1c110700, HSCOEFF6
);
839 write_reg(0x3e393127, HSCOEFF7
);
840 write_reg(0x00000040, HSCOEFF8
);
846 * Power management hooks. Note that we won't be called from IRQ context,
847 * unlike the blank functions above, so we may sleep.
849 static int mbxfb_suspend(struct platform_device
*dev
, pm_message_t state
)
851 /* make frame buffer memory enter self-refresh mode */
852 write_reg_dly(LMPWR_MC_PWR_SRM
, LMPWR
);
853 while (LMPWRSTAT
!= LMPWRSTAT_MC_PWR_SRM
)
854 ; /* empty statement */
856 /* reset the device, since it's initial state is 'mostly sleeping' */
857 write_reg_dly(SYSRST_RST
, SYSRST
);
861 static int mbxfb_resume(struct platform_device
*dev
)
863 struct fb_info
*fbi
= platform_get_drvdata(dev
);
866 /* setup_graphics(fbi); */
867 /* setup_display(fbi); */
869 write_reg_dly((readl(DSCTRL
) | DSCTRL_SYNCGEN_EN
), DSCTRL
);
873 #define mbxfb_suspend NULL
874 #define mbxfb_resume NULL
877 /* debugfs entries */
878 #ifndef CONFIG_FB_MBX_DEBUG
879 #define mbxfb_debugfs_init(x) do {} while(0)
880 #define mbxfb_debugfs_remove(x) do {} while(0)
883 #define res_size(_r) (((_r)->end - (_r)->start) + 1)
885 static int __devinit
mbxfb_probe(struct platform_device
*dev
)
889 struct mbxfb_info
*mfbi
;
890 struct mbxfb_platform_data
*pdata
;
892 dev_dbg(dev
, "mbxfb_probe\n");
894 pdata
= dev
->dev
.platform_data
;
896 dev_err(&dev
->dev
, "platform data is required\n");
900 fbi
= framebuffer_alloc(sizeof(struct mbxfb_info
), &dev
->dev
);
902 dev_err(&dev
->dev
, "framebuffer_alloc failed\n");
907 fbi
->pseudo_palette
= mfbi
->pseudo_palette
;
911 mfbi
->platform_probe
= pdata
->probe
;
913 mfbi
->platform_remove
= pdata
->remove
;
915 mfbi
->fb_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
916 mfbi
->reg_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 1);
918 if (!mfbi
->fb_res
|| !mfbi
->reg_res
) {
919 dev_err(&dev
->dev
, "no resources found\n");
924 mfbi
->fb_req
= request_mem_region(mfbi
->fb_res
->start
,
925 res_size(mfbi
->fb_res
), dev
->name
);
926 if (mfbi
->fb_req
== NULL
) {
927 dev_err(&dev
->dev
, "failed to claim framebuffer memory\n");
931 mfbi
->fb_phys_addr
= mfbi
->fb_res
->start
;
933 mfbi
->reg_req
= request_mem_region(mfbi
->reg_res
->start
,
934 res_size(mfbi
->reg_res
), dev
->name
);
935 if (mfbi
->reg_req
== NULL
) {
936 dev_err(&dev
->dev
, "failed to claim Marathon registers\n");
940 mfbi
->reg_phys_addr
= mfbi
->reg_res
->start
;
942 mfbi
->reg_virt_addr
= ioremap_nocache(mfbi
->reg_phys_addr
,
943 res_size(mfbi
->reg_req
));
944 if (!mfbi
->reg_virt_addr
) {
945 dev_err(&dev
->dev
, "failed to ioremap Marathon registers\n");
949 virt_base_2700
= (unsigned long)mfbi
->reg_virt_addr
;
951 mfbi
->fb_virt_addr
= ioremap_nocache(mfbi
->fb_phys_addr
,
952 res_size(mfbi
->fb_req
));
953 if (!mfbi
->reg_virt_addr
) {
954 dev_err(&dev
->dev
, "failed to ioremap frame buffer\n");
959 fbi
->screen_base
= (char __iomem
*)(mfbi
->fb_virt_addr
+ 0x60000);
960 fbi
->screen_size
= pdata
->memsize
;
961 fbi
->fbops
= &mbxfb_ops
;
963 fbi
->var
= mbxfb_default
;
964 fbi
->fix
= mbxfb_fix
;
965 fbi
->fix
.smem_start
= mfbi
->fb_phys_addr
+ 0x60000;
966 fbi
->fix
.smem_len
= pdata
->memsize
;
967 fbi
->fix
.line_length
= mbxfb_default
.xres_virtual
*
968 mbxfb_default
.bits_per_pixel
/ 8;
970 ret
= fb_alloc_cmap(&fbi
->cmap
, 256, 0);
972 dev_err(&dev
->dev
, "fb_alloc_cmap failed\n");
977 platform_set_drvdata(dev
, fbi
);
979 printk(KERN_INFO
"fb%d: mbx frame buffer device\n", fbi
->node
);
981 if (mfbi
->platform_probe
)
982 mfbi
->platform_probe(fbi
);
984 enable_controller(fbi
);
986 mbxfb_debugfs_init(fbi
);
988 ret
= register_framebuffer(fbi
);
990 dev_err(&dev
->dev
, "register_framebuffer failed\n");
998 fb_dealloc_cmap(&fbi
->cmap
);
1000 iounmap(mfbi
->fb_virt_addr
);
1002 iounmap(mfbi
->reg_virt_addr
);
1004 release_mem_region(mfbi
->reg_res
->start
, res_size(mfbi
->reg_res
));
1006 release_mem_region(mfbi
->fb_res
->start
, res_size(mfbi
->fb_res
));
1008 framebuffer_release(fbi
);
1013 static int __devexit
mbxfb_remove(struct platform_device
*dev
)
1015 struct fb_info
*fbi
= platform_get_drvdata(dev
);
1017 write_reg_dly(SYSRST_RST
, SYSRST
);
1019 mbxfb_debugfs_remove(fbi
);
1022 struct mbxfb_info
*mfbi
= fbi
->par
;
1024 unregister_framebuffer(fbi
);
1026 if (mfbi
->platform_remove
)
1027 mfbi
->platform_remove(fbi
);
1029 if (mfbi
->fb_virt_addr
)
1030 iounmap(mfbi
->fb_virt_addr
);
1031 if (mfbi
->reg_virt_addr
)
1032 iounmap(mfbi
->reg_virt_addr
);
1034 release_mem_region(mfbi
->reg_req
->start
,
1035 res_size(mfbi
->reg_req
));
1037 release_mem_region(mfbi
->fb_req
->start
,
1038 res_size(mfbi
->fb_req
));
1040 framebuffer_release(fbi
);
1046 static struct platform_driver mbxfb_driver
= {
1047 .probe
= mbxfb_probe
,
1048 .remove
= mbxfb_remove
,
1049 .suspend
= mbxfb_suspend
,
1050 .resume
= mbxfb_resume
,
1056 int __devinit
mbxfb_init(void)
1058 return platform_driver_register(&mbxfb_driver
);
1061 static void __devexit
mbxfb_exit(void)
1063 platform_driver_unregister(&mbxfb_driver
);
1066 module_init(mbxfb_init
);
1067 module_exit(mbxfb_exit
);
1069 MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
1070 MODULE_AUTHOR("Mike Rapoport, Compulab");
1071 MODULE_LICENSE("GPL");