@@ -24,15 +24,16 @@
/**
* struct s3c_fb_pd_win - per window setup data
- * @win_mode: The display parameters to initialise (not for window 0)
+ * @xres : The window X size.
+ * @yres : The window Y size.
* @virtual_x: The virtual X size.
* @virtual_y: The virtual Y size.
*/
struct s3c_fb_pd_win {
- struct fb_videomode win_mode;
-
unsigned short default_bpp;
unsigned short max_bpp;
+ unsigned short xres;
+ unsigned short yres;
unsigned short virtual_x;
unsigned short virtual_y;
};
@@ -45,6 +46,7 @@ struct s3c_fb_pd_win {
* @default_win: default window layer number to be used for UI layer.
* @vidcon0: The base vidcon0 values to control the panel data format.
* @vidcon1: The base vidcon1 values to control the panel data output.
+ * @vtiming: Video timing when connected to a RGB type panel.
* @win: The setup data for each hardware window, or NULL for unused.
* @display_mode: The LCD output display mode.
*
@@ -58,6 +60,7 @@ struct s3c_fb_platdata {
void (*setup_gpio)(void);
struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN];
+ struct fb_videomode *vtiming;
u32 default_win;
@@ -495,7 +495,6 @@ static int s3c_fb_set_par(struct fb_info *info)
u32 alpha = 0;
u32 data;
u32 pagewidth;
- int clkdiv;
dev_dbg(sfb->dev, "setting framebuffer parameters\n");
@@ -532,47 +531,8 @@ static int s3c_fb_set_par(struct fb_info *info)
/* disable the window whilst we update it */
writel(0, regs + WINCON(win_no));
- /* use platform specified window as the basis for the lcd timings */
-
- if (win_no == sfb->pdata->default_win) {
- clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
-
- data = sfb->pdata->vidcon0;
- data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
-
- if (clkdiv > 1)
- data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
- else
- data &= ~VIDCON0_CLKDIR; /* 1:1 clock */
-
- /* write the timing data to the panel */
-
- if (sfb->variant.is_2443)
- data |= (1 << 5);
-
- writel(data, regs + VIDCON0);
-
- s3c_fb_enable(sfb, 1);
-
- data = VIDTCON0_VBPD(var->upper_margin - 1) |
- VIDTCON0_VFPD(var->lower_margin - 1) |
- VIDTCON0_VSPW(var->vsync_len - 1);
-
- writel(data, regs + sfb->variant.vidtcon);
-
- data = VIDTCON1_HBPD(var->left_margin - 1) |
- VIDTCON1_HFPD(var->right_margin - 1) |
- VIDTCON1_HSPW(var->hsync_len - 1);
-
- /* VIDTCON1 */
- writel(data, regs + sfb->variant.vidtcon + 4);
-
- data = VIDTCON2_LINEVAL(var->yres - 1) |
- VIDTCON2_HOZVAL(var->xres - 1) |
- VIDTCON2_LINEVAL_E(var->yres - 1) |
- VIDTCON2_HOZVAL_E(var->xres - 1);
- writel(data, regs + sfb->variant.vidtcon + 8);
- }
+ if (win_no == sfb->pdata->default_win)
+ s3c_fb_enable(sfb, 1);
/* write the buffer address */
@@ -1144,11 +1104,11 @@ static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb,
dev_dbg(sfb->dev, "allocating memory for display\n");
- real_size = windata->win_mode.xres * windata->win_mode.yres;
+ real_size = windata->xres * windata->yres;
virt_size = windata->virtual_x * windata->virtual_y;
dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n",
- real_size, windata->win_mode.xres, windata->win_mode.yres,
+ real_size, windata->xres, windata->yres,
virt_size, windata->virtual_x, windata->virtual_y);
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,
struct s3c_fb_win **res)
{
struct fb_var_screeninfo *var;
- struct fb_videomode *initmode;
+ struct fb_videomode initmode;
struct s3c_fb_pd_win *windata;
struct s3c_fb_win *win;
struct fb_info *fbinfo;
@@ -1251,11 +1211,11 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
}
windata = sfb->pdata->win[win_no];
- initmode = &windata->win_mode;
+ initmode = *sfb->pdata->vtiming;
WARN_ON(windata->max_bpp == 0);
- WARN_ON(windata->win_mode.xres == 0);
- WARN_ON(windata->win_mode.yres == 0);
+ WARN_ON(windata->xres == 0);
+ WARN_ON(windata->yres == 0);
win = fbinfo->par;
*res = win;
@@ -1294,7 +1254,9 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
}
/* setup the initial video mode from the window */
- fb_videomode_to_var(&fbinfo->var, initmode);
+ initmode.xres = windata->xres;
+ initmode.yres = windata->yres;
+ fb_videomode_to_var(&fbinfo->var, &initmode);
fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
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,
}
/**
+ * s3c_fb_set_rgb_timing() - set video timing for rgb interface.
+ * @sfb: The base resources for the hardware.
+ *
+ * Set horizontal and vertical lcd rgb interface timing.
+ */
+static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb)
+{
+ struct fb_videomode *vmode = sfb->pdata->vtiming;
+ void __iomem *regs = sfb->regs;
+ int clkdiv;
+ u32 data;
+
+ if (!vmode->pixclock)
+ s3c_fb_missing_pixclock(vmode);
+
+ clkdiv = s3c_fb_calc_pixclk(sfb, vmode->pixclock);
+
+ data = sfb->pdata->vidcon0;
+ data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
+
+ if (clkdiv > 1)
+ data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
+ else
+ data &= ~VIDCON0_CLKDIR; /* 1:1 clock */
+
+ if (sfb->variant.is_2443)
+ data |= (1 << 5);
+ writel(data, regs + VIDCON0);
+
+ data = VIDTCON0_VBPD(vmode->upper_margin - 1) |
+ VIDTCON0_VFPD(vmode->lower_margin - 1) |
+ VIDTCON0_VSPW(vmode->vsync_len - 1);
+ writel(data, regs + sfb->variant.vidtcon);
+
+ data = VIDTCON1_HBPD(vmode->left_margin - 1) |
+ VIDTCON1_HFPD(vmode->right_margin - 1) |
+ VIDTCON1_HSPW(vmode->hsync_len - 1);
+ writel(data, regs + sfb->variant.vidtcon + 4);
+
+ data = VIDTCON2_LINEVAL(vmode->yres - 1) |
+ VIDTCON2_HOZVAL(vmode->xres - 1) |
+ VIDTCON2_LINEVAL_E(vmode->yres - 1) |
+ VIDTCON2_HOZVAL_E(vmode->xres - 1);
+ writel(data, regs + sfb->variant.vidtcon + 8);
+}
+
+/**
* s3c_fb_clear_win() - clear hardware window registers.
* @sfb: The base resources for the hardware.
* @win: The window to process.
@@ -1481,15 +1490,14 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
writel(0xffffff, regs + WKEYCON1);
}
+ s3c_fb_set_rgb_timing(sfb);
+
/* we have the register setup, start allocating framebuffers */
for (win = 0; win < fbdrv->variant.nr_windows; win++) {
if (!pd->win[win])
continue;
- if (!pd->win[win]->win_mode.pixclock)
- s3c_fb_missing_pixclock(&pd->win[win]->win_mode);
-
ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
&sfb->windows[win]);
if (ret < 0) {
@@ -1623,6 +1631,8 @@ static int s3c_fb_resume(struct device *dev)
shadow_protect_win(win, 0);
}
+ s3c_fb_set_rgb_timing(sfb);
+
/* restore framebuffers */
for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
win = sfb->windows[win_no];