OMAPDSS: Add LCD3 overlay manager and Clock and IRQ support
authorChandrabhanu Mahapatra <cmahapatra@ti.com>
Fri, 29 Jun 2012 05:13:13 +0000 (10:43 +0530)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Fri, 29 Jun 2012 06:41:24 +0000 (09:41 +0300)
The support for LCD3 manager has been added into the manager module. LCD3 panel
has registers as DISPC_CONTROL3 and DISPC_CONFIG3 just like those in LCD and
LCD2 panels. These registers control the Display Controller (DISPC) module for
LCD3 output. The three LCDs support Display Serial Interface (DSI), Remote Frame
Buffer Interface (RFBI) and Parallel CMOS Output Interface (DPI). These LCDs can
be connected through parallel output interface using DISPC and RFBI or DPI. For
serial interface DSS uses DSI.

The LCD3 panel, just like LCD and LCD2 panels, has a clock switch in DSS_CTRL
register which has been enabled. The clock switch chooses between DSS_CLK and
DPLL_DSI1_C_CLK1 as source for LCD3_CLK. New IRQs as DISPC_IRQ_VSYNC3,
DISPC_IRQ_FRAMEDONE3, DISPC_IRQ_ACBIAS_COUNT_STAT3 and DISPC_IRQ_SYNC_LOST3 have
been added specific to the new manager.

Signed-off-by: Chandrabhanu Mahapatra <cmahapatra@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dispc.h
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss_features.h
drivers/video/omap2/dss/manager.c
drivers/video/omap2/dss/overlay.c
include/video/omapdss.h

index eb1c9be..d19665e 100644 (file)
@@ -191,6 +191,23 @@ static const struct {
                        [DISPC_MGR_FLD_FIFOHANDCHECK]   = { DISPC_CONFIG2,  16, 16 },
                },
        },
+       [OMAP_DSS_CHANNEL_LCD3] = {
+               .name           = "LCD3",
+               .vsync_irq      = DISPC_IRQ_VSYNC3,
+               .framedone_irq  = DISPC_IRQ_FRAMEDONE3,
+               .sync_lost_irq  = DISPC_IRQ_SYNC_LOST3,
+               .reg_desc       = {
+                       [DISPC_MGR_FLD_ENABLE]          = { DISPC_CONTROL3,  0,  0 },
+                       [DISPC_MGR_FLD_STNTFT]          = { DISPC_CONTROL3,  3,  3 },
+                       [DISPC_MGR_FLD_GO]              = { DISPC_CONTROL3,  5,  5 },
+                       [DISPC_MGR_FLD_TFTDATALINES]    = { DISPC_CONTROL3,  9,  8 },
+                       [DISPC_MGR_FLD_STALLMODE]       = { DISPC_CONTROL3, 11, 11 },
+                       [DISPC_MGR_FLD_TCKENABLE]       = { DISPC_CONFIG3,  10, 10 },
+                       [DISPC_MGR_FLD_TCKSELECTION]    = { DISPC_CONFIG3,  11, 11 },
+                       [DISPC_MGR_FLD_CPR]             = { DISPC_CONFIG3,  15, 15 },
+                       [DISPC_MGR_FLD_FIFOHANDCHECK]   = { DISPC_CONFIG3,  16, 16 },
+               },
+       },
 };
 
 static void _omap_dispc_set_irqs(void);
@@ -239,6 +256,10 @@ static void dispc_save_context(void)
                SR(CONTROL2);
                SR(CONFIG2);
        }
+       if (dss_has_feature(FEAT_MGR_LCD3)) {
+               SR(CONTROL3);
+               SR(CONFIG3);
+       }
 
        for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
                SR(DEFAULT_COLOR(i));
@@ -352,6 +373,8 @@ static void dispc_restore_context(void)
                RR(GLOBAL_ALPHA);
        if (dss_has_feature(FEAT_MGR_LCD2))
                RR(CONFIG2);
+       if (dss_has_feature(FEAT_MGR_LCD3))
+               RR(CONFIG3);
 
        for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
                RR(DEFAULT_COLOR(i));
@@ -437,6 +460,8 @@ static void dispc_restore_context(void)
        RR(CONTROL);
        if (dss_has_feature(FEAT_MGR_LCD2))
                RR(CONTROL2);
+       if (dss_has_feature(FEAT_MGR_LCD3))
+               RR(CONTROL3);
        /* clear spurious SYNC_LOST_DIGIT interrupts */
        dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
 
@@ -476,7 +501,8 @@ void dispc_runtime_put(void)
 static inline bool dispc_mgr_is_lcd(enum omap_channel channel)
 {
        if (channel == OMAP_DSS_CHANNEL_LCD ||
-                       channel == OMAP_DSS_CHANNEL_LCD2)
+                       channel == OMAP_DSS_CHANNEL_LCD2 ||
+                       channel == OMAP_DSS_CHANNEL_LCD3)
                return true;
        else
                return false;
@@ -867,6 +893,15 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
                        chan = 0;
                        chan2 = 1;
                        break;
+               case OMAP_DSS_CHANNEL_LCD3:
+                       if (dss_has_feature(FEAT_MGR_LCD3)) {
+                               chan = 0;
+                               chan2 = 2;
+                       } else {
+                               BUG();
+                               return;
+                       }
+                       break;
                default:
                        BUG();
                        return;
@@ -902,7 +937,14 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
 
        val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
 
