diff options
Diffstat (limited to 'drivers/video/imxfb.c')
-rw-r--r-- | drivers/video/imxfb.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index d58c68cd456e..bd1cb75cd14b 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> |
@@ -44,7 +43,12 @@ | |||
44 | 43 | ||
45 | #define LCDC_SIZE 0x04 | 44 | #define LCDC_SIZE 0x04 |
46 | #define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) | 45 | #define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) |
46 | |||
47 | #ifdef CONFIG_ARCH_MX1 | ||
47 | #define SIZE_YMAX(y) ((y) & 0x1ff) | 48 | #define SIZE_YMAX(y) ((y) & 0x1ff) |
49 | #else | ||
50 | #define SIZE_YMAX(y) ((y) & 0x3ff) | ||
51 | #endif | ||
48 | 52 | ||
49 | #define LCDC_VPW 0x08 | 53 | #define LCDC_VPW 0x08 |
50 | #define VPW_VPW(x) ((x) & 0x3ff) | 54 | #define VPW_VPW(x) ((x) & 0x3ff) |
@@ -54,7 +58,12 @@ | |||
54 | #define CPOS_CC0 (1<<30) | 58 | #define CPOS_CC0 (1<<30) |
55 | #define CPOS_OP (1<<28) | 59 | #define CPOS_OP (1<<28) |
56 | #define CPOS_CXP(x) (((x) & 3ff) << 16) | 60 | #define CPOS_CXP(x) (((x) & 3ff) << 16) |
61 | |||
62 | #ifdef CONFIG_ARCH_MX1 | ||
57 | #define CPOS_CYP(y) ((y) & 0x1ff) | 63 | #define CPOS_CYP(y) ((y) & 0x1ff) |
64 | #else | ||
65 | #define CPOS_CYP(y) ((y) & 0x3ff) | ||
66 | #endif | ||
58 | 67 | ||
59 | #define LCDC_LCWHB 0x10 | 68 | #define LCDC_LCWHB 0x10 |
60 | #define LCWHB_BK_EN (1<<31) | 69 | #define LCWHB_BK_EN (1<<31) |
@@ -63,9 +72,16 @@ | |||
63 | #define LCWHB_BD(x) ((x) & 0xff) | 72 | #define LCWHB_BD(x) ((x) & 0xff) |
64 | 73 | ||
65 | #define LCDC_LCHCC 0x14 | 74 | #define LCDC_LCHCC 0x14 |
75 | |||
76 | #ifdef CONFIG_ARCH_MX1 | ||
66 | #define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11) | 77 | #define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11) |
67 | #define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5) | 78 | #define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5) |
68 | #define LCHCC_CUR_COL_B(b) ((b) & 0x1f) | 79 | #define LCHCC_CUR_COL_B(b) ((b) & 0x1f) |
80 | #else | ||
81 | #define LCHCC_CUR_COL_R(r) (((r) & 0x3f) << 12) | ||
82 | #define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 6) | ||
83 | #define LCHCC_CUR_COL_B(b) ((b) & 0x3f) | ||
84 | #endif | ||
69 | 85 | ||
70 | #define LCDC_PCR 0x18 | 86 | #define LCDC_PCR 0x18 |
71 | 87 | ||
@@ -92,7 +108,13 @@ | |||
92 | /* bit fields in imxfb.h */ | 108 | /* bit fields in imxfb.h */ |
93 | 109 | ||
94 | #define LCDC_RMCR 0x34 | 110 | #define LCDC_RMCR 0x34 |
111 | |||
112 | #ifdef CONFIG_ARCH_MX1 | ||
95 | #define RMCR_LCDC_EN (1<<1) | 113 | #define RMCR_LCDC_EN (1<<1) |
114 | #else | ||
115 | #define RMCR_LCDC_EN 0 | ||
116 | #endif | ||
117 | |||
96 | #define RMCR_SELF_REF (1<<0) | 118 | #define RMCR_SELF_REF (1<<0) |
97 | 119 | ||
98 | #define LCDC_LCDICR 0x38 | 120 | #define LCDC_LCDICR 0x38 |
@@ -159,6 +181,17 @@ struct imxfb_info { | |||
159 | #define MIN_XRES 64 | 181 | #define MIN_XRES 64 |
160 | #define MIN_YRES 64 | 182 | #define MIN_YRES 64 |
161 | 183 | ||
184 | /* Actually this really is 18bit support, the lowest 2 bits of each colour | ||
185 | * are unused in hardware. We claim to have 24bit support to make software | ||
186 | * like X work, which does not support 18bit. | ||
187 | */ | ||
188 | static struct imxfb_rgb def_rgb_18 = { | ||
189 | .red = {.offset = 16, .length = 8,}, | ||
190 | .green = {.offset = 8, .length = 8,}, | ||
191 | .blue = {.offset = 0, .length = 8,}, | ||
192 | .transp = {.offset = 0, .length = 0,}, | ||
193 | }; | ||
194 | |||
162 | static struct imxfb_rgb def_rgb_16_tft = { | 195 | static struct imxfb_rgb def_rgb_16_tft = { |
163 | .red = {.offset = 11, .length = 5,}, | 196 | .red = {.offset = 11, .length = 5,}, |
164 | .green = {.offset = 5, .length = 6,}, | 197 | .green = {.offset = 5, .length = 6,}, |
@@ -286,6 +319,9 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
286 | 319 | ||
287 | pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); | 320 | pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); |
288 | switch (var->bits_per_pixel) { | 321 | switch (var->bits_per_pixel) { |
322 | case 32: | ||
323 | rgb = &def_rgb_18; | ||
324 | break; | ||
289 | case 16: | 325 | case 16: |
290 | default: | 326 | default: |
291 | if (readl(fbi->regs + LCDC_PCR) & PCR_TFT) | 327 | if (readl(fbi->regs + LCDC_PCR) & PCR_TFT) |
@@ -327,9 +363,7 @@ static int imxfb_set_par(struct fb_info *info) | |||
327 | struct imxfb_info *fbi = info->par; | 363 | struct imxfb_info *fbi = info->par; |
328 | struct fb_var_screeninfo *var = &info->var; | 364 | struct fb_var_screeninfo *var = &info->var; |
329 | 365 | ||
330 | pr_debug("set_par\n"); | 366 | 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; | 367 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
334 | else if (!fbi->cmap_static) | 368 | else if (!fbi->cmap_static) |
335 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | 369 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; |
@@ -354,10 +388,6 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) | |||
354 | { | 388 | { |
355 | pr_debug("Enabling LCD controller\n"); | 389 | pr_debug("Enabling LCD controller\n"); |
356 | 390 | ||
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); | 391 | writel(fbi->screen_dma, fbi->regs + LCDC_SSA); |
362 | 392 | ||
363 | /* physical screen start address */ | 393 | /* physical screen start address */ |
@@ -465,9 +495,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf | |||
465 | info->fix.id, var->lower_margin); | 495 | info->fix.id, var->lower_margin); |
466 | #endif | 496 | #endif |
467 | 497 | ||
468 | writel(HCR_H_WIDTH(var->hsync_len) | | 498 | writel(HCR_H_WIDTH(var->hsync_len - 1) | |
469 | HCR_H_WAIT_1(var->right_margin) | | 499 | HCR_H_WAIT_1(var->right_margin - 1) | |
470 | HCR_H_WAIT_2(var->left_margin), | 500 | HCR_H_WAIT_2(var->left_margin - 3), |
471 | fbi->regs + LCDC_HCR); | 501 | fbi->regs + LCDC_HCR); |
472 | 502 | ||
473 | writel(VCR_V_WIDTH(var->vsync_len) | | 503 | writel(VCR_V_WIDTH(var->vsync_len) | |
@@ -650,6 +680,12 @@ static int __init imxfb_probe(struct platform_device *pdev) | |||
650 | info->fix.smem_start = fbi->screen_dma; | 680 | info->fix.smem_start = fbi->screen_dma; |
651 | } | 681 | } |
652 | 682 | ||
683 | if (pdata->init) { | ||
684 | ret = pdata->init(fbi->pdev); | ||
685 | if (ret) | ||
686 | goto failed_platform_init; | ||
687 | } | ||
688 | |||
653 | /* | 689 | /* |
654 | * This makes sure that our colour bitfield | 690 | * This makes sure that our colour bitfield |
655 | * descriptors are correctly initialised. | 691 | * descriptors are correctly initialised. |
@@ -674,6 +710,9 @@ static int __init imxfb_probe(struct platform_device *pdev) | |||
674 | failed_register: | 710 | failed_register: |
675 | fb_dealloc_cmap(&info->cmap); | 711 | fb_dealloc_cmap(&info->cmap); |
676 | failed_cmap: | 712 | failed_cmap: |
713 | if (pdata->exit) | ||
714 | pdata->exit(fbi->pdev); | ||
715 | failed_platform_init: | ||
677 | if (!pdata->fixed_screen_cpu) | 716 | if (!pdata->fixed_screen_cpu) |
678 | dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, | 717 | dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, |
679 | fbi->map_dma); | 718 | fbi->map_dma); |
@@ -691,6 +730,7 @@ failed_init: | |||
691 | 730 | ||
692 | static int __devexit imxfb_remove(struct platform_device *pdev) | 731 | static int __devexit imxfb_remove(struct platform_device *pdev) |
693 | { | 732 | { |
733 | struct imx_fb_platform_data *pdata; | ||
694 | struct fb_info *info = platform_get_drvdata(pdev); | 734 | struct fb_info *info = platform_get_drvdata(pdev); |
695 | struct imxfb_info *fbi = info->par; | 735 | struct imxfb_info *fbi = info->par; |
696 | struct resource *res; | 736 | struct resource *res; |
@@ -701,6 +741,10 @@ static int __devexit imxfb_remove(struct platform_device *pdev) | |||
701 | 741 | ||
702 | unregister_framebuffer(info); | 742 | unregister_framebuffer(info); |
703 | 743 | ||
744 | pdata = pdev->dev.platform_data; | ||
745 | if (pdata->exit) | ||
746 | pdata->exit(fbi->pdev); | ||
747 | |||
704 | fb_dealloc_cmap(&info->cmap); | 748 | fb_dealloc_cmap(&info->cmap); |
705 | kfree(info->pseudo_palette); | 749 | kfree(info->pseudo_palette); |
706 | framebuffer_release(info); | 750 | framebuffer_release(info); |