aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/s3c-fb.c
diff options
context:
space:
mode:
authorThomas Abraham <thomas.abraham@linaro.org>2012-03-24 12:28:45 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-04-09 12:11:23 -0400
commita4196febbe75e2cc8fcb7af6460d2c3ef208d66c (patch)
treeeff279e45c63a45278c99341f14a56dba53496c9 /drivers/video/s3c-fb.c
parentb78f29ca0516266431688c5eb42d39ce42ec039a (diff)
video: s3c-fb: move video interface timing out of window setup data
The video interface timing is independent of the window setup data. The resolution of the window can be smaller than that of the lcd panel to which the video data is output. So move the video timing data from the per-window setup data to the platform specific section in the platform data. This also removes the restriction that atleast one window should have the same resolution as that of the panel attached. Cc: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org> Acked-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/s3c-fb.c')
-rw-r--r--drivers/video/s3c-fb.c112
1 files changed, 61 insertions, 51 deletions
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];