aboutsummaryrefslogtreecommitdiffstats
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 @@
32#include <linux/console.h> 32#include <linux/console.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <video/da8xx-fb.h> 34#include <video/da8xx-fb.h>
35#include <asm/div64.h>
35 36
36#define DRIVER_NAME "da8xx_lcdc" 37#define DRIVER_NAME "da8xx_lcdc"
37 38
@@ -161,6 +162,7 @@ struct da8xx_fb_par {
161 int vsync_timeout; 162 int vsync_timeout;
162#ifdef CONFIG_CPU_FREQ 163#ifdef CONFIG_CPU_FREQ
163 struct notifier_block freq_transition; 164 struct notifier_block freq_transition;
165 unsigned int lcd_fck_rate;
164#endif 166#endif
165 void (*panel_power_ctrl)(int); 167 void (*panel_power_ctrl)(int);
166}; 168};
@@ -174,7 +176,6 @@ static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
174 .activate = 0, 176 .activate = 0,
175 .height = -1, 177 .height = -1,
176 .width = -1, 178 .width = -1,
177 .pixclock = 46666, /* 46us - AUO display */
178 .accel_flags = 0, 179 .accel_flags = 0,
179 .left_margin = LEFT_MARGIN, 180 .left_margin = LEFT_MARGIN,
180 .right_margin = RIGHT_MARGIN, 181 .right_margin = RIGHT_MARGIN,
@@ -238,6 +239,20 @@ static struct da8xx_panel known_lcd_panels[] = {
238 .pxl_clk = 7833600, 239 .pxl_clk = 7833600,
239 .invert_pxl_clk = 0, 240 .invert_pxl_clk = 0,
240 }, 241 },
242 [2] = {
243 /* Hitachi SP10Q010 */
244 .name = "SP10Q010",
245 .width = 320,
246 .height = 240,
247 .hfp = 10,
248 .hbp = 10,
249 .hsw = 10,
250 .vfp = 10,
251 .vbp = 10,
252 .vsw = 10,
253 .pxl_clk = 7833600,
254 .invert_pxl_clk = 0,
255 },
241}; 256};
242 257
243/* Enable the Raster Engine of the LCD Controller */ 258/* Enable the Raster Engine of the LCD Controller */
@@ -546,7 +561,26 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
546 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 561 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
547 return 1; 562 return 1;
548 563
549 if (info->var.bits_per_pixel == 8) { 564 if (info->var.bits_per_pixel == 4) {
565 if (regno > 15)
566 return 1;
567
568 if (info->var.grayscale) {
569 pal = regno;
570 } else {
571 red >>= 4;
572 green >>= 8;
573 blue >>= 12;
574
575 pal = (red & 0x0f00);
576 pal |= (green & 0x00f0);
577 pal |= (blue & 0x000f);
578 }
579 if (regno == 0)
580 pal |= 0x2000;
581 palette[regno] = pal;
582
583 } else if (info->var.bits_per_pixel == 8) {
550 red >>= 4; 584 red >>= 4;
551 green >>= 8; 585 green >>= 8;
552 blue >>= 12; 586 blue >>= 12;
@@ -801,6 +835,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
801 var->blue.length = 8; 835 var->blue.length = 8;
802 var->transp.offset = 0; 836 var->transp.offset = 0;
803 var->transp.length = 0; 837 var->transp.length = 0;
838 var->nonstd = 0;
804 break; 839 break;
805 case 4: 840 case 4:
806 var->red.offset = 0; 841 var->red.offset = 0;
@@ -811,6 +846,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
811 var->blue.length = 4; 846 var->blue.length = 4;
812 var->transp.offset = 0; 847 var->transp.offset = 0;
813 var->transp.length = 0; 848 var->transp.length = 0;
849 var->nonstd = FB_NONSTD_REV_PIX_IN_B;
814 break; 850 break;
815 case 16: /* RGB 565 */ 851 case 16: /* RGB 565 */
816 var->red.offset = 11; 852 var->red.offset = 11;
@@ -821,6 +857,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
821 var->blue.length = 5; 857 var->blue.length = 5;
822 var->transp.offset = 0; 858 var->transp.offset = 0;
823 var->transp.length = 0; 859 var->transp.length = 0;
860 var->nonstd = 0;
824 break; 861 break;
825 default: 862 default:
826 err = -EINVAL; 863 err = -EINVAL;
@@ -840,11 +877,13 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
840 struct da8xx_fb_par *par; 877 struct da8xx_fb_par *par;
841 878
842 par = container_of(nb, struct da8xx_fb_par, freq_transition); 879 par = container_of(nb, struct da8xx_fb_par, freq_transition);
843 if (val == CPUFREQ_PRECHANGE) { 880 if (val == CPUFREQ_POSTCHANGE) {
844 lcd_disable_raster(); 881 if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
845 } else if (val == CPUFREQ_POSTCHANGE) { 882 par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
846 lcd_calc_clk_divider(par); 883 lcd_disable_raster();
847 lcd_enable_raster(); 884 lcd_calc_clk_divider(par);
885 lcd_enable_raster();
886 }
848 } 887 }
849 888
850 return 0; 889 return 0;
@@ -1048,6 +1087,22 @@ static struct fb_ops da8xx_fb_ops = {
1048 .fb_blank = cfb_blank, 1087 .fb_blank = cfb_blank,
1049}; 1088};
1050 1089
1090/* Calculate and return pixel clock period in pico seconds */
1091static unsigned int da8xxfb_pixel_clk_period(struct da8xx_fb_par *par)
1092{
1093 unsigned int lcd_clk, div;
1094 unsigned int configured_pix_clk;
1095 unsigned long long pix_clk_period_picosec = 1000000000000ULL;
1096
1097 lcd_clk = clk_get_rate(par->lcdc_clk);
1098 div = lcd_clk / par->pxl_clk;
1099 configured_pix_clk = (lcd_clk / div);
1100
1101 do_div(pix_clk_period_picosec, configured_pix_clk);
1102
1103 return pix_clk_period_picosec;
1104}
1105
1051static int __devinit fb_probe(struct platform_device *device) 1106static int __devinit fb_probe(struct platform_device *device)
1052{ 1107{
1053 struct da8xx_lcdc_platform_data *fb_pdata = 1108 struct da8xx_lcdc_platform_data *fb_pdata =
@@ -1137,6 +1192,9 @@ static int __devinit fb_probe(struct platform_device *device)
1137 1192
1138 par = da8xx_fb_info->par; 1193 par = da8xx_fb_info->par;
1139 par->lcdc_clk = fb_clk; 1194 par->lcdc_clk = fb_clk;
1195#ifdef CONFIG_CPU_FREQ
1196 par->lcd_fck_rate = clk_get_rate(fb_clk);
1197#endif
1140 par->pxl_clk = lcdc_info->pxl_clk; 1198 par->pxl_clk = lcdc_info->pxl_clk;
1141 if (fb_pdata->panel_power_ctrl) { 1199 if (fb_pdata->panel_power_ctrl) {
1142 par->panel_power_ctrl = fb_pdata->panel_power_ctrl; 1200 par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
@@ -1209,6 +1267,11 @@ static int __devinit fb_probe(struct platform_device *device)
1209 1267
1210 da8xx_fb_var.hsync_len = lcdc_info->hsw; 1268 da8xx_fb_var.hsync_len = lcdc_info->hsw;
1211 da8xx_fb_var.vsync_len = lcdc_info->vsw; 1269 da8xx_fb_var.vsync_len = lcdc_info->vsw;
1270 da8xx_fb_var.right_margin = lcdc_info->hfp;
1271 da8xx_fb_var.left_margin = lcdc_info->hbp;
1272 da8xx_fb_var.lower_margin = lcdc_info->vfp;
1273 da8xx_fb_var.upper_margin = lcdc_info->vbp;
1274 da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
1212 1275
1213 /* Initialize fbinfo */ 1276 /* Initialize fbinfo */
1214 da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; 1277 da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
@@ -1264,8 +1327,8 @@ static int __devinit fb_probe(struct platform_device *device)
1264irq_freq: 1327irq_freq:
1265#ifdef CONFIG_CPU_FREQ 1328#ifdef CONFIG_CPU_FREQ
1266 lcd_da8xx_cpufreq_deregister(par); 1329 lcd_da8xx_cpufreq_deregister(par);
1267#endif
1268err_cpu_freq: 1330err_cpu_freq:
1331#endif
1269 unregister_framebuffer(da8xx_fb_info); 1332 unregister_framebuffer(da8xx_fb_info);
1270 1333
1271err_dealloc_cmap: 1334err_dealloc_cmap: