diff options
Diffstat (limited to 'drivers/video/da8xx-fb.c')
-rw-r--r-- | drivers/video/da8xx-fb.c | 30 |
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) { |