summaryrefslogtreecommitdiffstats
path: root/drivers/video/da8xx-fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/da8xx-fb.c')
-rw-r--r--drivers/video/da8xx-fb.c79
1 files changed, 71 insertions, 8 deletions
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 29577bf1f559..47118c75a4c0 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -32,6 +32,7 @@
#include <linux/console.h>
#include <linux/slab.h>
#include <video/da8xx-fb.h>
+#include <asm/div64.h>
#define DRIVER_NAME "da8xx_lcdc"
@@ -161,6 +162,7 @@ struct da8xx_fb_par {
int vsync_timeout;
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
+ unsigned int lcd_fck_rate;
#endif
void (*panel_power_ctrl)(int);
};
@@ -174,7 +176,6 @@ static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
.activate = 0,
.height = -1,
.width = -1,
- .pixclock = 46666, /* 46us - AUO display */
.accel_flags = 0,
.left_margin = LEFT_MARGIN,
.right_margin = RIGHT_MARGIN,
@@ -238,6 +239,20 @@ static struct da8xx_panel known_lcd_panels[] = {
.pxl_clk = 7833600,
.invert_pxl_clk = 0,
},
+ [2] = {
+ /* Hitachi SP10Q010 */
+ .name = "SP10Q010",
+ .width = 320,
+ .height = 240,
+ .hfp = 10,
+ .hbp = 10,
+ .hsw = 10,
+ .vfp = 10,
+ .vbp = 10,
+ .vsw = 10,
+ .pxl_clk = 7833600,
+ .invert_pxl_clk = 0,
+ },
};
/* Enable the Raster Engine of the LCD Controller */
@@ -546,7 +561,26 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
return 1;
- if (info->var.bits_per_pixel == 8) {
+ if (info->var.bits_per_pixel == 4) {
+ if (regno > 15)
+ return 1;
+
+ if (info->var.grayscale) {
+ pal = regno;
+ } else {
+ red >>= 4;
+ green >>= 8;
+ blue >>= 12;
+
+ pal = (red & 0x0f00);
+ pal |= (green & 0x00f0);
+ pal |= (blue & 0x000f);
+ }
+ if (regno == 0)
+ pal |= 0x2000;
+ palette[regno] = pal;
+
+ } else if (info->var.bits_per_pixel == 8) {
red >>= 4;
green >>= 8;
blue >>= 12;
@@ -801,6 +835,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
+ var->nonstd = 0;
break;
case 4:
var->red.offset = 0;
@@ -811,6 +846,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
var->blue.length = 4;
var->transp.offset = 0;
var->transp.length = 0;
+ var->nonstd = FB_NONSTD_REV_PIX_IN_B;
break;
case 16: /* RGB 565 */
var->red.offset = 11;
@@ -821,6 +857,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
+ var->nonstd = 0;
break;
default:
err = -EINVAL;
@@ -840,11 +877,13 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
struct da8xx_fb_par *par;
par = container_of(nb, struct da8xx_fb_par, freq_transition);
- if (val == CPUFREQ_PRECHANGE) {
- lcd_disable_raster();
- } else if (val == CPUFREQ_POSTCHANGE) {
- lcd_calc_clk_divider(par);
- lcd_enable_raster();
+ if (val == CPUFREQ_POSTCHANGE) {
+ if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
+ par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
+ lcd_disable_raster();
+ lcd_calc_clk_divider(par);
+ lcd_enable_raster();
+ }
}
return 0;
@@ -1048,6 +1087,22 @@ static struct fb_ops da8xx_fb_ops = {
.fb_blank = cfb_blank,
};
+/* Calculate and return pixel clock period in pico seconds */
+static unsigned int da8xxfb_pixel_clk_period(struct da8xx_fb_par *par)
+{
+ unsigned int lcd_clk, div;
+ unsigned int configured_pix_clk;
+ unsigned long long pix_clk_period_picosec = 1000000000000ULL;
+
+ lcd_clk = clk_get_rate(par->lcdc_clk);
+ div = lcd_clk / par->pxl_clk;
+ configured_pix_clk = (lcd_clk / div);
+
+ do_div(pix_clk_period_picosec, configured_pix_clk);
+
+ return pix_clk_period_picosec;
+}
+
static int __devinit fb_probe(struct platform_device *device)
{
struct da8xx_lcdc_platform_data *fb_pdata =
@@ -1137,6 +1192,9 @@ static int __devinit fb_probe(struct platform_device *device)
par = da8xx_fb_info->par;
par->lcdc_clk = fb_clk;
+#ifdef CONFIG_CPU_FREQ
+ par->lcd_fck_rate = clk_get_rate(fb_clk);
+#endif
par->pxl_clk = lcdc_info->pxl_clk;
if (fb_pdata->panel_power_ctrl) {
par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
@@ -1209,6 +1267,11 @@ static int __devinit fb_probe(struct platform_device *device)
da8xx_fb_var.hsync_len = lcdc_info->hsw;
da8xx_fb_var.vsync_len = lcdc_info->vsw;
+ da8xx_fb_var.right_margin = lcdc_info->hfp;
+ da8xx_fb_var.left_margin = lcdc_info->hbp;
+ da8xx_fb_var.lower_margin = lcdc_info->vfp;
+ da8xx_fb_var.upper_margin = lcdc_info->vbp;
+ da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
/* Initialize fbinfo */
da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
@@ -1264,8 +1327,8 @@ static int __devinit fb_probe(struct platform_device *device)
irq_freq:
#ifdef CONFIG_CPU_FREQ
lcd_da8xx_cpufreq_deregister(par);
-#endif
err_cpu_freq:
+#endif
unregister_framebuffer(da8xx_fb_info);
err_dealloc_cmap: