]> Pileus Git - ~andy/linux/blobdiff - drivers/video/da8xx-fb.c
Merge branch 'at91-fixes' of git://github.com/at91linux/linux-at91 into fixes
[~andy/linux] / drivers / video / da8xx-fb.c
index 29577bf1f559070044ee2c9f50d300d86745f78e..47118c75a4c07fc2190601db42d9942ad7030053 100644 (file)
@@ -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: