aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/da8xx-fb.c
diff options
context:
space:
mode:
authorManjunathappa, Prakash <prakash.pm@ti.com>2012-08-24 09:13:00 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-09-22 17:17:57 -0400
commita481b37a9e18e7d7cacf7ef1080bcdd718ec8e9d (patch)
tree73257a560de9f54fb33425efd713ea993d842372 /drivers/video/da8xx-fb.c
parent1d90a66f5bf25b60951b01f196bd7e4282c69b73 (diff)
da8xx-fb: allow frame to complete after disabling LCDC
Wait for active frame transfer to complete after disabling LCDC. At the same this wait is not be required when there are sync and underflow errors. Patch applies for revision 2 of LCDC present am335x. More information on disable and reset sequence can be found in section 13.4.6 of AM335x TRM @www.ti.com/am335x. Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/da8xx-fb.c')
-rw-r--r--drivers/video/da8xx-fb.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 761c8d1ad9a0..03ebc0ddcfdb 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -27,6 +27,7 @@
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/uaccess.h> 28#include <linux/uaccess.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/wait.h>
30#include <linux/clk.h> 31#include <linux/clk.h>
31#include <linux/cpufreq.h> 32#include <linux/cpufreq.h>
32#include <linux/console.h> 33#include <linux/console.h>
@@ -48,6 +49,7 @@
48#define LCD_PL_LOAD_DONE BIT(6) 49#define LCD_PL_LOAD_DONE BIT(6)
49#define LCD_FIFO_UNDERFLOW BIT(5) 50#define LCD_FIFO_UNDERFLOW BIT(5)
50#define LCD_SYNC_LOST BIT(2) 51#define LCD_SYNC_LOST BIT(2)
52#define LCD_FRAME_DONE BIT(0)
51 53
52/* LCD DMA Control Register */ 54/* LCD DMA Control Register */
53#define LCD_DMA_BURST_SIZE(x) ((x) << 4) 55#define LCD_DMA_BURST_SIZE(x) ((x) << 4)
@@ -137,6 +139,8 @@ static resource_size_t da8xx_fb_reg_base;
137static struct resource *lcdc_regs; 139static struct resource *lcdc_regs;
138static unsigned int lcd_revision; 140static unsigned int lcd_revision;
139static irq_handler_t lcdc_irq_handler; 141static irq_handler_t lcdc_irq_handler;
142static wait_queue_head_t frame_done_wq;
143static int frame_done_flag;
140 144
141static inline unsigned int lcdc_read(unsigned int addr) 145static inline unsigned int lcdc_read(unsigned int addr)
142{ 146{
@@ -290,13 +294,26 @@ static inline void lcd_enable_raster(void)
290} 294}
291 295
292/* Disable the Raster Engine of the LCD Controller */ 296/* Disable the Raster Engine of the LCD Controller */
293static inline void lcd_disable_raster(void) 297static inline void lcd_disable_raster(bool wait_for_frame_done)
294{ 298{
295 u32 reg; 299 u32 reg;
300 int ret;
296 301
297 reg = lcdc_read(LCD_RASTER_CTRL_REG); 302 reg = lcdc_read(LCD_RASTER_CTRL_REG);
298 if (reg & LCD_RASTER_ENABLE) 303 if (reg & LCD_RASTER_ENABLE)
299 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); 304 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
305 else
306 /* return if already disabled */
307 return;
308
309 if ((wait_for_frame_done == true) && (lcd_revision == LCD_VERSION_2)) {
310 frame_done_flag = 0;
311 ret = wait_event_interruptible_timeout(frame_done_wq,
312 frame_done_flag != 0,
313 msecs_to_jiffies(50));
314 if (ret == 0)
315 pr_err("LCD Controller timed out\n");
316 }
300} 317}
301 318
302static void lcd_blit(int load_mode, struct da8xx_fb_par *par) 319static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
@@ -323,7 +340,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
323 } else { 340 } else {
324 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | 341 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
325 LCD_V2_END_OF_FRAME0_INT_ENA | 342 LCD_V2_END_OF_FRAME0_INT_ENA |
326 LCD_V2_END_OF_FRAME1_INT_ENA; 343 LCD_V2_END_OF_FRAME1_INT_ENA |
344 LCD_FRAME_DONE;
327 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); 345 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
328 } 346 }
329 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; 347 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
@@ -677,7 +695,7 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
677static void lcd_reset(struct da8xx_fb_par *par) 695static void lcd_reset(struct da8xx_fb_par *par)
678{ 696{
679 /* Disable the Raster if previously Enabled */ 697 /* Disable the Raster if previously Enabled */
680 lcd_disable_raster(); 698 lcd_disable_raster(false);
681 699
682 /* DMA has to be disabled */ 700 /* DMA has to be disabled */
683 lcdc_write(0, LCD_DMA_CTRL_REG); 701 lcdc_write(0, LCD_DMA_CTRL_REG);
@@ -773,7 +791,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
773 u32 stat = lcdc_read(LCD_MASKED_STAT_REG); 791 u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
774 792
775 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { 793 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
776 lcd_disable_raster(); 794 lcd_disable_raster(false);
777 lcdc_write(stat, LCD_MASKED_STAT_REG); 795 lcdc_write(stat, LCD_MASKED_STAT_REG);
778 lcd_enable_raster(); 796 lcd_enable_raster();
779 } else if (stat & LCD_PL_LOAD_DONE) { 797 } else if (stat & LCD_PL_LOAD_DONE) {
@@ -783,7 +801,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
783 * interrupt via the following write to the status register. If 801 * interrupt via the following write to the status register. If
784 * this is done after then one gets multiple PL done interrupts. 802 * this is done after then one gets multiple PL done interrupts.
785 */ 803 */
786 lcd_disable_raster(); 804 lcd_disable_raster(false);
787 805
788 lcdc_write(stat, LCD_MASKED_STAT_REG); 806 lcdc_write(stat, LCD_MASKED_STAT_REG);
789 807
@@ -814,6 +832,14 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
814 par->vsync_flag = 1; 832 par->vsync_flag = 1;
815 wake_up_interruptible(&par->vsync_wait); 833 wake_up_interruptible(&par->vsync_wait);
816 } 834 }
835
836 /* Set only when controller is disabled and at the end of
837 * active frame
838 */
839 if (stat & BIT(0)) {
840 frame_done_flag = 1;
841 wake_up_interruptible(&frame_done_wq);
842 }
817 } 843 }
818 844
819 lcdc_write(0, LCD_END_OF_INT_IND_REG); 845 lcdc_write(0, LCD_END_OF_INT_IND_REG);
@@ -828,7 +854,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
828 u32 reg_ras; 854 u32 reg_ras;
829 855
830 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { 856 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
831 lcd_disable_raster(); 857 lcd_disable_raster(false);
832 lcdc_write(stat, LCD_STAT_REG); 858 lcdc_write(stat, LCD_STAT_REG);
833 lcd_enable_raster(); 859 lcd_enable_raster();
834 } else if (stat & LCD_PL_LOAD_DONE) { 860 } else if (stat & LCD_PL_LOAD_DONE) {
@@ -838,7 +864,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
838 * interrupt via the following write to the status register. If 864 * interrupt via the following write to the status register. If
839 * this is done after then one gets multiple PL done interrupts. 865 * this is done after then one gets multiple PL done interrupts.
840 */ 866 */
841 lcd_disable_raster(); 867 lcd_disable_raster(false);
842 868
843 lcdc_write(stat, LCD_STAT_REG); 869 lcdc_write(stat, LCD_STAT_REG);
844 870
@@ -960,7 +986,7 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
960 if (val == CPUFREQ_POSTCHANGE) { 986 if (val == CPUFREQ_POSTCHANGE) {
961 if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) { 987 if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
962 par->lcd_fck_rate = clk_get_rate(par->lcdc_clk); 988 par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
963 lcd_disable_raster(); 989 lcd_disable_raster(true);
964 lcd_calc_clk_divider(par); 990 lcd_calc_clk_divider(par);
965 lcd_enable_raster(); 991 lcd_enable_raster();
966 } 992 }
@@ -997,7 +1023,7 @@ static int __devexit fb_remove(struct platform_device *dev)
997 if (par->panel_power_ctrl) 1023 if (par->panel_power_ctrl)
998 par->panel_power_ctrl(0); 1024 par->panel_power_ctrl(0);
999 1025
1000 lcd_disable_raster(); 1026 lcd_disable_raster(true);
1001 lcdc_write(0, LCD_RASTER_CTRL_REG); 1027 lcdc_write(0, LCD_RASTER_CTRL_REG);
1002 1028
1003 /* disable DMA */ 1029 /* disable DMA */
@@ -1113,7 +1139,7 @@ static int cfb_blank(int blank, struct fb_info *info)
1113 if (par->panel_power_ctrl) 1139 if (par->panel_power_ctrl)
1114 par->panel_power_ctrl(0); 1140 par->panel_power_ctrl(0);
1115 1141
1116 lcd_disable_raster(); 1142 lcd_disable_raster(true);
1117 break; 1143 break;
1118 default: 1144 default:
1119 ret = -EINVAL; 1145 ret = -EINVAL;
@@ -1418,8 +1444,10 @@ static int __devinit fb_probe(struct platform_device *device)
1418 1444
1419 if (lcd_revision == LCD_VERSION_1) 1445 if (lcd_revision == LCD_VERSION_1)
1420 lcdc_irq_handler = lcdc_irq_handler_rev01; 1446 lcdc_irq_handler = lcdc_irq_handler_rev01;
1421 else 1447 else {
1448 init_waitqueue_head(&frame_done_wq);
1422 lcdc_irq_handler = lcdc_irq_handler_rev02; 1449 lcdc_irq_handler = lcdc_irq_handler_rev02;
1450 }
1423 1451
1424 ret = request_irq(par->irq, lcdc_irq_handler, 0, 1452 ret = request_irq(par->irq, lcdc_irq_handler, 0,
1425 DRIVER_NAME, par); 1453 DRIVER_NAME, par);
@@ -1473,7 +1501,7 @@ static int fb_suspend(struct platform_device *dev, pm_message_t state)
1473 par->panel_power_ctrl(0); 1501 par->panel_power_ctrl(0);
1474 1502
1475 fb_set_suspend(info, 1); 1503 fb_set_suspend(info, 1);
1476 lcd_disable_raster(); 1504 lcd_disable_raster(true);
1477 clk_disable(par->lcdc_clk); 1505 clk_disable(par->lcdc_clk);
1478 console_unlock(); 1506 console_unlock();
1479 1507