aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaphael Assenat <raph@8d.com>2006-12-08 05:40:36 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-08 11:29:06 -0500
commitea465250d41c99b4ee7dac1e6eb87b7106f7b11e (patch)
treec9c4d883562b14121390f6736f9ee3e6616d7f57
parent128806c3b3e263c579af12c061a9b04db3950016 (diff)
[PATCH] mbxfb: Add YUV video overlay support
This patch adds a way to create and use the video plane (YUV overlay) and scaling video scaling features of the chip. The overlay is configured, resized and modified using a device specific ioctl. Also included in this patch: - If no platform data was passed, print an error and exit instead of crashing. - Added a write_reg(_dly) macro. This improves readability when manipulating chip registers. (no more udelay() after each write). - Comments about some issues. Signed-off-by: Raphael Assenat <raph@8d.com> Cc: "Antonino A. Daplas" <adaplas@pol.net> Acked-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/video/mbx/mbxfb.c359
-rw-r--r--include/video/mbxfb.h31
2 files changed, 302 insertions, 88 deletions
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index a32d1af79e07..980d5f623902 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -1,8 +1,14 @@
1/* 1/*
2 * linux/drivers/video/mbx/mbxfb.c 2 * linux/drivers/video/mbx/mbxfb.c
3 * 3 *
4 * Copyright (C) 2006 8D Technologies inc
5 * Raphael Assenat <raph@8d.com>
6 * - Added video overlay support
7 * - Various improvements
8 *
4 * Copyright (C) 2006 Compulab, Ltd. 9 * Copyright (C) 2006 Compulab, Ltd.
5 * Mike Rapoport <mike@compulab.co.il> 10 * Mike Rapoport <mike@compulab.co.il>
11 * - Creation of driver
6 * 12 *
7 * Based on pxafb.c 13 * Based on pxafb.c
8 * 14 *
@@ -19,6 +25,7 @@
19#include <linux/init.h> 25#include <linux/init.h>
20#include <linux/module.h> 26#include <linux/module.h>
21#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/uaccess.h>
22 29
23#include <asm/io.h> 30#include <asm/io.h>
24 31
@@ -29,6 +36,14 @@
29 36
30static unsigned long virt_base_2700; 37static unsigned long virt_base_2700;
31 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
32#define MIN_XRES 16 47#define MIN_XRES 16
33#define MIN_YRES 16 48#define MIN_YRES 16
34#define MAX_XRES 2048 49#define MAX_XRES 2048
@@ -257,19 +272,17 @@ static int mbxfb_set_par(struct fb_info *info)
257 gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); 272 gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT));
258 gsctrl |= Gsctrl_Width(info->var.xres) | 273 gsctrl |= Gsctrl_Width(info->var.xres) |
259 Gsctrl_Height(info->var.yres); 274 Gsctrl_Height(info->var.yres);
260 writel(gsctrl, GSCTRL); 275 write_reg_dly(gsctrl, GSCTRL);
261 udelay(1000);
262 276
263 gsadr &= ~(FMsk(GSADR_SRCSTRIDE)); 277 gsadr &= ~(FMsk(GSADR_SRCSTRIDE));
264 gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / 278 gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel /
265 (8 * 16) - 1); 279 (8 * 16) - 1);
266 writel(gsadr, GSADR); 280 write_reg_dly(gsadr, GSADR);
267 udelay(1000);
268 281
269 /* setup timings */ 282 /* setup timings */
270 var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); 283 var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div);
271 284
272 writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | 285 write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
273 Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL); 286 Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL);
274 287
275 hbps = var->hsync_len; 288 hbps = var->hsync_len;
@@ -282,18 +295,20 @@ static int mbxfb_set_par(struct fb_info *info)
282 vfps = vas + var->yres; 295 vfps = vas + var->yres;
283 vt = vfps + var->lower_margin; 296 vt = vfps + var->lower_margin;
284 297
285 writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); 298 write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
286 writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); 299 write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
287 writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); 300 write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
288 writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); 301 write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
289 302
290 writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); 303 write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
291 writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); 304 write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
292 writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); 305 write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
293 writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); 306 write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
294 writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); 307 write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
295 308
296 writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); 309 write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
310
311 write_reg_dly(DINTRE_VEVENT0_EN, DINTRE);
297 312
298 return 0; 313 return 0;
299} 314}
@@ -305,23 +320,203 @@ static int mbxfb_blank(int blank, struct fb_info *info)
305 case FB_BLANK_VSYNC_SUSPEND: 320 case FB_BLANK_VSYNC_SUSPEND:
306 case FB_BLANK_HSYNC_SUSPEND: 321 case FB_BLANK_HSYNC_SUSPEND:
307 case FB_BLANK_NORMAL: 322 case FB_BLANK_NORMAL:
308 writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); 323 write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
309 udelay(1000); 324 write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
310 writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); 325 write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
311 udelay(1000);
312 writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
313 udelay(1000);
314 break; 326 break;
315 case FB_BLANK_UNBLANK: 327 case FB_BLANK_UNBLANK:
316 writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); 328 write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
317 udelay(1000); 329 write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
318 writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
319 udelay(1000);
320 break; 330 break;
321 } 331 }
322 return 0; 332 return 0;
323} 333}
324 334
335static 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
495static 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
325static struct fb_ops mbxfb_ops = { 520static struct fb_ops mbxfb_ops = {
326 .owner = THIS_MODULE, 521 .owner = THIS_MODULE,
327 .fb_check_var = mbxfb_check_var, 522 .fb_check_var = mbxfb_check_var,
@@ -331,6 +526,7 @@ static struct fb_ops mbxfb_ops = {
331 .fb_copyarea = cfb_copyarea, 526 .fb_copyarea = cfb_copyarea,
332 .fb_imageblit = cfb_imageblit, 527 .fb_imageblit = cfb_imageblit,
333 .fb_blank = mbxfb_blank, 528 .fb_blank = mbxfb_blank,
529 .fb_ioctl = mbxfb_ioctl,
334}; 530};
335 531
336/* 532/*
@@ -339,36 +535,29 @@ static struct fb_ops mbxfb_ops = {
339*/ 535*/
340static void __devinit setup_memc(struct fb_info *fbi) 536static void __devinit setup_memc(struct fb_info *fbi)
341{ 537{
342 struct mbxfb_info *mfbi = fbi->par;
343 unsigned long tmp; 538 unsigned long tmp;
344 int i; 539 int i;
345 540
346 /* FIXME: use platfrom specific parameters */ 541 /* FIXME: use platfrom specific parameters */
347 /* setup SDRAM controller */ 542 /* setup SDRAM controller */
348 writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | 543 write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
349 LMCFG_LMA_TS), 544 LMCFG_LMA_TS),
350 LMCFG); 545 LMCFG);
351 udelay(1000);
352 546
353 writel(LMPWR_MC_PWR_ACT, LMPWR); 547 write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
354 udelay(1000);
355 548
356 /* setup SDRAM timings */ 549 /* setup SDRAM timings */
357 writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | 550 write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
358 Lmtim_Trc(9) | Lmtim_Tdpl(2)), 551 Lmtim_Trc(9) | Lmtim_Tdpl(2)),
359 LMTIM); 552 LMTIM);
360 udelay(1000);
361 /* setup SDRAM refresh rate */ 553 /* setup SDRAM refresh rate */
362 writel(0xc2b, LMREFRESH); 554 write_reg_dly(0xc2b, LMREFRESH);
363 udelay(1000);
364 /* setup SDRAM type parameters */ 555 /* setup SDRAM type parameters */
365 writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | 556 write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
366 LMTYPE_COLSZ_8), 557 LMTYPE_COLSZ_8),
367 LMTYPE); 558 LMTYPE);
368 udelay(1000);
369 /* enable memory controller */ 559 /* enable memory controller */
370 writel(LMPWR_MC_PWR_ACT, LMPWR); 560 write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
371 udelay(1000);
372 561
373 /* perform dummy reads */ 562 /* perform dummy reads */
374 for ( i = 0; i < 16; i++ ) { 563 for ( i = 0; i < 16; i++ ) {
@@ -379,34 +568,30 @@ static void __devinit setup_memc(struct fb_info *fbi)
379static void enable_clocks(struct fb_info *fbi) 568static void enable_clocks(struct fb_info *fbi)
380{ 569{
381 /* enable clocks */ 570 /* enable clocks */
382 writel(SYSCLKSRC_PLL_2, SYSCLKSRC); 571 write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC);
383 udelay(1000); 572 write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC);
384 writel(PIXCLKSRC_PLL_1, PIXCLKSRC); 573 write_reg_dly(0x00000000, CLKSLEEP);
385 udelay(1000); 574
386 writel(0x00000000, CLKSLEEP); 575 /* PLL output = (Frefclk * M) / (N * 2^P )
387 udelay(1000); 576 *
388 writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) | 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) |
389 CORE_PLL_EN), 581 CORE_PLL_EN),
390 COREPLL); 582 COREPLL);
391 udelay(1000); 583
392 writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | 584 write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
393 DISP_PLL_EN), 585 DISP_PLL_EN),
394 DISPPLL); 586 DISPPLL);
395 587
396 writel(0x00000000, VOVRCLK); 588 write_reg_dly(0x00000000, VOVRCLK);
397 udelay(1000); 589 write_reg_dly(PIXCLK_EN, PIXCLK);
398 writel(PIXCLK_EN, PIXCLK); 590 write_reg_dly(MEMCLK_EN, MEMCLK);
399 udelay(1000); 591 write_reg_dly(0x00000006, M24CLK);
400 writel(MEMCLK_EN, MEMCLK); 592 write_reg_dly(0x00000006, MBXCLK);
401 udelay(1000); 593 write_reg_dly(SDCLK_EN, SDCLK);
402 writel(0x00000006, M24CLK); 594 write_reg_dly(0x00000001, PIXCLKDIV);
403 udelay(1000);
404 writel(0x00000006, MBXCLK);
405 udelay(1000);
406 writel(SDCLK_EN, SDCLK);
407 udelay(1000);
408 writel(0x00000001, PIXCLKDIV);
409 udelay(1000);
410} 595}
411 596
412static void __devinit setup_graphics(struct fb_info *fbi) 597static void __devinit setup_graphics(struct fb_info *fbi)
@@ -430,16 +615,11 @@ static void __devinit setup_graphics(struct fb_info *fbi)
430 break; 615 break;
431 } 616 }
432 617
433 writel(gsctrl, GSCTRL); 618 write_reg_dly(gsctrl, GSCTRL);
434 udelay(1000); 619 write_reg_dly(0x00000000, GBBASE);
435 writel(0x00000000, GBBASE); 620 write_reg_dly(0x00ffffff, GDRCTRL);
436 udelay(1000); 621 write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
437 writel(0x00ffffff, GDRCTRL); 622 write_reg_dly(0x00000000, GPLUT);
438 udelay(1000);
439 writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
440 udelay(1000);
441 writel(0x00000000, GPLUT);
442 udelay(1000);
443} 623}
444 624
445static void __devinit setup_display(struct fb_info *fbi) 625static void __devinit setup_display(struct fb_info *fbi)
@@ -451,17 +631,14 @@ static void __devinit setup_display(struct fb_info *fbi)
451 dsctrl |= DSCTRL_HS_POL; 631 dsctrl |= DSCTRL_HS_POL;
452 if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) 632 if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
453 dsctrl |= DSCTRL_VS_POL; 633 dsctrl |= DSCTRL_VS_POL;
454 writel(dsctrl, DSCTRL); 634 write_reg_dly(dsctrl, DSCTRL);
455 udelay(1000); 635 write_reg_dly(0xd0303010, DMCTRL);
456 writel(0xd0303010, DMCTRL); 636 write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
457 udelay(1000);
458 writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
459} 637}
460 638
461static void __devinit enable_controller(struct fb_info *fbi) 639static void __devinit enable_controller(struct fb_info *fbi)
462{ 640{
463 writel(SYSRST_RST, SYSRST); 641 write_reg_dly(SYSRST_RST, SYSRST);
464 udelay(1000);
465 642
466 643
467 enable_clocks(fbi); 644 enable_clocks(fbi);
@@ -478,12 +655,12 @@ static void __devinit enable_controller(struct fb_info *fbi)
478static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) 655static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
479{ 656{
480 /* make frame buffer memory enter self-refresh mode */ 657 /* make frame buffer memory enter self-refresh mode */
481 writel(LMPWR_MC_PWR_SRM, LMPWR); 658 write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
482 while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM) 659 while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM)
483 ; /* empty statement */ 660 ; /* empty statement */
484 661
485 /* reset the device, since it's initial state is 'mostly sleeping' */ 662 /* reset the device, since it's initial state is 'mostly sleeping' */
486 writel(SYSRST_RST, SYSRST); 663 write_reg_dly(SYSRST_RST, SYSRST);
487 return 0; 664 return 0;
488} 665}
489 666
@@ -495,7 +672,7 @@ static int mbxfb_resume(struct platform_device *dev)
495/* setup_graphics(fbi); */ 672/* setup_graphics(fbi); */
496/* setup_display(fbi); */ 673/* setup_display(fbi); */
497 674
498 writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); 675 write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
499 return 0; 676 return 0;
500} 677}
501#else 678#else
@@ -520,6 +697,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
520 697
521 dev_dbg(dev, "mbxfb_probe\n"); 698 dev_dbg(dev, "mbxfb_probe\n");
522 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
523 fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); 706 fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev);
524 if (fbi == NULL) { 707 if (fbi == NULL) {
525 dev_err(&dev->dev, "framebuffer_alloc failed\n"); 708 dev_err(&dev->dev, "framebuffer_alloc failed\n");
@@ -528,7 +711,8 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
528 711
529 mfbi = fbi->par; 712 mfbi = fbi->par;
530 fbi->pseudo_palette = mfbi->pseudo_palette; 713 fbi->pseudo_palette = mfbi->pseudo_palette;
531 pdata = dev->dev.platform_data; 714
715
532 if (pdata->probe) 716 if (pdata->probe)
533 mfbi->platform_probe = pdata->probe; 717 mfbi->platform_probe = pdata->probe;
534 if (pdata->remove) 718 if (pdata->remove)
@@ -578,16 +762,16 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
578 goto err4; 762 goto err4;
579 } 763 }
580 764
581 /* FIXME: get from platform */
582 fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); 765 fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
583 fbi->screen_size = 8 * 1024 * 1024; /* 8 Megs */ 766 fbi->screen_size = pdata->memsize;
584 fbi->fbops = &mbxfb_ops; 767 fbi->fbops = &mbxfb_ops;
585 768
586 fbi->var = mbxfb_default; 769 fbi->var = mbxfb_default;
587 fbi->fix = mbxfb_fix; 770 fbi->fix = mbxfb_fix;
588 fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; 771 fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000;
589 fbi->fix.smem_len = 8 * 1024 * 1024; 772 fbi->fix.smem_len = pdata->memsize;
590 fbi->fix.line_length = 640 * 2; 773 fbi->fix.line_length = mbxfb_default.xres_virtual *
774 mbxfb_default.bits_per_pixel / 8;
591 775
592 ret = fb_alloc_cmap(&fbi->cmap, 256, 0); 776 ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
593 if (ret < 0) { 777 if (ret < 0) {
@@ -636,8 +820,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev)
636{ 820{
637 struct fb_info *fbi = platform_get_drvdata(dev); 821 struct fb_info *fbi = platform_get_drvdata(dev);
638 822
639 writel(SYSRST_RST, SYSRST); 823 write_reg_dly(SYSRST_RST, SYSRST);
640 udelay(1000);
641 824
642 mbxfb_debugfs_remove(fbi); 825 mbxfb_debugfs_remove(fbi);
643 826
diff --git a/include/video/mbxfb.h b/include/video/mbxfb.h
index 3bde0f5cd55c..20b9002712ef 100644
--- a/include/video/mbxfb.h
+++ b/include/video/mbxfb.h
@@ -1,6 +1,9 @@
1#ifndef __MBX_FB_H 1#ifndef __MBX_FB_H
2#define __MBX_FB_H 2#define __MBX_FB_H
3 3
4#include <asm/ioctl.h>
5#include <asm/types.h>
6
4struct mbxfb_val { 7struct mbxfb_val {
5 unsigned int defval; 8 unsigned int defval;
6 unsigned int min; 9 unsigned int min;
@@ -25,4 +28,32 @@ struct mbxfb_platform_data {
25 int (*remove)(struct fb_info *fb); 28 int (*remove)(struct fb_info *fb);
26}; 29};
27 30
31/* planar */
32#define MBXFB_FMT_YUV12 0
33
34/* packed */
35#define MBXFB_FMT_UY0VY1 1
36#define MBXFB_FMT_VY0UY1 2
37#define MBXFB_FMT_Y0UY1V 3
38#define MBXFB_FMT_Y0VY1U 4
39struct mbxfb_overlaySetup {
40 __u32 enable;
41 __u32 x, y;
42 __u32 width, height;
43 __u32 alpha;
44 __u32 fmt;
45 __u32 mem_offset;
46 __u32 scaled_width;
47 __u32 scaled_height;
48
49 /* Filled by the driver */
50 __u32 U_offset;
51 __u32 V_offset;
52
53 __u16 Y_stride;
54 __u16 UV_stride;
55};
56
57#define MBXFB_IOCX_OVERLAY _IOWR(0xF4, 0x00,struct mbxfb_overlaySetup)
58
28#endif /* __MBX_FB_H */ 59#endif /* __MBX_FB_H */