diff options
-rw-r--r-- | arch/arm/mach-mx2/mx27ads.c | 36 | ||||
-rw-r--r-- | arch/arm/mach-mx2/pcm970-baseboard.c | 83 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/imxfb.h | 26 | ||||
-rw-r--r-- | drivers/video/imxfb.c | 191 |
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 | ||
186 | static struct imx_fb_platform_data mx27ads_fb_data = { | 186 | static 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, | 206 | static 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 | /* | 128 | static 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", |
132 | static 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, | 182 | static 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 | ||
50 | struct imx_fb_platform_data { | 52 | struct 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; | 58 | struct 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. */ | ||
134 | static 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 | ||
305 | static 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 = { | |||
469 | static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info) | 526 | static 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 | ||
854 | static 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 | |||
831 | int __init imxfb_init(void) | 875 | int __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 | ||