aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-mx2/mx27ads.c36
-rw-r--r--arch/arm/mach-mx2/pcm970-baseboard.c83
-rw-r--r--arch/arm/plat-mxc/include/mach/imxfb.h26
-rw-r--r--drivers/video/imxfb.c191
4 files changed, 208 insertions, 128 deletions
diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c
index a9f69eb58b7c..83e412b713e6 100644
--- a/arch/arm/mach-mx2/mx27ads.c
+++ b/arch/arm/mach-mx2/mx27ads.c
@@ -183,20 +183,29 @@ void lcd_power(int on)
183 __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG); 183 __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG);
184} 184}
185 185
186static struct imx_fb_platform_data mx27ads_fb_data = { 186static struct imx_fb_videomode mx27ads_modes[] = {
187 .pixclock = 188679, 187 {
188 .xres = 240, 188 .mode = {
189 .yres = 320, 189 .name = "Sharp-LQ035Q7",
190 190 .refresh = 60,
191 .bpp = 16, 191 .xres = 240,
192 .hsync_len = 1, 192 .yres = 320,
193 .left_margin = 9, 193 .pixclock = 188679, /* in ps (5.3MHz) */
194 .right_margin = 16, 194 .hsync_len = 1,
195 .left_margin = 9,
196 .right_margin = 16,
197 .vsync_len = 1,
198 .upper_margin = 7,
199 .lower_margin = 9,
200 },
201 .bpp = 16,
202 .pcr = 0xFB008BC0,
203 },
204};
195 205
196 .vsync_len = 1, 206static struct imx_fb_platform_data mx27ads_fb_data = {
197 .upper_margin = 7, 207 .mode = mx27ads_modes,
198 .lower_margin = 9, 208 .num_modes = ARRAY_SIZE(mx27ads_modes),
199 .fixed_screen_cpu = 0,
200 209
201 /* 210 /*
202 * - HSYNC active high 211 * - HSYNC active high
@@ -207,7 +216,6 @@ static struct imx_fb_platform_data mx27ads_fb_data = {
207 * - data enable low active 216 * - data enable low active
208 * - enable sharp mode 217 * - enable sharp mode
209 */ 218 */
210 .pcr = 0xFB008BC0,
211 .pwmr = 0x00A903FF, 219 .pwmr = 0x00A903FF,
212 .lscr1 = 0x00120300, 220 .lscr1 = 0x00120300,
213 .dmacr = 0x00020010, 221 .dmacr = 0x00020010,
diff --git a/arch/arm/mach-mx2/pcm970-baseboard.c b/arch/arm/mach-mx2/pcm970-baseboard.c
index 6a3acaf57dd4..8e2bc94f1a03 100644
--- a/arch/arm/mach-mx2/pcm970-baseboard.c
+++ b/arch/arm/mach-mx2/pcm970-baseboard.c
@@ -125,35 +125,64 @@ static struct imxmmc_platform_data sdhc_pdata = {
125 .exit = pcm970_sdhc2_exit, 125 .exit = pcm970_sdhc2_exit,
126}; 126};
127 127
128/* 128static struct imx_fb_videomode pcm970_modes[] = {
129 * Connected is a portrait Sharp-QVGA display 129 {
130 * of type: LQ035Q7DH06 130 .mode = {
131 */ 131 .name = "Sharp-LQ035Q7",
132static struct imx_fb_platform_data pcm038_fb_data = { 132 .refresh = 60,
133 .pixclock = 188679, /* in ps (5.3MHz) */ 133 .xres = 240,
134 .xres = 240, 134 .yres = 320,
135 .yres = 320, 135 .pixclock = 188679, /* in ps (5.3MHz) */
136 136 .hsync_len = 7,
137 .bpp = 16, 137 .left_margin = 5,
138 .hsync_len = 7, 138 .right_margin = 16,
139 .left_margin = 5, 139 .vsync_len = 1,
140 .right_margin = 16, 140 .upper_margin = 7,
141 .lower_margin = 9,
142 },
143 /*
144 * - HSYNC active high
145 * - VSYNC active high
146 * - clk notenabled while idle
147 * - clock not inverted
148 * - data not inverted
149 * - data enable low active
150 * - enable sharp mode
151 */
152 .pcr = 0xF00080C0,
153 .bpp = 16,
154 }, {
155 .mode = {
156 .name = "TX090",
157 .refresh = 60,
158 .xres = 240,
159 .yres = 320,
160 .pixclock = 38255,
161 .left_margin = 144,
162 .right_margin = 0,
163 .upper_margin = 7,
164 .lower_margin = 40,
165 .hsync_len = 96,
166 .vsync_len = 1,
167 },
168 /*
169 * - HSYNC active low (1 << 22)
170 * - VSYNC active low (1 << 23)
171 * - clk notenabled while idle
172 * - clock not inverted
173 * - data not inverted
174 * - data enable low active
175 * - enable sharp mode
176 */
177 .pcr = 0xF0008080 | (1<<22) | (1<<23) | (1<<19),
178 .bpp = 32,
179 },
180};
141 181
142 .vsync_len = 1, 182static struct imx_fb_platform_data pcm038_fb_data = {
143 .upper_margin = 7, 183 .mode = pcm970_modes,
144 .lower_margin = 9, 184 .num_modes = ARRAY_SIZE(pcm970_modes),
145 .fixed_screen_cpu = 0,
146 185
147 /*
148 * - HSYNC active high
149 * - VSYNC active high
150 * - clk notenabled while idle
151 * - clock not inverted
152 * - data not inverted
153 * - data enable low active
154 * - enable sharp mode
155 */
156 .pcr = 0xFA0080C0,
157 .pwmr = 0x00A903FF, 186 .pwmr = 0x00A903FF,
158 .lscr1 = 0x00120300, 187 .lscr1 = 0x00120300,
159 .dmacr = 0x00020010, 188 .dmacr = 0x00020010,
diff --git a/arch/arm/plat-mxc/include/mach/imxfb.h b/arch/arm/plat-mxc/include/mach/imxfb.h
index 66259f6158e0..5263506b7ddf 100644
--- a/arch/arm/plat-mxc/include/mach/imxfb.h
+++ b/arch/arm/plat-mxc/include/mach/imxfb.h
@@ -2,6 +2,8 @@
2 * This structure describes the machine which we are running on. 2 * This structure describes the machine which we are running on.
3 */ 3 */
4 4
5#include <linux/fb.h>
6
5#define PCR_TFT (1 << 31) 7#define PCR_TFT (1 << 31)
6#define PCR_COLOR (1 << 30) 8#define PCR_COLOR (1 << 30)
7#define PCR_PBSIZ_1 (0 << 28) 9#define PCR_PBSIZ_1 (0 << 28)
@@ -47,29 +49,21 @@
47#define DMACR_HM(x) (((x) & 0xf) << 16) 49#define DMACR_HM(x) (((x) & 0xf) << 16)
48#define DMACR_TM(x) ((x) & 0xf) 50#define DMACR_TM(x) ((x) & 0xf)
49 51
50struct imx_fb_platform_data { 52struct imx_fb_videomode {
51 u_long pixclock; 53 struct fb_videomode mode;
52 54 u32 pcr;
53 u_short xres; 55 unsigned char bpp;
54 u_short yres; 56};
55
56 u_int nonstd;
57 u_char bpp;
58 u_char hsync_len;
59 u_char left_margin;
60 u_char right_margin;
61 57
62 u_char vsync_len; 58struct imx_fb_platform_data {
63 u_char upper_margin; 59 struct imx_fb_videomode *mode;
64 u_char lower_margin; 60 int num_modes;
65 u_char sync;
66 61
67 u_int cmap_greyscale:1, 62 u_int cmap_greyscale:1,
68 cmap_inverse:1, 63 cmap_inverse:1,
69 cmap_static:1, 64 cmap_static:1,
70 unused:29; 65 unused:29;
71 66
72 u_int pcr;
73 u_int pwmr; 67 u_int pwmr;
74 u_int lscr1; 68 u_int lscr1;
75 u_int dmacr; 69 u_int dmacr;
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 330857a8b318..30ae3022f633 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -130,6 +130,10 @@
130#define LCDISR_EOF (1<<1) 130#define LCDISR_EOF (1<<1)
131#define LCDISR_BOF (1<<0) 131#define LCDISR_BOF (1<<0)
132 132
133/* Used fb-mode. Can be set on kernel command line, therefore file-static. */
134static const char *fb_mode;
135
136
133/* 137/*
134 * These are the bitfields for each 138 * These are the bitfields for each
135 * display depth that we support. 139 * display depth that we support.
@@ -146,10 +150,6 @@ struct imxfb_info {
146 void __iomem *regs; 150 void __iomem *regs;
147 struct clk *clk; 151 struct clk *clk;
148 152
149 u_int max_bpp;
150 u_int max_xres;
151 u_int max_yres;
152
153 /* 153 /*
154 * These are the addresses we mapped 154 * These are the addresses we mapped
155 * the framebuffer memory region to. 155 * the framebuffer memory region to.
@@ -173,6 +173,9 @@ struct imxfb_info {
173 cmap_static:1, 173 cmap_static:1,
174 unused:30; 174 unused:30;
175 175
176 struct imx_fb_videomode *mode;
177 int num_modes;
178
176 void (*lcd_power)(int); 179 void (*lcd_power)(int);
177 void (*backlight_power)(int); 180 void (*backlight_power)(int);
178}; 181};
@@ -299,6 +302,18 @@ static int imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
299 return ret; 302 return ret;
300} 303}
301 304
305static const struct imx_fb_videomode *imxfb_find_mode(struct imxfb_info *fbi)
306{
307 struct imx_fb_videomode *m;
308 int i;
309
310 for (i = 0, m = &fbi->mode[0]; i < fbi->num_modes; i++, m++) {
311 if (!strcmp(m->mode.name, fb_mode))
312 return m;
313 }
314 return NULL;
315}
316
302/* 317/*
303 * imxfb_check_var(): 318 * imxfb_check_var():
304 * Round up in the following order: bits_per_pixel, xres, 319 * Round up in the following order: bits_per_pixel, xres,
@@ -309,35 +324,81 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
309{ 324{
310 struct imxfb_info *fbi = info->par; 325 struct imxfb_info *fbi = info->par;
311 struct imxfb_rgb *rgb; 326 struct imxfb_rgb *rgb;
327 const struct imx_fb_videomode *imxfb_mode;
328 unsigned long lcd_clk;
329 unsigned long long tmp;
330 u32 pcr = 0;
312 331
313 if (var->xres < MIN_XRES) 332 if (var->xres < MIN_XRES)
314 var->xres = MIN_XRES; 333 var->xres = MIN_XRES;
315 if (var->yres < MIN_YRES) 334 if (var->yres < MIN_YRES)
316 var->yres = MIN_YRES; 335 var->yres = MIN_YRES;
317 if (var->xres > fbi->max_xres) 336
318 var->xres = fbi->max_xres; 337 imxfb_mode = imxfb_find_mode(fbi);
319 if (var->yres > fbi->max_yres) 338 if (!imxfb_mode)
320 var->yres = fbi->max_yres; 339 return -EINVAL;
321 var->xres_virtual = max(var->xres_virtual, var->xres); 340
322 var->yres_virtual = max(var->yres_virtual, var->yres); 341 var->xres = imxfb_mode->mode.xres;
342 var->yres = imxfb_mode->mode.yres;
343 var->bits_per_pixel = imxfb_mode->bpp;
344 var->pixclock = imxfb_mode->mode.pixclock;
345 var->hsync_len = imxfb_mode->mode.hsync_len;
346 var->left_margin = imxfb_mode->mode.left_margin;
347 var->right_margin = imxfb_mode->mode.right_margin;
348 var->vsync_len = imxfb_mode->mode.vsync_len;
349 var->upper_margin = imxfb_mode->mode.upper_margin;
350 var->lower_margin = imxfb_mode->mode.lower_margin;
351 var->sync = imxfb_mode->mode.sync;
352 var->xres_virtual = max(var->xres_virtual, var->xres);
353 var->yres_virtual = max(var->yres_virtual, var->yres);
323 354
324 pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); 355 pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
356
357 lcd_clk = clk_get_rate(fbi->clk);
358
359 tmp = var->pixclock * (unsigned long long)lcd_clk;
360
361 do_div(tmp, 1000000);
362
363 if (do_div(tmp, 1000000) > 500000)
364 tmp++;
365
366 pcr = (unsigned int)tmp;
367
368 if (--pcr > 0x3F) {
369 pcr = 0x3F;
370 printk(KERN_WARNING "Must limit pixel clock to %luHz\n",
371 lcd_clk / pcr);
372 }
373
325 switch (var->bits_per_pixel) { 374 switch (var->bits_per_pixel) {
326 case 32: 375 case 32:
376 pcr |= PCR_BPIX_18;
327 rgb = &def_rgb_18; 377 rgb = &def_rgb_18;
328 break; 378 break;
329 case 16: 379 case 16:
330 default: 380 default:
331 if (fbi->pcr & PCR_TFT) 381 if (cpu_is_mx1())
382 pcr |= PCR_BPIX_12;
383 else
384 pcr |= PCR_BPIX_16;
385
386 if (imxfb_mode->pcr & PCR_TFT)
332 rgb = &def_rgb_16_tft; 387 rgb = &def_rgb_16_tft;
333 else 388 else
334 rgb = &def_rgb_16_stn; 389 rgb = &def_rgb_16_stn;
335 break; 390 break;
336 case 8: 391 case 8:
392 pcr |= PCR_BPIX_8;
337 rgb = &def_rgb_8; 393 rgb = &def_rgb_8;
338 break; 394 break;
339 } 395 }
340 396
397 /* add sync polarities */
398 pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25));
399
400 fbi->pcr = pcr;
401
341 /* 402 /*
342 * Copy the RGB parameters for this display 403 * Copy the RGB parameters for this display
343 * from the machine specific parameters. 404 * from the machine specific parameters.
@@ -394,10 +455,6 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
394 455
395 writel(fbi->screen_dma, fbi->regs + LCDC_SSA); 456 writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
396 457
397 /* physical screen start address */
398 writel(VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4),
399 fbi->regs + LCDC_VPW);
400
401 /* panning offset 0 (0 pixel offset) */ 458 /* panning offset 0 (0 pixel offset) */
402 writel(0x00000000, fbi->regs + LCDC_POS); 459 writel(0x00000000, fbi->regs + LCDC_POS);
403 460
@@ -469,8 +526,6 @@ static struct fb_ops imxfb_ops = {
469static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info) 526static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
470{ 527{
471 struct imxfb_info *fbi = info->par; 528 struct imxfb_info *fbi = info->par;
472 unsigned int pcr, lcd_clk;
473 unsigned long long tmp;
474 529
475 pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", 530 pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
476 var->xres, var->hsync_len, 531 var->xres, var->hsync_len,
@@ -506,6 +561,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
506 info->fix.id, var->lower_margin); 561 info->fix.id, var->lower_margin);
507#endif 562#endif
508 563
564 /* physical screen start address */
565 writel(VPW_VPW(var->xres * var->bits_per_pixel / 8 / 4),
566 fbi->regs + LCDC_VPW);
567
509 writel(HCR_H_WIDTH(var->hsync_len - 1) | 568 writel(HCR_H_WIDTH(var->hsync_len - 1) |
510 HCR_H_WAIT_1(var->right_margin - 1) | 569 HCR_H_WAIT_1(var->right_margin - 1) |
511 HCR_H_WAIT_2(var->left_margin - 3), 570 HCR_H_WAIT_2(var->left_margin - 3),
@@ -519,38 +578,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
519 writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres), 578 writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
520 fbi->regs + LCDC_SIZE); 579 fbi->regs + LCDC_SIZE);
521 580
522 lcd_clk = clk_get_rate(fbi->clk); 581 writel(fbi->pcr, fbi->regs + LCDC_PCR);
523 tmp = var->pixclock * (unsigned long long)lcd_clk;
524 do_div(tmp, 1000000);
525 if (do_div(tmp, 1000000) > 500000)
526 tmp++;
527 pcr = (unsigned int)tmp;
528 if (--pcr > 0x3F) {
529 pcr = 0x3F;
530 printk(KERN_WARNING "Must limit pixel clock to %uHz\n",
531 lcd_clk / pcr);
532 }
533
534 switch (var->bits_per_pixel) {
535 case 32:
536 pcr |= PCR_BPIX_18;
537 break;
538 case 16:
539 default:
540 if (cpu_is_mx1())
541 pcr |= PCR_BPIX_12;
542 else
543 pcr |= PCR_BPIX_16;
544 break;
545 case 8:
546 pcr |= PCR_BPIX_8;
547 break;
548 }
549
550 /* add sync polarities */
551 pcr |= fbi->pcr & ~(0x3f | (7 << 25));
552
553 writel(pcr, fbi->regs + LCDC_PCR);
554 writel(fbi->pwmr, fbi->regs + LCDC_PWMR); 582 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
555 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); 583 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
556 writel(fbi->dmacr, fbi->regs + LCDC_DMACR); 584 writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
@@ -592,6 +620,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev)
592 struct imx_fb_platform_data *pdata = pdev->dev.platform_data; 620 struct imx_fb_platform_data *pdata = pdev->dev.platform_data;
593 struct fb_info *info = dev_get_drvdata(&pdev->dev); 621 struct fb_info *info = dev_get_drvdata(&pdev->dev);
594 struct imxfb_info *fbi = info->par; 622 struct imxfb_info *fbi = info->par;
623 struct imx_fb_videomode *m;
624 int i;
595 625
596 pr_debug("%s\n",__func__); 626 pr_debug("%s\n",__func__);
597 627
@@ -620,35 +650,18 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev)
620 info->fbops = &imxfb_ops; 650 info->fbops = &imxfb_ops;
621 info->flags = FBINFO_FLAG_DEFAULT | 651 info->flags = FBINFO_FLAG_DEFAULT |
622 FBINFO_READS_FAST; 652 FBINFO_READS_FAST;
623
624 fbi->max_xres = pdata->xres;
625 info->var.xres = pdata->xres;
626 info->var.xres_virtual = pdata->xres;
627 fbi->max_yres = pdata->yres;
628 info->var.yres = pdata->yres;
629 info->var.yres_virtual = pdata->yres;
630 fbi->max_bpp = pdata->bpp;
631 info->var.bits_per_pixel = pdata->bpp;
632 info->var.nonstd = pdata->nonstd;
633 info->var.pixclock = pdata->pixclock;
634 info->var.hsync_len = pdata->hsync_len;
635 info->var.left_margin = pdata->left_margin;
636 info->var.right_margin = pdata->right_margin;
637 info->var.vsync_len = pdata->vsync_len;
638 info->var.upper_margin = pdata->upper_margin;
639 info->var.lower_margin = pdata->lower_margin;
640 info->var.sync = pdata->sync;
641 info->var.grayscale = pdata->cmap_greyscale; 653 info->var.grayscale = pdata->cmap_greyscale;
642 fbi->cmap_inverse = pdata->cmap_inverse; 654 fbi->cmap_inverse = pdata->cmap_inverse;
643 fbi->cmap_static = pdata->cmap_static; 655 fbi->cmap_static = pdata->cmap_static;
644 fbi->pcr = pdata->pcr;
645 fbi->lscr1 = pdata->lscr1; 656 fbi->lscr1 = pdata->lscr1;
646 fbi->dmacr = pdata->dmacr; 657 fbi->dmacr = pdata->dmacr;
647 fbi->pwmr = pdata->pwmr; 658 fbi->pwmr = pdata->pwmr;
648 fbi->lcd_power = pdata->lcd_power; 659 fbi->lcd_power = pdata->lcd_power;
649 fbi->backlight_power = pdata->backlight_power; 660 fbi->backlight_power = pdata->backlight_power;
650 info->fix.smem_len = fbi->max_xres * fbi->max_yres * 661
651 fbi->max_bpp / 8; 662 for (i = 0, m = &pdata->mode[0]; i < pdata->num_modes; i++, m++)
663 info->fix.smem_len = max_t(size_t, info->fix.smem_len,
664 m->mode.xres * m->mode.yres * m->bpp / 8);
652 665
653 return 0; 666 return 0;
654} 667}
@@ -659,7 +672,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
659 struct fb_info *info; 672 struct fb_info *info;
660 struct imx_fb_platform_data *pdata; 673 struct imx_fb_platform_data *pdata;
661 struct resource *res; 674 struct resource *res;
662 int ret; 675 int ret, i;
663 676
664 dev_info(&pdev->dev, "i.MX Framebuffer driver\n"); 677 dev_info(&pdev->dev, "i.MX Framebuffer driver\n");
665 678
@@ -679,6 +692,9 @@ static int __init imxfb_probe(struct platform_device *pdev)
679 692
680 fbi = info->par; 693 fbi = info->par;
681 694
695 if (!fb_mode)
696 fb_mode = pdata->mode[0].mode.name;
697
682 platform_set_drvdata(pdev, info); 698 platform_set_drvdata(pdev, info);
683 699
684 ret = imxfb_init_fbinfo(pdev); 700 ret = imxfb_init_fbinfo(pdev);
@@ -736,6 +752,13 @@ static int __init imxfb_probe(struct platform_device *pdev)
736 goto failed_platform_init; 752 goto failed_platform_init;
737 } 753 }
738 754
755 fbi->mode = pdata->mode;
756 fbi->num_modes = pdata->num_modes;
757
758 INIT_LIST_HEAD(&info->modelist);
759 for (i = 0; i < pdata->num_modes; i++)
760 fb_add_videomode(&pdata->mode[i].mode, &info->modelist);
761
739 /* 762 /*
740 * This makes sure that our colour bitfield 763 * This makes sure that our colour bitfield
741 * descriptors are correctly initialised. 764 * descriptors are correctly initialised.
@@ -828,8 +851,34 @@ static struct platform_driver imxfb_driver = {
828 }, 851 },
829}; 852};
830 853
854static int imxfb_setup(void)
855{
856#ifndef MODULE
857 char *opt, *options = NULL;
858
859 if (fb_get_options("imxfb", &options))
860 return -ENODEV;
861
862 if (!options || !*options)
863 return 0;
864
865 while ((opt = strsep(&options, ",")) != NULL) {
866 if (!*opt)
867 continue;
868 else
869 fb_mode = opt;
870 }
871#endif
872 return 0;
873}
874
831int __init imxfb_init(void) 875int __init imxfb_init(void)
832{ 876{
877 int ret = imxfb_setup();
878
879 if (ret < 0)
880 return ret;
881
833 return platform_driver_probe(&imxfb_driver, imxfb_probe); 882 return platform_driver_probe(&imxfb_driver, imxfb_probe);
834} 883}
835 884