-       if (dss_has_feature(FEAT_MGR_LCD2)) {
+       if (dss_has_feature(FEAT_MGR_LCD3)) {
+               if (FLD_GET(val, 31, 30) == 0)
+                       channel = FLD_GET(val, shift, shift);
+               else if (FLD_GET(val, 31, 30) == 1)
+                       channel = OMAP_DSS_CHANNEL_LCD2;
+               else
+                       channel = OMAP_DSS_CHANNEL_LCD3;
+       } else if (dss_has_feature(FEAT_MGR_LCD2)) {
                if (FLD_GET(val, 31, 30) == 0)
                        channel = FLD_GET(val, shift, shift);
                else
@@ -3587,6 +3629,8 @@ static void _omap_dispc_initialize_irq(void)
        dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
        if (dss_has_feature(FEAT_MGR_LCD2))
                dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+       if (dss_has_feature(FEAT_MGR_LCD3))
+               dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
        if (dss_feat_get_num_ovls() > 3)
                dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
 
index 420c980..92d8a9b 100644 (file)
@@ -36,6 +36,8 @@
 #define DISPC_CONTROL2                 0x0238
 #define DISPC_CONFIG2                  0x0620
 #define DISPC_DIVISOR                  0x0804
+#define DISPC_CONTROL3                  0x0848
+#define DISPC_CONFIG3                   0x084C
 
 /* DISPC overlay registers */
 #define DISPC_OVL_BA0(n)               (DISPC_OVL_BASE(n) + \
index d2b5719..fc0c3ce 100644 (file)
@@ -388,7 +388,8 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
                dsi_wait_pll_hsdiv_dispc_active(dsidev);
                break;
        case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-               BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2);
+               BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
+                      channel != OMAP_DSS_CHANNEL_LCD3);
                b = 1;
                dsidev = dsi_get_dsidev_from_id(1);
                dsi_wait_pll_hsdiv_dispc_active(dsidev);
@@ -398,10 +399,12 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
                return;
        }
 
-       pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
+       pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
+            (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
        REG_FLD_MOD(DSS_CONTROL, b, pos, pos);  /* LCDx_CLK_SWITCH */
 
-       ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
+       ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
+           (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
        dss.lcd_clk_source[ix] = clk_src;
 }
 
@@ -418,7 +421,8 @@ enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
 enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
 {
        if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
-               int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
+               int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
+                       (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
                return dss.lcd_clk_source[ix];
        } else {
                /* LCD_CLK source is the same as DISPC_FCLK source for
index bdf469f..996ffcb 100644 (file)
@@ -24,9 +24,9 @@
 #include "ti_hdmi.h"
 #endif
 
-#define MAX_DSS_MANAGERS       3
+#define MAX_DSS_MANAGERS       4
 #define MAX_DSS_OVERLAYS       4
-#define MAX_DSS_LCD_MANAGERS   2
+#define MAX_DSS_LCD_MANAGERS   3
 #define MAX_NUM_DSI            2
 
 /* DSS has feature id */
@@ -36,6 +36,7 @@ enum dss_feat_id {
        FEAT_PCKFREEENABLE,
        FEAT_FUNCGATED,
        FEAT_MGR_LCD2,
+       FEAT_MGR_LCD3,
        FEAT_LINEBUFFERSPLIT,
        FEAT_ROWREPEATENABLE,
        FEAT_RESIZECONF,
index bb602a2..a51eb06 100644 (file)
@@ -541,6 +541,10 @@ int dss_init_overlay_managers(struct platform_device *pdev)
                        mgr->name = "lcd2";
                        mgr->id = OMAP_DSS_CHANNEL_LCD2;
                        break;
+               case 3:
+                       mgr->name = "lcd3";
+                       mgr->id = OMAP_DSS_CHANNEL_LCD3;
+                       break;
                }
 
                mgr->set_device = &dss_mgr_set_device;
index c492bb0..ec69325 100644 (file)
@@ -528,14 +528,24 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
        struct omap_overlay_manager *lcd_mgr;
        struct omap_overlay_manager *tv_mgr;
        struct omap_overlay_manager *lcd2_mgr = NULL;
+       struct omap_overlay_manager *lcd3_mgr = NULL;
        struct omap_overlay_manager *mgr = NULL;
 
        lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD);
        tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT);
+       if (dss_has_feature(FEAT_MGR_LCD3))
+               lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3);
        if (dss_has_feature(FEAT_MGR_LCD2))
                lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2);
 
-       if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
+       if (dssdev->channel == OMAP_DSS_CHANNEL_LCD3) {
+               if (!lcd3_mgr->device || force) {
+                       if (lcd3_mgr->device)
+                               lcd3_mgr->unset_device(lcd3_mgr);
+                       lcd3_mgr->set_device(lcd3_mgr, dssdev);
+                       mgr = lcd3_mgr;
+               }
+       } else if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
                if (!lcd2_mgr->device || force) {
                        if (lcd2_mgr->device)
                                lcd2_mgr->unset_device(lcd2_mgr);
index 23887b3..117de0e 100644 (file)
 #define DISPC_IRQ_FRAMEDONEWB          (1 << 23)
 #define DISPC_IRQ_FRAMEDONETV          (1 << 24)
 #define DISPC_IRQ_WBBUFFEROVERFLOW     (1 << 25)
+#define DISPC_IRQ_FRAMEDONE3           (1 << 26)
+#define DISPC_IRQ_VSYNC3               (1 << 27)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT3   (1 << 28)
+#define DISPC_IRQ_SYNC_LOST3           (1 << 29)
 
 struct omap_dss_device;
 struct omap_overlay_manager;