diff options
-rw-r--r-- | arch/arm/plat-samsung/include/plat/fb.h | 9 | ||||
-rw-r--r-- | drivers/video/s3c-fb.c | 112 |
2 files changed, 67 insertions, 54 deletions
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h index 0fedf47fa502..39d6bd7af308 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h | |||
@@ -24,15 +24,16 @@ | |||
24 | 24 | ||
25 | /** | 25 | /** |
26 | * struct s3c_fb_pd_win - per window setup data | 26 | * struct s3c_fb_pd_win - per window setup data |
27 | * @win_mode: The display parameters to initialise (not for window 0) | 27 | * @xres : The window X size. |
28 | * @yres : The window Y size. | ||
28 | * @virtual_x: The virtual X size. | 29 | * @virtual_x: The virtual X size. |
29 | * @virtual_y: The virtual Y size. | 30 | * @virtual_y: The virtual Y size. |
30 | */ | 31 | */ |
31 | struct s3c_fb_pd_win { | 32 | struct s3c_fb_pd_win { |
32 | struct fb_videomode win_mode; | ||
33 | |||
34 | unsigned short default_bpp; | 33 | unsigned short default_bpp; |
35 | unsigned short max_bpp; | 34 | unsigned short max_bpp; |
35 | unsigned short xres; | ||
36 | unsigned short yres; | ||
36 | unsigned short virtual_x; | 37 | unsigned short virtual_x; |
37 | unsigned short virtual_y; | 38 | unsigned short virtual_y; |
38 | }; | 39 | }; |
@@ -45,6 +46,7 @@ struct s3c_fb_pd_win { | |||
45 | * @default_win: default window layer number to be used for UI layer. | 46 | * @default_win: default window layer number to be used for UI layer. |
46 | * @vidcon0: The base vidcon0 values to control the panel data format. | 47 | * @vidcon0: The base vidcon0 values to control the panel data format. |
47 | * @vidcon1: The base vidcon1 values to control the panel data output. | 48 | * @vidcon1: The base vidcon1 values to control the panel data output. |
49 | * @vtiming: Video timing when connected to a RGB type panel. | ||
48 | * @win: The setup data for each hardware window, or NULL for unused. | 50 | * @win: The setup data for each hardware window, or NULL for unused. |
49 | * @display_mode: The LCD output display mode. | 51 | * @display_mode: The LCD output display mode. |
50 | * | 52 | * |
@@ -58,6 +60,7 @@ struct s3c_fb_platdata { | |||
58 | void (*setup_gpio)(void); | 60 | void (*setup_gpio)(void); |
59 | 61 | ||
60 | struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; | 62 | struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; |
63 | struct fb_videomode *vtiming; | ||
61 | 64 | ||
62 | u32 default_win; | 65 | u32 default_win; |
63 | 66 | ||
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index f3105160bf98..c94f40d2cc2e 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
@@ -495,7 +495,6 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
495 | u32 alpha = 0; | 495 | u32 alpha = 0; |
496 | u32 data; | 496 | u32 data; |
497 | u32 pagewidth; | 497 | u32 pagewidth; |
498 | int clkdiv; | ||
499 | 498 | ||
500 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); | 499 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); |
501 | 500 | ||
@@ -532,48 +531,9 @@ static int s3c_fb_set_par(struct fb_info *info) | |||
532 | /* disable the window whilst we update it */ | 531 | /* disable the window whilst we update it */ |
533 | writel(0, regs + WINCON(win_no)); | 532 | writel(0, regs + WINCON(win_no)); |
534 | 533 | ||
535 | /* use platform specified window as the basis for the lcd timings */ | 534 | if (win_no == sfb->pdata->default_win) |
536 | |||
537 | if (win_no == sfb->pdata->default_win) { | ||
538 | clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); | ||
539 | |||
540 | data = sfb->pdata->vidcon0; | ||
541 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); | ||
542 | |||
543 | if (clkdiv > 1) | ||
544 | data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; | ||
545 | else | ||
546 | data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ | ||
547 | |||
548 | /* write the timing data to the panel */ | ||
549 | |||
550 | if (sfb->variant.is_2443) | ||
551 | data |= (1 << 5); | ||
552 | |||
553 | writel(data, regs + VIDCON0); | ||
554 | |||
555 | s3c_fb_enable(sfb, 1); | 535 | s3c_fb_enable(sfb, 1); |
556 | 536 | ||
557 | data = VIDTCON0_VBPD(var->upper_margin - 1) | | ||
558 | VIDTCON0_VFPD(var->lower_margin - 1) | | ||
559 | VIDTCON0_VSPW(var->vsync_len - 1); | ||
560 | |||
561 | writel(data, regs + sfb->variant.vidtcon); | ||
562 | |||
563 | data = VIDTCON1_HBPD(var->left_margin - 1) | | ||
564 | VIDTCON1_HFPD(var->right_margin - 1) | | ||
565 | VIDTCON1_HSPW(var->hsync_len - 1); | ||
566 | |||
567 | /* VIDTCON1 */ | ||
568 | writel(data, regs + sfb->variant.vidtcon + 4); | ||
569 | |||
570 | data = VIDTCON2_LINEVAL(var->yres - 1) | | ||
571 | VIDTCON2_HOZVAL(var->xres - 1) | | ||
572 | VIDTCON2_LINEVAL_E(var->yres - 1) | | ||
573 | VIDTCON2_HOZVAL_E(var->xres - 1); | ||
574 | writel(data, regs + sfb->variant.vidtcon + 8); | ||
575 | } | ||
576 | |||
577 | /* write the buffer address */ | 537 | /* write the buffer address */ |
578 | 538 | ||
579 | /* start and end registers stride is 8 */ | 539 | /* start and end registers stride is 8 */ |
@@ -1144,11 +1104,11 @@ static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb, | |||
1144 | 1104 | ||
1145 | dev_dbg(sfb->dev, "allocating memory for display\n"); | 1105 | dev_dbg(sfb->dev, "allocating memory for display\n"); |
1146 | 1106 | ||
1147 | real_size = windata->win_mode.xres * windata->win_mode.yres; | 1107 | real_size = windata->xres * windata->yres; |
1148 | virt_size = windata->virtual_x * windata->virtual_y; | 1108 | virt_size = windata->virtual_x * windata->virtual_y; |
1149 | 1109 | ||
1150 | dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", | 1110 | dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", |
1151 | real_size, windata->win_mode.xres, windata->win_mode.yres, | 1111 | real_size, windata->xres, windata->yres, |
1152 | virt_size, windata->virtual_x, windata->virtual_y); | 1112 | virt_size, windata->virtual_x, windata->virtual_y); |
1153 | 1113 | ||
1154 | size = (real_size > virt_size) ? real_size : virt_size; | 1114 | size = (real_size > virt_size) ? real_size : virt_size; |
@@ -1230,7 +1190,7 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
1230 | struct s3c_fb_win **res) | 1190 | struct s3c_fb_win **res) |
1231 | { | 1191 | { |
1232 | struct fb_var_screeninfo *var; | 1192 | struct fb_var_screeninfo *var; |
1233 | struct fb_videomode *initmode; | 1193 | struct fb_videomode initmode; |
1234 | struct s3c_fb_pd_win *windata; | 1194 | struct s3c_fb_pd_win *windata; |
1235 | struct s3c_fb_win *win; | 1195 | struct s3c_fb_win *win; |
1236 | struct fb_info *fbinfo; | 1196 | struct fb_info *fbinfo; |
@@ -1251,11 +1211,11 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
1251 | } | 1211 | } |
1252 | 1212 | ||
1253 | windata = sfb->pdata->win[win_no]; | 1213 | windata = sfb->pdata->win[win_no]; |
1254 | initmode = &windata->win_mode; | 1214 | initmode = *sfb->pdata->vtiming; |
1255 | 1215 | ||
1256 | WARN_ON(windata->max_bpp == 0); | 1216 | WARN_ON(windata->max_bpp == 0); |
1257 | WARN_ON(windata->win_mode.xres == 0); | 1217 | WARN_ON(windata->xres == 0); |
1258 | WARN_ON(windata->win_mode.yres == 0); | 1218 | WARN_ON(windata->yres == 0); |
1259 | 1219 | ||
1260 | win = fbinfo->par; | 1220 | win = fbinfo->par; |
1261 | *res = win; | 1221 | *res = win; |
@@ -1294,7 +1254,9 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
1294 | } | 1254 | } |
1295 | 1255 | ||
1296 | /* setup the initial video mode from the window */ | 1256 | /* setup the initial video mode from the window */ |
1297 | fb_videomode_to_var(&fbinfo->var, initmode); | 1257 | initmode.xres = windata->xres; |
1258 | initmode.yres = windata->yres; | ||
1259 | fb_videomode_to_var(&fbinfo->var, &initmode); | ||
1298 | 1260 | ||
1299 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; | 1261 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; |
1300 | fbinfo->fix.accel = FB_ACCEL_NONE; | 1262 | fbinfo->fix.accel = FB_ACCEL_NONE; |
@@ -1339,6 +1301,53 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | |||
1339 | } | 1301 | } |
1340 | 1302 | ||
1341 | /** | 1303 | /** |
1304 | * s3c_fb_set_rgb_timing() - set video timing for rgb interface. | ||
1305 | * @sfb: The base resources for the hardware. | ||
1306 | * | ||
1307 | * Set horizontal and vertical lcd rgb interface timing. | ||
1308 | */ | ||
1309 | static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb) | ||
1310 | { | ||
1311 | struct fb_videomode *vmode = sfb->pdata->vtiming; | ||
1312 | void __iomem *regs = sfb->regs; | ||
1313 | int clkdiv; | ||
1314 | u32 data; | ||
1315 | |||
1316 | if (!vmode->pixclock) | ||
1317 | s3c_fb_missing_pixclock(vmode); | ||
1318 | |||
1319 | clkdiv = s3c_fb_calc_pixclk(sfb, vmode->pixclock); | ||
1320 | |||
1321 | data = sfb->pdata->vidcon0; | ||
1322 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); | ||
1323 | |||
1324 | if (clkdiv > 1) | ||
1325 | data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; | ||
1326 | else | ||
1327 | data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ | ||
1328 | |||
1329 | if (sfb->variant.is_2443) | ||
1330 | data |= (1 << 5); | ||
1331 | writel(data, regs + VIDCON0); | ||
1332 | |||
1333 | data = VIDTCON0_VBPD(vmode->upper_margin - 1) | | ||
1334 | VIDTCON0_VFPD(vmode->lower_margin - 1) | | ||
1335 | VIDTCON0_VSPW(vmode->vsync_len - 1); | ||
1336 | writel(data, regs + sfb->variant.vidtcon); | ||
1337 | |||
1338 | data = VIDTCON1_HBPD(vmode->left_margin - 1) | | ||
1339 | VIDTCON1_HFPD(vmode->right_margin - 1) | | ||
1340 | VIDTCON1_HSPW(vmode->hsync_len - 1); | ||
1341 | writel(data, regs + sfb->variant.vidtcon + 4); | ||
1342 | |||
1343 | data = VIDTCON2_LINEVAL(vmode->yres - 1) | | ||
1344 | VIDTCON2_HOZVAL(vmode->xres - 1) | | ||
1345 | VIDTCON2_LINEVAL_E(vmode->yres - 1) | | ||
1346 | VIDTCON2_HOZVAL_E(vmode->xres - 1); | ||
1347 | writel(data, regs + sfb->variant.vidtcon + 8); | ||
1348 | } | ||
1349 | |||
1350 | /** | ||
1342 | * s3c_fb_clear_win() - clear hardware window registers. | 1351 | * s3c_fb_clear_win() - clear hardware window registers. |
1343 | * @sfb: The base resources for the hardware. | 1352 | * @sfb: The base resources for the hardware. |
1344 | * @win: The window to process. | 1353 | * @win: The window to process. |
@@ -1481,15 +1490,14 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
1481 | writel(0xffffff, regs + WKEYCON1); | 1490 | writel(0xffffff, regs + WKEYCON1); |
1482 | } | 1491 | } |
1483 | 1492 | ||
1493 | s3c_fb_set_rgb_timing(sfb); | ||
1494 | |||
1484 | /* we have the register setup, start allocating framebuffers */ | 1495 | /* we have the register setup, start allocating framebuffers */ |
1485 | 1496 | ||
1486 | for (win = 0; win < fbdrv->variant.nr_windows; win++) { | 1497 | for (win = 0; win < fbdrv->variant.nr_windows; win++) { |
1487 | if (!pd->win[win]) | 1498 | if (!pd->win[win]) |
1488 | continue; | 1499 | continue; |
1489 | 1500 | ||
1490 | if (!pd->win[win]->win_mode.pixclock) | ||
1491 | s3c_fb_missing_pixclock(&pd->win[win]->win_mode); | ||
1492 | |||
1493 | ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win], | 1501 | ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win], |
1494 | &sfb->windows[win]); | 1502 | &sfb->windows[win]); |
1495 | if (ret < 0) { | 1503 | if (ret < 0) { |
@@ -1623,6 +1631,8 @@ static int s3c_fb_resume(struct device *dev) | |||
1623 | shadow_protect_win(win, 0); | 1631 | shadow_protect_win(win, 0); |
1624 | } | 1632 | } |
1625 | 1633 | ||
1634 | s3c_fb_set_rgb_timing(sfb); | ||
1635 | |||
1626 | /* restore framebuffers */ | 1636 | /* restore framebuffers */ |
1627 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { | 1637 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { |
1628 | win = sfb->windows[win_no]; | 1638 | win = sfb->windows[win_no]; |