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.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 7264aa3b20ff..6b7f2da6f907 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -30,6 +30,7 @@
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>
34#include <linux/lcm.h> 35#include <linux/lcm.h>
35#include <video/da8xx-fb.h> 36#include <video/da8xx-fb.h>
@@ -161,6 +162,13 @@ struct da8xx_fb_par {
161 wait_queue_head_t vsync_wait; 162 wait_queue_head_t vsync_wait;
162 int vsync_flag; 163 int vsync_flag;
163 int vsync_timeout; 164 int vsync_timeout;
165 spinlock_t lock_for_chan_update;
166
167 /*
168 * LCDC has 2 ping pong DMA channels, channel 0
169 * and channel 1.
170 */
171 unsigned int which_dma_channel_done;
164#ifdef CONFIG_CPU_FREQ 172#ifdef CONFIG_CPU_FREQ
165 struct notifier_block freq_transition; 173 struct notifier_block freq_transition;
166 unsigned int lcd_fck_rate; 174 unsigned int lcd_fck_rate;
@@ -741,6 +749,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
741 lcdc_write(stat, LCD_MASKED_STAT_REG); 749 lcdc_write(stat, LCD_MASKED_STAT_REG);
742 750
743 if (stat & LCD_END_OF_FRAME0) { 751 if (stat & LCD_END_OF_FRAME0) {
752 par->which_dma_channel_done = 0;
744 lcdc_write(par->dma_start, 753 lcdc_write(par->dma_start,
745 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); 754 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
746 lcdc_write(par->dma_end, 755 lcdc_write(par->dma_end,
@@ -750,6 +759,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
750 } 759 }
751 760
752 if (stat & LCD_END_OF_FRAME1) { 761 if (stat & LCD_END_OF_FRAME1) {
762 par->which_dma_channel_done = 1;
753 lcdc_write(par->dma_start, 763 lcdc_write(par->dma_start,
754 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); 764 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
755 lcdc_write(par->dma_end, 765 lcdc_write(par->dma_end,
@@ -796,6 +806,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
796 lcdc_write(stat, LCD_STAT_REG); 806 lcdc_write(stat, LCD_STAT_REG);
797 807
798 if (stat & LCD_END_OF_FRAME0) { 808 if (stat & LCD_END_OF_FRAME0) {
809 par->which_dma_channel_done = 0;
799 lcdc_write(par->dma_start, 810 lcdc_write(par->dma_start,
800 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); 811 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
801 lcdc_write(par->dma_end, 812 lcdc_write(par->dma_end,
@@ -805,6 +816,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
805 } 816 }
806 817
807 if (stat & LCD_END_OF_FRAME1) { 818 if (stat & LCD_END_OF_FRAME1) {
819 par->which_dma_channel_done = 1;
808 lcdc_write(par->dma_start, 820 lcdc_write(par->dma_start,
809 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); 821 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
810 lcdc_write(par->dma_end, 822 lcdc_write(par->dma_end,
@@ -1053,6 +1065,7 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
1053 struct fb_fix_screeninfo *fix = &fbi->fix; 1065 struct fb_fix_screeninfo *fix = &fbi->fix;
1054 unsigned int end; 1066 unsigned int end;
1055 unsigned int start; 1067 unsigned int start;
1068 unsigned long irq_flags;
1056 1069
1057 if (var->xoffset != fbi->var.xoffset || 1070 if (var->xoffset != fbi->var.xoffset ||
1058 var->yoffset != fbi->var.yoffset) { 1071 var->yoffset != fbi->var.yoffset) {
@@ -1070,6 +1083,21 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
1070 end = start + fbi->var.yres * fix->line_length - 1; 1083 end = start + fbi->var.yres * fix->line_length - 1;
1071 par->dma_start = start; 1084 par->dma_start = start;
1072 par->dma_end = end; 1085 par->dma_end = end;
1086 spin_lock_irqsave(&par->lock_for_chan_update,
1087 irq_flags);
1088 if (par->which_dma_channel_done == 0) {
1089 lcdc_write(par->dma_start,
1090 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
1091 lcdc_write(par->dma_end,
1092 LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
1093 } else if (par->which_dma_channel_done == 1) {
1094 lcdc_write(par->dma_start,
1095 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
1096 lcdc_write(par->dma_end,
1097 LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
1098 }
1099 spin_unlock_irqrestore(&par->lock_for_chan_update,
1100 irq_flags);
1073 } 1101 }
1074 } 1102 }
1075 1103
@@ -1299,6 +1327,8 @@ static int __devinit fb_probe(struct platform_device *device)
1299 /* initialize the vsync wait queue */ 1327 /* initialize the vsync wait queue */
1300 init_waitqueue_head(&par->vsync_wait); 1328 init_waitqueue_head(&par->vsync_wait);
1301 par->vsync_timeout = HZ / 5; 1329 par->vsync_timeout = HZ / 5;
1330 par->which_dma_channel_done = -1;
1331 spin_lock_init(&par->lock_for_chan_update);
1302 1332
1303 /* Register the Frame Buffer */ 1333 /* Register the Frame Buffer */
1304 if (register_framebuffer(da8xx_fb_info) < 0) { 1334 if (register_framebuffer(da8xx_fb_info) < 0) {