aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/da8xx-fb.c
diff options
context:
space:
mode:
authorManjunathappa, Prakash <prakash.pm@ti.com>2011-07-05 06:21:20 -0400
committerPaul Mundt <lethal@linux-sh.org>2011-07-13 03:58:53 -0400
commitc6daf05b6d7afca4c9e04a7361e284ef9e1d8dad (patch)
treee4ca4f2b7763791c311f5efd13fd6529f4f050d5 /drivers/video/da8xx-fb.c
parenta4b8f97a8fdeb94492738c36fddbd2cf822ed138 (diff)
video: da8xx-fb: Interrupt configuration of revised LCDC IP
An upcoming SoC of TI comes with an LCD controller which is an updated version of that found on TI's DA850 SoC. The da8xx-fb driver can support this LCD with some enhancements. This patch adds support for updated interrupt configuration on the new SoC. 1) Registers for setting and clearing interrupts are different. 2) Raw and masked status registers are different. The updates have been tested on an emulation platform for new features and the patch has been tested on DA850 platform to make sure nothing existing breaks. Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/video/da8xx-fb.c')
-rw-r--r--drivers/video/da8xx-fb.c151
1 files changed, 142 insertions, 9 deletions
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 8d4e4ebd9977..217c05f74541 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -35,6 +35,9 @@
35 35
36#define DRIVER_NAME "da8xx_lcdc" 36#define DRIVER_NAME "da8xx_lcdc"
37 37
38#define LCD_VERSION_1 1
39#define LCD_VERSION_2 2
40
38/* LCD Status Register */ 41/* LCD Status Register */
39#define LCD_END_OF_FRAME1 BIT(9) 42#define LCD_END_OF_FRAME1 BIT(9)
40#define LCD_END_OF_FRAME0 BIT(8) 43#define LCD_END_OF_FRAME0 BIT(8)
@@ -49,7 +52,9 @@
49#define LCD_DMA_BURST_4 0x2 52#define LCD_DMA_BURST_4 0x2
50#define LCD_DMA_BURST_8 0x3 53#define LCD_DMA_BURST_8 0x3
51#define LCD_DMA_BURST_16 0x4 54#define LCD_DMA_BURST_16 0x4
52#define LCD_END_OF_FRAME_INT_ENA BIT(2) 55#define LCD_V1_END_OF_FRAME_INT_ENA BIT(2)
56#define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8)
57#define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9)
53#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) 58#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0)
54 59
55/* LCD Control Register */ 60/* LCD Control Register */
@@ -65,12 +70,18 @@
65#define LCD_MONO_8BIT_MODE BIT(9) 70#define LCD_MONO_8BIT_MODE BIT(9)
66#define LCD_RASTER_ORDER BIT(8) 71#define LCD_RASTER_ORDER BIT(8)
67#define LCD_TFT_MODE BIT(7) 72#define LCD_TFT_MODE BIT(7)
68#define LCD_UNDERFLOW_INT_ENA BIT(6) 73#define LCD_V1_UNDERFLOW_INT_ENA BIT(6)
69#define LCD_PL_ENABLE BIT(4) 74#define LCD_V2_UNDERFLOW_INT_ENA BIT(5)
75#define LCD_V1_PL_INT_ENA BIT(4)
76#define LCD_V2_PL_INT_ENA BIT(6)
70#define LCD_MONOCHROME_MODE BIT(1) 77#define LCD_MONOCHROME_MODE BIT(1)
71#define LCD_RASTER_ENABLE BIT(0) 78#define LCD_RASTER_ENABLE BIT(0)
72#define LCD_TFT_ALT_ENABLE BIT(23) 79#define LCD_TFT_ALT_ENABLE BIT(23)
73#define LCD_STN_565_ENABLE BIT(24) 80#define LCD_STN_565_ENABLE BIT(24)
81#define LCD_V2_DMA_CLK_EN BIT(2)
82#define LCD_V2_LIDD_CLK_EN BIT(1)
83#define LCD_V2_CORE_CLK_EN BIT(0)
84#define LCD_V2_LPP_B10 26
74 85
75/* LCD Raster Timing 2 Register */ 86/* LCD Raster Timing 2 Register */
76#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) 87#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
@@ -82,6 +93,7 @@
82#define LCD_INVERT_FRAME_CLOCK BIT(20) 93#define LCD_INVERT_FRAME_CLOCK BIT(20)
83 94
84/* LCD Block */ 95/* LCD Block */
96#define LCD_PID_REG 0x0
85#define LCD_CTRL_REG 0x4 97#define LCD_CTRL_REG 0x4
86#define LCD_STAT_REG 0x8 98#define LCD_STAT_REG 0x8
87#define LCD_RASTER_CTRL_REG 0x28 99#define LCD_RASTER_CTRL_REG 0x28
@@ -94,6 +106,17 @@
94#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C 106#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C
95#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 107#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50
96 108
109/* Interrupt Registers available only in Version 2 */
110#define LCD_RAW_STAT_REG 0x58
111#define LCD_MASKED_STAT_REG 0x5c
112#define LCD_INT_ENABLE_SET_REG 0x60
113#define LCD_INT_ENABLE_CLR_REG 0x64
114#define LCD_END_OF_INT_IND_REG 0x68
115
116/* Clock registers available only on Version 2 */
117#define LCD_CLK_ENABLE_REG 0x6c
118#define LCD_CLK_RESET_REG 0x70
119
97#define LCD_NUM_BUFFERS 2 120#define LCD_NUM_BUFFERS 2
98 121
99#define WSI_TIMEOUT 50 122#define WSI_TIMEOUT 50
@@ -105,6 +128,8 @@
105 128
106static resource_size_t da8xx_fb_reg_base; 129static resource_size_t da8xx_fb_reg_base;
107static struct resource *lcdc_regs; 130static struct resource *lcdc_regs;
131static unsigned int lcd_revision;
132static irq_handler_t lcdc_irq_handler;
108 133
109static inline unsigned int lcdc_read(unsigned int addr) 134static inline unsigned int lcdc_read(unsigned int addr)
110{ 135{
@@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
240 u32 end; 265 u32 end;
241 u32 reg_ras; 266 u32 reg_ras;
242 u32 reg_dma; 267 u32 reg_dma;
268 u32 reg_int;
243 269
244 /* init reg to clear PLM (loading mode) fields */ 270 /* init reg to clear PLM (loading mode) fields */
245 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); 271 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
@@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
252 end = par->dma_end; 278 end = par->dma_end;
253 279
254 reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); 280 reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
255 reg_dma |= LCD_END_OF_FRAME_INT_ENA; 281 if (lcd_revision == LCD_VERSION_1) {
282 reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
283 } else {
284 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
285 LCD_V2_END_OF_FRAME0_INT_ENA |
286 LCD_V2_END_OF_FRAME1_INT_ENA;
287 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
288 }
256 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; 289 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
257 290
258 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); 291 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
@@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
264 end = start + par->palette_sz - 1; 297 end = start + par->palette_sz - 1;
265 298
266 reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); 299 reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
267 reg_ras |= LCD_PL_ENABLE; 300
301 if (lcd_revision == LCD_VERSION_1) {
302 reg_ras |= LCD_V1_PL_INT_ENA;
303 } else {
304 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
305 LCD_V2_PL_INT_ENA;
306 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
307 }
268 308
269 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); 309 lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
270 lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); 310 lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
@@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
348static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) 388static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
349{ 389{
350 u32 reg; 390 u32 reg;
391 u32 reg_int;
351 392
352 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | 393 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
353 LCD_MONO_8BIT_MODE | 394 LCD_MONO_8BIT_MODE |
@@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
375 } 416 }
376 417
377 /* enable additional interrupts here */ 418 /* enable additional interrupts here */
378 reg |= LCD_UNDERFLOW_INT_ENA; 419 if (lcd_revision == LCD_VERSION_1) {
420 reg |= LCD_V1_UNDERFLOW_INT_ENA;
421 } else {
422 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
423 LCD_V2_UNDERFLOW_INT_ENA;
424 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
425 }
379 426
380 lcdc_write(reg, LCD_RASTER_CTRL_REG); 427 lcdc_write(reg, LCD_RASTER_CTRL_REG);
381 428
@@ -511,6 +558,9 @@ static void lcd_reset(struct da8xx_fb_par *par)
511 /* DMA has to be disabled */ 558 /* DMA has to be disabled */
512 lcdc_write(0, LCD_DMA_CTRL_REG); 559 lcdc_write(0, LCD_DMA_CTRL_REG);
513 lcdc_write(0, LCD_RASTER_CTRL_REG); 560 lcdc_write(0, LCD_RASTER_CTRL_REG);
561
562 if (lcd_revision == LCD_VERSION_2)
563 lcdc_write(0, LCD_INT_ENABLE_SET_REG);
514} 564}
515 565
516static void lcd_calc_clk_divider(struct da8xx_fb_par *par) 566static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
@@ -523,6 +573,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
523 /* Configure the LCD clock divisor. */ 573 /* Configure the LCD clock divisor. */
524 lcdc_write(LCD_CLK_DIVISOR(div) | 574 lcdc_write(LCD_CLK_DIVISOR(div) |
525 (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); 575 (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
576
577 if (lcd_revision == LCD_VERSION_2)
578 lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
579 LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
580
526} 581}
527 582
528static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, 583static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
@@ -583,7 +638,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
583 return 0; 638 return 0;
584} 639}
585 640
586static irqreturn_t lcdc_irq_handler(int irq, void *arg) 641/* IRQ handler for version 2 of LCDC */
642static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
643{
644 struct da8xx_fb_par *par = arg;
645 u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
646 u32 reg_int;
647
648 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
649 lcd_disable_raster();
650 lcdc_write(stat, LCD_MASKED_STAT_REG);
651 lcd_enable_raster();
652 } else if (stat & LCD_PL_LOAD_DONE) {
653 /*
654 * Must disable raster before changing state of any control bit.
655 * And also must be disabled before clearing the PL loading
656 * interrupt via the following write to the status register. If
657 * this is done after then one gets multiple PL done interrupts.
658 */
659 lcd_disable_raster();
660
661 lcdc_write(stat, LCD_MASKED_STAT_REG);
662
663 /* Disable PL completion inerrupt */
664 reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) |
665 (LCD_V2_PL_INT_ENA);
666 lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG);
667
668 /* Setup and start data loading mode */
669 lcd_blit(LOAD_DATA, par);
670 } else {
671 lcdc_write(stat, LCD_MASKED_STAT_REG);
672
673 if (stat & LCD_END_OF_FRAME0) {
674 lcdc_write(par->dma_start,
675 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
676 lcdc_write(par->dma_end,
677 LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
678 par->vsync_flag = 1;
679 wake_up_interruptible(&par->vsync_wait);
680 }
681
682 if (stat & LCD_END_OF_FRAME1) {
683 lcdc_write(par->dma_start,
684 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
685 lcdc_write(par->dma_end,
686 LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
687 par->vsync_flag = 1;
688 wake_up_interruptible(&par->vsync_wait);
689 }
690 }
691
692 lcdc_write(0, LCD_END_OF_INT_IND_REG);
693 return IRQ_HANDLED;
694}
695
696/* IRQ handler for version 1 LCDC */
697static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
587{ 698{
588 struct da8xx_fb_par *par = arg; 699 struct da8xx_fb_par *par = arg;
589 u32 stat = lcdc_read(LCD_STAT_REG); 700 u32 stat = lcdc_read(LCD_STAT_REG);
@@ -606,7 +717,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg)
606 717
607 /* Disable PL completion inerrupt */ 718 /* Disable PL completion inerrupt */
608 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); 719 reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
609 reg_ras &= ~LCD_PL_ENABLE; 720 reg_ras &= ~LCD_V1_PL_INT_ENA;
610 lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); 721 lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
611 722
612 /* Setup and start data loading mode */ 723 /* Setup and start data loading mode */
@@ -945,6 +1056,22 @@ static int __devinit fb_probe(struct platform_device *device)
945 if (ret) 1056 if (ret)
946 goto err_clk_put; 1057 goto err_clk_put;
947 1058
1059 /* Determine LCD IP Version */
1060 switch (lcdc_read(LCD_PID_REG)) {
1061 case 0x4C100102:
1062 lcd_revision = LCD_VERSION_1;
1063 break;
1064 case 0x4F200800:
1065 lcd_revision = LCD_VERSION_2;
1066 break;
1067 default:
1068 dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
1069 "defaulting to LCD revision 1\n",
1070 lcdc_read(LCD_PID_REG));
1071 lcd_revision = LCD_VERSION_1;
1072 break;
1073 }
1074
948 for (i = 0, lcdc_info = known_lcd_panels; 1075 for (i = 0, lcdc_info = known_lcd_panels;
949 i < ARRAY_SIZE(known_lcd_panels); 1076 i < ARRAY_SIZE(known_lcd_panels);
950 i++, lcdc_info++) { 1077 i++, lcdc_info++) {
@@ -1085,7 +1212,13 @@ static int __devinit fb_probe(struct platform_device *device)
1085 } 1212 }
1086#endif 1213#endif
1087 1214
1088 ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); 1215 if (lcd_revision == LCD_VERSION_1)
1216 lcdc_irq_handler = lcdc_irq_handler_rev01;
1217 else
1218 lcdc_irq_handler = lcdc_irq_handler_rev02;
1219
1220 ret = request_irq(par->irq, lcdc_irq_handler, 0,
1221 DRIVER_NAME, par);
1089 if (ret) 1222 if (ret)
1090 goto irq_freq; 1223 goto irq_freq;
1091 return 0; 1224 return 0;