diff options
Diffstat (limited to 'drivers/video/da8xx-fb.c')
-rw-r--r-- | drivers/video/da8xx-fb.c | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 47118c75a4c0..7ae9d53f2bf1 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c | |||
@@ -30,7 +30,10 @@ | |||
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/cpufreq.h> | 31 | #include <linux/cpufreq.h> |
32 | #include <linux/console.h> | 32 | #include <linux/console.h> |
33 | #include <linux/spinlock.h> | ||
33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/delay.h> | ||
36 | #include <linux/lcm.h> | ||
34 | #include <video/da8xx-fb.h> | 37 | #include <video/da8xx-fb.h> |
35 | #include <asm/div64.h> | 38 | #include <asm/div64.h> |
36 | 39 | ||
@@ -160,6 +163,13 @@ struct da8xx_fb_par { | |||
160 | wait_queue_head_t vsync_wait; | 163 | wait_queue_head_t vsync_wait; |
161 | int vsync_flag; | 164 | int vsync_flag; |
162 | int vsync_timeout; | 165 | int vsync_timeout; |
166 | spinlock_t lock_for_chan_update; | ||
167 | |||
168 | /* | ||
169 | * LCDC has 2 ping pong DMA channels, channel 0 | ||
170 | * and channel 1. | ||
171 | */ | ||
172 | unsigned int which_dma_channel_done; | ||
163 | #ifdef CONFIG_CPU_FREQ | 173 | #ifdef CONFIG_CPU_FREQ |
164 | struct notifier_block freq_transition; | 174 | struct notifier_block freq_transition; |
165 | unsigned int lcd_fck_rate; | 175 | unsigned int lcd_fck_rate; |
@@ -260,10 +270,18 @@ static inline void lcd_enable_raster(void) | |||
260 | { | 270 | { |
261 | u32 reg; | 271 | u32 reg; |
262 | 272 | ||
273 | /* Put LCDC in reset for several cycles */ | ||
274 | if (lcd_revision == LCD_VERSION_2) | ||
275 | /* Write 1 to reset LCDC */ | ||
276 | lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); | ||
277 | mdelay(1); | ||
278 | |||
263 | /* Bring LCDC out of reset */ | 279 | /* Bring LCDC out of reset */ |
264 | if (lcd_revision == LCD_VERSION_2) | 280 | if (lcd_revision == LCD_VERSION_2) |
265 | lcdc_write(0, LCD_CLK_RESET_REG); | 281 | lcdc_write(0, LCD_CLK_RESET_REG); |
282 | mdelay(1); | ||
266 | 283 | ||
284 | /* Above reset sequence doesnot reset register context */ | ||
267 | reg = lcdc_read(LCD_RASTER_CTRL_REG); | 285 | reg = lcdc_read(LCD_RASTER_CTRL_REG); |
268 | if (!(reg & LCD_RASTER_ENABLE)) | 286 | if (!(reg & LCD_RASTER_ENABLE)) |
269 | lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); | 287 | lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); |
@@ -277,10 +295,6 @@ static inline void lcd_disable_raster(void) | |||
277 | reg = lcdc_read(LCD_RASTER_CTRL_REG); | 295 | reg = lcdc_read(LCD_RASTER_CTRL_REG); |
278 | if (reg & LCD_RASTER_ENABLE) | 296 | if (reg & LCD_RASTER_ENABLE) |
279 | lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); | 297 | lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); |
280 | |||
281 | if (lcd_revision == LCD_VERSION_2) | ||
282 | /* Write 1 to reset LCDC */ | ||
283 | lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); | ||
284 | } | 298 | } |
285 | 299 | ||
286 | static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | 300 | static void lcd_blit(int load_mode, struct da8xx_fb_par *par) |
@@ -344,8 +358,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
344 | lcd_enable_raster(); | 358 | lcd_enable_raster(); |
345 | } | 359 | } |
346 | 360 | ||
347 | /* Configure the Burst Size of DMA */ | 361 | /* Configure the Burst Size and fifo threhold of DMA */ |
348 | static int lcd_cfg_dma(int burst_size) | 362 | static int lcd_cfg_dma(int burst_size, int fifo_th) |
349 | { | 363 | { |
350 | u32 reg; | 364 | u32 reg; |
351 | 365 | ||
@@ -369,6 +383,9 @@ static int lcd_cfg_dma(int burst_size) | |||
369 | default: | 383 | default: |
370 | return -EINVAL; | 384 | return -EINVAL; |
371 | } | 385 | } |
386 | |||
387 | reg |= (fifo_th << 8); | ||
388 | |||
372 | lcdc_write(reg, LCD_DMA_CTRL_REG); | 389 | lcdc_write(reg, LCD_DMA_CTRL_REG); |
373 | 390 | ||
374 | return 0; | 391 | return 0; |
@@ -670,8 +687,8 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | |||
670 | lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) & | 687 | lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) & |
671 | ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); | 688 | ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); |
672 | 689 | ||
673 | /* Configure the DMA burst size. */ | 690 | /* Configure the DMA burst size and fifo threshold. */ |
674 | ret = lcd_cfg_dma(cfg->dma_burst_sz); | 691 | ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th); |
675 | if (ret < 0) | 692 | if (ret < 0) |
676 | return ret; | 693 | return ret; |
677 | 694 | ||
@@ -715,7 +732,6 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) | |||
715 | { | 732 | { |
716 | struct da8xx_fb_par *par = arg; | 733 | struct da8xx_fb_par *par = arg; |
717 | u32 stat = lcdc_read(LCD_MASKED_STAT_REG); | 734 | u32 stat = lcdc_read(LCD_MASKED_STAT_REG); |
718 | u32 reg_int; | ||
719 | 735 | ||
720 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { | 736 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { |
721 | lcd_disable_raster(); | 737 | lcd_disable_raster(); |
@@ -732,10 +748,8 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) | |||
732 | 748 | ||
733 | lcdc_write(stat, LCD_MASKED_STAT_REG); | 749 | lcdc_write(stat, LCD_MASKED_STAT_REG); |
734 | 750 | ||
735 | /* Disable PL completion inerrupt */ | 751 | /* Disable PL completion interrupt */ |
736 | reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) | | 752 | lcdc_write(LCD_V2_PL_INT_ENA, LCD_INT_ENABLE_CLR_REG); |
737 | (LCD_V2_PL_INT_ENA); | ||
738 | lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG); | ||
739 | 753 | ||
740 | /* Setup and start data loading mode */ | 754 | /* Setup and start data loading mode */ |
741 | lcd_blit(LOAD_DATA, par); | 755 | lcd_blit(LOAD_DATA, par); |
@@ -743,6 +757,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) | |||
743 | lcdc_write(stat, LCD_MASKED_STAT_REG); | 757 | lcdc_write(stat, LCD_MASKED_STAT_REG); |
744 | 758 | ||
745 | if (stat & LCD_END_OF_FRAME0) { | 759 | if (stat & LCD_END_OF_FRAME0) { |
760 | par->which_dma_channel_done = 0; | ||
746 | lcdc_write(par->dma_start, | 761 | lcdc_write(par->dma_start, |
747 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 762 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
748 | lcdc_write(par->dma_end, | 763 | lcdc_write(par->dma_end, |
@@ -752,6 +767,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) | |||
752 | } | 767 | } |
753 | 768 | ||
754 | if (stat & LCD_END_OF_FRAME1) { | 769 | if (stat & LCD_END_OF_FRAME1) { |
770 | par->which_dma_channel_done = 1; | ||
755 | lcdc_write(par->dma_start, | 771 | lcdc_write(par->dma_start, |
756 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | 772 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); |
757 | lcdc_write(par->dma_end, | 773 | lcdc_write(par->dma_end, |
@@ -798,6 +814,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) | |||
798 | lcdc_write(stat, LCD_STAT_REG); | 814 | lcdc_write(stat, LCD_STAT_REG); |
799 | 815 | ||
800 | if (stat & LCD_END_OF_FRAME0) { | 816 | if (stat & LCD_END_OF_FRAME0) { |
817 | par->which_dma_channel_done = 0; | ||
801 | lcdc_write(par->dma_start, | 818 | lcdc_write(par->dma_start, |
802 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 819 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
803 | lcdc_write(par->dma_end, | 820 | lcdc_write(par->dma_end, |
@@ -807,6 +824,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) | |||
807 | } | 824 | } |
808 | 825 | ||
809 | if (stat & LCD_END_OF_FRAME1) { | 826 | if (stat & LCD_END_OF_FRAME1) { |
827 | par->which_dma_channel_done = 1; | ||
810 | lcdc_write(par->dma_start, | 828 | lcdc_write(par->dma_start, |
811 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | 829 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); |
812 | lcdc_write(par->dma_end, | 830 | lcdc_write(par->dma_end, |
@@ -1021,11 +1039,14 @@ static int cfb_blank(int blank, struct fb_info *info) | |||
1021 | par->blank = blank; | 1039 | par->blank = blank; |
1022 | switch (blank) { | 1040 | switch (blank) { |
1023 | case FB_BLANK_UNBLANK: | 1041 | case FB_BLANK_UNBLANK: |
1042 | lcd_enable_raster(); | ||
1043 | |||
1024 | if (par->panel_power_ctrl) | 1044 | if (par->panel_power_ctrl) |
1025 | par->panel_power_ctrl(1); | 1045 | par->panel_power_ctrl(1); |
1026 | |||
1027 | lcd_enable_raster(); | ||
1028 | break; | 1046 | break; |
1047 | case FB_BLANK_NORMAL: | ||
1048 | case FB_BLANK_VSYNC_SUSPEND: | ||
1049 | case FB_BLANK_HSYNC_SUSPEND: | ||
1029 | case FB_BLANK_POWERDOWN: | 1050 | case FB_BLANK_POWERDOWN: |
1030 | if (par->panel_power_ctrl) | 1051 | if (par->panel_power_ctrl) |
1031 | par->panel_power_ctrl(0); | 1052 | par->panel_power_ctrl(0); |
@@ -1052,6 +1073,7 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var, | |||
1052 | struct fb_fix_screeninfo *fix = &fbi->fix; | 1073 | struct fb_fix_screeninfo *fix = &fbi->fix; |
1053 | unsigned int end; | 1074 | unsigned int end; |
1054 | unsigned int start; | 1075 | unsigned int start; |
1076 | unsigned long irq_flags; | ||
1055 | 1077 | ||
1056 | if (var->xoffset != fbi->var.xoffset || | 1078 | if (var->xoffset != fbi->var.xoffset || |
1057 | var->yoffset != fbi->var.yoffset) { | 1079 | var->yoffset != fbi->var.yoffset) { |
@@ -1069,6 +1091,21 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var, | |||
1069 | end = start + fbi->var.yres * fix->line_length - 1; | 1091 | end = start + fbi->var.yres * fix->line_length - 1; |
1070 | par->dma_start = start; | 1092 | par->dma_start = start; |
1071 | par->dma_end = end; | 1093 | par->dma_end = end; |
1094 | spin_lock_irqsave(&par->lock_for_chan_update, | ||
1095 | irq_flags); | ||
1096 | if (par->which_dma_channel_done == 0) { | ||
1097 | lcdc_write(par->dma_start, | ||
1098 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | ||
1099 | lcdc_write(par->dma_end, | ||
1100 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | ||
1101 | } else if (par->which_dma_channel_done == 1) { | ||
1102 | lcdc_write(par->dma_start, | ||
1103 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | ||
1104 | lcdc_write(par->dma_end, | ||
1105 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | ||
1106 | } | ||
1107 | spin_unlock_irqrestore(&par->lock_for_chan_update, | ||
1108 | irq_flags); | ||
1072 | } | 1109 | } |
1073 | } | 1110 | } |
1074 | 1111 | ||
@@ -1114,6 +1151,7 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1114 | struct da8xx_fb_par *par; | 1151 | struct da8xx_fb_par *par; |
1115 | resource_size_t len; | 1152 | resource_size_t len; |
1116 | int ret, i; | 1153 | int ret, i; |
1154 | unsigned long ulcm; | ||
1117 | 1155 | ||
1118 | if (fb_pdata == NULL) { | 1156 | if (fb_pdata == NULL) { |
1119 | dev_err(&device->dev, "Can not get platform data\n"); | 1157 | dev_err(&device->dev, "Can not get platform data\n"); |
@@ -1209,7 +1247,8 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1209 | 1247 | ||
1210 | /* allocate frame buffer */ | 1248 | /* allocate frame buffer */ |
1211 | par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp; | 1249 | par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp; |
1212 | par->vram_size = PAGE_ALIGN(par->vram_size/8); | 1250 | ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE); |
1251 | par->vram_size = roundup(par->vram_size/8, ulcm); | ||
1213 | par->vram_size = par->vram_size * LCD_NUM_BUFFERS; | 1252 | par->vram_size = par->vram_size * LCD_NUM_BUFFERS; |
1214 | 1253 | ||
1215 | par->vram_virt = dma_alloc_coherent(NULL, | 1254 | par->vram_virt = dma_alloc_coherent(NULL, |
@@ -1296,6 +1335,8 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1296 | /* initialize the vsync wait queue */ | 1335 | /* initialize the vsync wait queue */ |
1297 | init_waitqueue_head(&par->vsync_wait); | 1336 | init_waitqueue_head(&par->vsync_wait); |
1298 | par->vsync_timeout = HZ / 5; | 1337 | par->vsync_timeout = HZ / 5; |
1338 | par->which_dma_channel_done = -1; | ||
1339 | spin_lock_init(&par->lock_for_chan_update); | ||
1299 | 1340 | ||
1300 | /* Register the Frame Buffer */ | 1341 | /* Register the Frame Buffer */ |
1301 | if (register_framebuffer(da8xx_fb_info) < 0) { | 1342 | if (register_framebuffer(da8xx_fb_info) < 0) { |
@@ -1382,11 +1423,12 @@ static int fb_resume(struct platform_device *dev) | |||
1382 | struct da8xx_fb_par *par = info->par; | 1423 | struct da8xx_fb_par *par = info->par; |
1383 | 1424 | ||
1384 | console_lock(); | 1425 | console_lock(); |
1426 | clk_enable(par->lcdc_clk); | ||
1427 | lcd_enable_raster(); | ||
1428 | |||
1385 | if (par->panel_power_ctrl) | 1429 | if (par->panel_power_ctrl) |
1386 | par->panel_power_ctrl(1); | 1430 | par->panel_power_ctrl(1); |
1387 | 1431 | ||
1388 | clk_enable(par->lcdc_clk); | ||
1389 | lcd_enable_raster(); | ||
1390 | fb_set_suspend(info, 0); | 1432 | fb_set_suspend(info, 0); |
1391 | console_unlock(); | 1433 | console_unlock(); |
1392 | 1434 | ||