aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/imxfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/imxfb.c')
-rw-r--r--drivers/video/imxfb.c108
1 files changed, 95 insertions, 13 deletions
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index d58c68cd456e..15a0ee6d8e23 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -14,7 +14,6 @@
14 * linux-arm-kernel@lists.arm.linux.org.uk 14 * linux-arm-kernel@lists.arm.linux.org.uk
15 */ 15 */
16 16
17
18#include <linux/module.h> 17#include <linux/module.h>
19#include <linux/kernel.h> 18#include <linux/kernel.h>
20#include <linux/errno.h> 19#include <linux/errno.h>
@@ -27,9 +26,11 @@
27#include <linux/init.h> 26#include <linux/init.h>
28#include <linux/ioport.h> 27#include <linux/ioport.h>
29#include <linux/cpufreq.h> 28#include <linux/cpufreq.h>
29#include <linux/clk.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/dma-mapping.h> 31#include <linux/dma-mapping.h>
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/math64.h>
33 34
34#include <mach/imxfb.h> 35#include <mach/imxfb.h>
35 36
@@ -44,7 +45,12 @@
44 45
45#define LCDC_SIZE 0x04 46#define LCDC_SIZE 0x04
46#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) 47#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20)
48
49#ifdef CONFIG_ARCH_MX1
47#define SIZE_YMAX(y) ((y) & 0x1ff) 50#define SIZE_YMAX(y) ((y) & 0x1ff)
51#else
52#define SIZE_YMAX(y) ((y) & 0x3ff)
53#endif
48 54
49#define LCDC_VPW 0x08 55#define LCDC_VPW 0x08
50#define VPW_VPW(x) ((x) & 0x3ff) 56#define VPW_VPW(x) ((x) & 0x3ff)
@@ -54,7 +60,12 @@
54#define CPOS_CC0 (1<<30) 60#define CPOS_CC0 (1<<30)
55#define CPOS_OP (1<<28) 61#define CPOS_OP (1<<28)
56#define CPOS_CXP(x) (((x) & 3ff) << 16) 62#define CPOS_CXP(x) (((x) & 3ff) << 16)
63
64#ifdef CONFIG_ARCH_MX1
57#define CPOS_CYP(y) ((y) & 0x1ff) 65#define CPOS_CYP(y) ((y) & 0x1ff)
66#else
67#define CPOS_CYP(y) ((y) & 0x3ff)
68#endif
58 69
59#define LCDC_LCWHB 0x10 70#define LCDC_LCWHB 0x10
60#define LCWHB_BK_EN (1<<31) 71#define LCWHB_BK_EN (1<<31)
@@ -63,9 +74,16 @@
63#define LCWHB_BD(x) ((x) & 0xff) 74#define LCWHB_BD(x) ((x) & 0xff)
64 75
65#define LCDC_LCHCC 0x14 76#define LCDC_LCHCC 0x14
77
78#ifdef CONFIG_ARCH_MX1
66#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11) 79#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11)
67#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5) 80#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5)
68#define LCHCC_CUR_COL_B(b) ((b) & 0x1f) 81#define LCHCC_CUR_COL_B(b) ((b) & 0x1f)
82#else
83#define LCHCC_CUR_COL_R(r) (((r) & 0x3f) << 12)
84#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 6)
85#define LCHCC_CUR_COL_B(b) ((b) & 0x3f)
86#endif
69 87
70#define LCDC_PCR 0x18 88#define LCDC_PCR 0x18
71 89
@@ -92,7 +110,13 @@
92/* bit fields in imxfb.h */ 110/* bit fields in imxfb.h */
93 111
94#define LCDC_RMCR 0x34 112#define LCDC_RMCR 0x34
113
114#ifdef CONFIG_ARCH_MX1
95#define RMCR_LCDC_EN (1<<1) 115#define RMCR_LCDC_EN (1<<1)
116#else
117#define RMCR_LCDC_EN 0
118#endif
119
96#define RMCR_SELF_REF (1<<0) 120#define RMCR_SELF_REF (1<<0)
97 121
98#define LCDC_LCDICR 0x38 122#define LCDC_LCDICR 0x38
@@ -119,6 +143,7 @@ struct imxfb_rgb {
119struct imxfb_info { 143struct imxfb_info {
120 struct platform_device *pdev; 144 struct platform_device *pdev;
121 void __iomem *regs; 145 void __iomem *regs;
146 struct clk *clk;
122 147
123 u_int max_bpp; 148 u_int max_bpp;
124 u_int max_xres; 149 u_int max_xres;
@@ -159,6 +184,17 @@ struct imxfb_info {
159#define MIN_XRES 64 184#define MIN_XRES 64
160#define MIN_YRES 64 185#define MIN_YRES 64
161 186
187/* Actually this really is 18bit support, the lowest 2 bits of each colour
188 * are unused in hardware. We claim to have 24bit support to make software
189 * like X work, which does not support 18bit.
190 */
191static struct imxfb_rgb def_rgb_18 = {
192 .red = {.offset = 16, .length = 8,},
193 .green = {.offset = 8, .length = 8,},
194 .blue = {.offset = 0, .length = 8,},
195 .transp = {.offset = 0, .length = 0,},
196};
197
162static struct imxfb_rgb def_rgb_16_tft = { 198static struct imxfb_rgb def_rgb_16_tft = {
163 .red = {.offset = 11, .length = 5,}, 199 .red = {.offset = 11, .length = 5,},
164 .green = {.offset = 5, .length = 6,}, 200 .green = {.offset = 5, .length = 6,},
@@ -286,9 +322,12 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
286 322
287 pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); 323 pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
288 switch (var->bits_per_pixel) { 324 switch (var->bits_per_pixel) {
325 case 32:
326 rgb = &def_rgb_18;
327 break;
289 case 16: 328 case 16:
290 default: 329 default:
291 if (readl(fbi->regs + LCDC_PCR) & PCR_TFT) 330 if (fbi->pcr & PCR_TFT)
292 rgb = &def_rgb_16_tft; 331 rgb = &def_rgb_16_tft;
293 else 332 else
294 rgb = &def_rgb_16_stn; 333 rgb = &def_rgb_16_stn;
@@ -327,9 +366,7 @@ static int imxfb_set_par(struct fb_info *info)
327 struct imxfb_info *fbi = info->par; 366 struct imxfb_info *fbi = info->par;
328 struct fb_var_screeninfo *var = &info->var; 367 struct fb_var_screeninfo *var = &info->var;
329 368
330 pr_debug("set_par\n"); 369 if (var->bits_per_pixel == 16 || var->bits_per_pixel == 32)
331
332 if (var->bits_per_pixel == 16)
333 info->fix.visual = FB_VISUAL_TRUECOLOR; 370 info->fix.visual = FB_VISUAL_TRUECOLOR;
334 else if (!fbi->cmap_static) 371 else if (!fbi->cmap_static)
335 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 372 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -354,10 +391,6 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
354{ 391{
355 pr_debug("Enabling LCD controller\n"); 392 pr_debug("Enabling LCD controller\n");
356 393
357 /* initialize LCDC */
358 writel(readl(fbi->regs + LCDC_RMCR) & ~RMCR_LCDC_EN,
359 fbi->regs + LCDC_RMCR); /* just to be safe... */
360
361 writel(fbi->screen_dma, fbi->regs + LCDC_SSA); 394 writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
362 395
363 /* physical screen start address */ 396 /* physical screen start address */
@@ -373,6 +406,8 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
373 406
374 writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR); 407 writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR);
375 408
409 clk_enable(fbi->clk);
410
376 if (fbi->backlight_power) 411 if (fbi->backlight_power)
377 fbi->backlight_power(1); 412 fbi->backlight_power(1);
378 if (fbi->lcd_power) 413 if (fbi->lcd_power)
@@ -388,6 +423,8 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
388 if (fbi->lcd_power) 423 if (fbi->lcd_power)
389 fbi->lcd_power(0); 424 fbi->lcd_power(0);
390 425
426 clk_disable(fbi->clk);
427
391 writel(0, fbi->regs + LCDC_RMCR); 428 writel(0, fbi->regs + LCDC_RMCR);
392} 429}
393 430
@@ -431,6 +468,9 @@ static struct fb_ops imxfb_ops = {
431static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info) 468static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
432{ 469{
433 struct imxfb_info *fbi = info->par; 470 struct imxfb_info *fbi = info->par;
471 unsigned int pcr, lcd_clk;
472 unsigned long long tmp;
473
434 pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", 474 pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
435 var->xres, var->hsync_len, 475 var->xres, var->hsync_len,
436 var->left_margin, var->right_margin); 476 var->left_margin, var->right_margin);
@@ -465,9 +505,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
465 info->fix.id, var->lower_margin); 505 info->fix.id, var->lower_margin);
466#endif 506#endif
467 507
468 writel(HCR_H_WIDTH(var->hsync_len) | 508 writel(HCR_H_WIDTH(var->hsync_len - 1) |
469 HCR_H_WAIT_1(var->right_margin) | 509 HCR_H_WAIT_1(var->right_margin - 1) |
470 HCR_H_WAIT_2(var->left_margin), 510 HCR_H_WAIT_2(var->left_margin - 3),
471 fbi->regs + LCDC_HCR); 511 fbi->regs + LCDC_HCR);
472 512
473 writel(VCR_V_WIDTH(var->vsync_len) | 513 writel(VCR_V_WIDTH(var->vsync_len) |
@@ -477,7 +517,23 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
477 517
478 writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres), 518 writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
479 fbi->regs + LCDC_SIZE); 519 fbi->regs + LCDC_SIZE);
480 writel(fbi->pcr, fbi->regs + LCDC_PCR); 520
521 lcd_clk = clk_get_rate(fbi->clk);
522 tmp = var->pixclock * (unsigned long long)lcd_clk;
523 do_div(tmp, 1000000);
524 if (do_div(tmp, 1000000) > 500000)
525 tmp++;
526 pcr = (unsigned int)tmp;
527 if (--pcr > 0x3F) {
528 pcr = 0x3F;
529 printk(KERN_WARNING "Must limit pixel clock to %uHz\n",
530 lcd_clk / pcr);
531 }
532
533 /* add sync polarities */
534 pcr |= fbi->pcr & ~0x3F;
535
536 writel(pcr, fbi->regs + LCDC_PCR);
481 writel(fbi->pwmr, fbi->regs + LCDC_PWMR); 537 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
482 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); 538 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
483 writel(fbi->dmacr, fbi->regs + LCDC_DMACR); 539 writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
@@ -619,6 +675,13 @@ static int __init imxfb_probe(struct platform_device *pdev)
619 goto failed_req; 675 goto failed_req;
620 } 676 }
621 677
678 fbi->clk = clk_get(&pdev->dev, NULL);
679 if (IS_ERR(fbi->clk)) {
680 ret = PTR_ERR(fbi->clk);;
681 dev_err(&pdev->dev, "unable to get clock: %d\n", ret);
682 goto failed_getclock;
683 }
684
622 fbi->regs = ioremap(res->start, resource_size(res)); 685 fbi->regs = ioremap(res->start, resource_size(res));
623 if (fbi->regs == NULL) { 686 if (fbi->regs == NULL) {
624 printk(KERN_ERR"Cannot map frame buffer registers\n"); 687 printk(KERN_ERR"Cannot map frame buffer registers\n");
@@ -650,6 +713,12 @@ static int __init imxfb_probe(struct platform_device *pdev)
650 info->fix.smem_start = fbi->screen_dma; 713 info->fix.smem_start = fbi->screen_dma;
651 } 714 }
652 715
716 if (pdata->init) {
717 ret = pdata->init(fbi->pdev);
718 if (ret)
719 goto failed_platform_init;
720 }
721
653 /* 722 /*
654 * This makes sure that our colour bitfield 723 * This makes sure that our colour bitfield
655 * descriptors are correctly initialised. 724 * descriptors are correctly initialised.
@@ -674,10 +743,15 @@ static int __init imxfb_probe(struct platform_device *pdev)
674failed_register: 743failed_register:
675 fb_dealloc_cmap(&info->cmap); 744 fb_dealloc_cmap(&info->cmap);
676failed_cmap: 745failed_cmap:
746 if (pdata->exit)
747 pdata->exit(fbi->pdev);
748failed_platform_init:
677 if (!pdata->fixed_screen_cpu) 749 if (!pdata->fixed_screen_cpu)
678 dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, 750 dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu,
679 fbi->map_dma); 751 fbi->map_dma);
680failed_map: 752failed_map:
753 clk_put(fbi->clk);
754failed_getclock:
681 iounmap(fbi->regs); 755 iounmap(fbi->regs);
682failed_ioremap: 756failed_ioremap:
683 release_mem_region(res->start, res->end - res->start); 757 release_mem_region(res->start, res->end - res->start);
@@ -691,6 +765,7 @@ failed_init:
691 765
692static int __devexit imxfb_remove(struct platform_device *pdev) 766static int __devexit imxfb_remove(struct platform_device *pdev)
693{ 767{
768 struct imx_fb_platform_data *pdata;
694 struct fb_info *info = platform_get_drvdata(pdev); 769 struct fb_info *info = platform_get_drvdata(pdev);
695 struct imxfb_info *fbi = info->par; 770 struct imxfb_info *fbi = info->par;
696 struct resource *res; 771 struct resource *res;
@@ -701,12 +776,19 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
701 776
702 unregister_framebuffer(info); 777 unregister_framebuffer(info);
703 778
779 pdata = pdev->dev.platform_data;
780 if (pdata->exit)
781 pdata->exit(fbi->pdev);
782
704 fb_dealloc_cmap(&info->cmap); 783 fb_dealloc_cmap(&info->cmap);
705 kfree(info->pseudo_palette); 784 kfree(info->pseudo_palette);
706 framebuffer_release(info); 785 framebuffer_release(info);
707 786
708 iounmap(fbi->regs); 787 iounmap(fbi->regs);
709 release_mem_region(res->start, res->end - res->start + 1); 788 release_mem_region(res->start, res->end - res->start + 1);
789 clk_disable(fbi->clk);
790 clk_put(fbi->clk);
791
710 platform_set_drvdata(pdev, NULL); 792 platform_set_drvdata(pdev, NULL);
711 793
712 return 0; 794 return 0;