aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-samsung/include/plat/fb.h9
-rw-r--r--drivers/video/s3c-fb.c112
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 */
31struct s3c_fb_pd_win { 32struct 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 */
1309static 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];