diff options
Diffstat (limited to 'recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch')
-rw-r--r-- | recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch b/recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch new file mode 100644 index 0000000000..c01c2520ec --- /dev/null +++ b/recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch @@ -0,0 +1,406 @@ +From 29cb3408c094bacd42d8bb17cbafb6f1c57f6cc8 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Tue, 30 Jun 2009 11:47:38 +0300 +Subject: [PATCH 132/146] DSS2: DSI: use only 1 VC. Fixes to TE. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/dss/dsi.c | 197 +++++++++++++++++++++++++--------------- + 1 files changed, 123 insertions(+), 74 deletions(-) + +diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c +index 03cf2d6..becaf64 100644 +--- a/drivers/video/omap2/dss/dsi.c ++++ b/drivers/video/omap2/dss/dsi.c +@@ -192,6 +192,11 @@ enum fifo_size { + DSI_FIFO_SIZE_128 = 4, + }; + ++enum dsi_vc_mode { ++ DSI_VC_MODE_L4 = 0, ++ DSI_VC_MODE_VP, ++}; ++ + struct dsi_update_region { + bool dirty; + u16 x, y, w, h; +@@ -210,6 +215,7 @@ static struct + struct regulator *vdds_dsi_reg; + + struct { ++ enum dsi_vc_mode mode; + struct omap_dss_device *dssdev; + enum fifo_size fifo_size; + int dest_per; /* destination peripheral 0-3 */ +@@ -1629,14 +1635,36 @@ static void dsi_vc_print_status(int channel) + DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff); + } + +-static void dsi_vc_config(int channel) ++static int dsi_vc_enable(int channel, bool enable) ++{ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBG("dsi_vc_enable channel %d, enable %d\n", ++ channel, enable); ++ ++ enable = enable ? 1 : 0; ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0); ++ ++ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) { ++ DSSERR("Failed to set dsi_vc_enable to %d\n", enable); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void dsi_vc_initial_config(int channel) + { + u32 r; + +- DSSDBG("dsi_vc_config %d\n", channel); ++ DSSDBGF("%d", channel); + + r = dsi_read_reg(DSI_VC_CTRL(channel)); + ++ if (FLD_GET(r, 15, 15)) /* VC_BUSY */ ++ DSSERR("VC(%d) busy when trying to configure it!\n", ++ channel); ++ + r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */ + r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */ + r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */ +@@ -1649,47 +1677,51 @@ static void dsi_vc_config(int channel) + r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ + + dsi_write_reg(DSI_VC_CTRL(channel), r); ++ ++ dsi.vc[channel].mode = DSI_VC_MODE_L4; + } + +-static void dsi_vc_config_vp(int channel) ++static void dsi_vc_config_l4(int channel) + { +- u32 r; ++ if (dsi.vc[channel].mode == DSI_VC_MODE_L4) ++ return; + +- DSSDBG("dsi_vc_config_vp\n"); ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBGF("%d", channel); + +- r = dsi_read_reg(DSI_VC_CTRL(channel)); ++ dsi_vc_enable(channel, 0); + +- r = FLD_MOD(r, 1, 1, 1); /* SOURCE, 1 = video port */ +- r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */ +- r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */ +- r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */ +- r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ +- r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ +- r = FLD_MOD(r, 1, 9, 9); /* MODE_SPEED, high speed on/off */ ++ if(REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ ++ DSSERR("vc(%d) busy when trying to config for L4\n", channel); + +- r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ +- r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ + +- dsi_write_reg(DSI_VC_CTRL(channel), r); +-} ++ dsi_vc_enable(channel, 1); + ++ dsi.vc[channel].mode = DSI_VC_MODE_L4; ++} + +-static int dsi_vc_enable(int channel, bool enable) ++static void dsi_vc_config_vp(int channel) + { +- DSSDBG("dsi_vc_enable channel %d, enable %d\n", channel, enable); ++ if (dsi.vc[channel].mode == DSI_VC_MODE_VP) ++ return; + +- enable = enable ? 1 : 0; ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBGF("%d", channel); + +- REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0); ++ dsi_vc_enable(channel, 0); + +- if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) { +- DSSERR("Failed to set dsi_vc_enable to %d\n", enable); +- return -EIO; +- } ++ if(REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ ++ DSSERR("vc(%d) busy when trying to config for VP\n", channel); + +- return 0; ++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ ++ ++ dsi_vc_enable(channel, 1); ++ ++ dsi.vc[channel].mode = DSI_VC_MODE_VP; + } + ++ + static void dsi_vc_enable_hs(int channel, bool enable) + { + DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); +@@ -1788,7 +1820,9 @@ static int dsi_vc_send_bta(int channel) + { + unsigned long tmo; + +- DSSDBG("dsi_vc_send_bta %d\n", channel); ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO && ++ (dsi.debug_write || dsi.debug_read)) ++ DSSDBG("dsi_vc_send_bta %d\n", channel); + + WARN_ON(!mutex_is_locked(&dsi.bus_lock)); + +@@ -1976,6 +2010,12 @@ int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) + + BUG_ON(len == 0); + ++ if (REG_GET(DSI_VC_CTRL(channel), 1, 1) != 0) { ++ DSSERR("vc(%d) not in L4 mode when trying to write\n", ++ channel); ++ return -EIO; ++ } ++ + if (len == 1) { + r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0, + data[0], 0); +@@ -2000,9 +2040,6 @@ int dsi_vc_dcs_write(int channel, u8 *data, int len) + if (r) + return r; + +- /* Some devices need time to process the msg in low power mode. +- This also makes the write synchronous, and checks that +- the peripheral is still alive */ + r = dsi_vc_send_bta_sync(channel); + + return r; +@@ -2016,7 +2053,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) + int r; + + if (dsi.debug_read) +- DSSDBG("dsi_vc_dcs_read\n"); ++ DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd); + + r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); + if (r) +@@ -2291,10 +2328,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) + + dsi_write_reg(DSI_CTRL, r); + +- /* we configure vc0 for L4 communication, and +- * vc1 for dispc */ +- dsi_vc_config(0); +- dsi_vc_config_vp(1); ++ dsi_vc_initial_config(0); + + /* set all vc targets to peripheral 0 */ + dsi.vc[0].dest_per = 0; +@@ -2535,10 +2569,11 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, + int packet_len; + u32 l; + bool use_te_trigger; ++ const int channel = 0; + + use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; + +- if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) + DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", + x, y, w, h); + +@@ -2559,22 +2594,27 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, + dsi_vc_print_status(1); + + l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ +- dsi_write_reg(DSI_VC_TE(1), l); ++ dsi_write_reg(DSI_VC_TE(channel), l); + +- dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, packet_len, 0); ++ dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0); + + if (use_te_trigger) + l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ + else + l = FLD_MOD(l, 1, 31, 31); /* TE_START */ +- dsi_write_reg(DSI_VC_TE(1), l); ++ dsi_write_reg(DSI_VC_TE(channel), l); + + dispc_disable_sidle(); + + dss_start_update(dssdev); + +- if (use_te_trigger) +- dsi_vc_send_bta(1); ++ if (use_te_trigger) { ++ /* disable LP_RX_TO, so that we can receive TE. Time to wait ++ * for TE is longer than the timer allows */ ++ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ ++ ++ dsi_vc_send_bta(channel); ++ } + } + + static void dsi_framedone_irq_callback(void *data, u32 mask) +@@ -2637,19 +2677,12 @@ static void dsi_start_auto_update(struct omap_dss_device *dssdev) + + static int dsi_set_te(struct omap_dss_device *dssdev, bool enable) + { +- dssdev->driver->enable_te(dssdev, enable); +- +- if (!dsi.use_ext_te) { +- if (enable) { +- /* disable LP_RX_TO, so that we can receive TE. Time +- * to wait for TE is longer than the timer allows */ +- REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ +- } else { +- REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ +- } +- } +- +- return 0; ++ int r; ++ r = dssdev->driver->enable_te(dssdev, enable); ++ /* XXX for some reason, DSI TE breaks if we don't wait here. ++ * Panel bug? Needs more studying */ ++ msleep(100); ++ return r; + } + + static void dsi_handle_framedone(void) +@@ -2657,8 +2690,14 @@ static void dsi_handle_framedone(void) + u32 l; + unsigned long tmo; + int i = 0; ++ int r; ++ const int channel = 0; ++ u32 te_size; ++ bool use_te_trigger; ++ ++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; + +- l = REG_GET(DSI_VC_TE(1), 23, 0); /* TE_SIZE */ ++ l = REG_GET(DSI_VC_TE(channel), 23, 0); /* TE_SIZE */ + + /* We get FRAMEDONE when DISPC has finished sending pixels and turns + * itself off. However, DSI still has the pixels in its buffers, and is +@@ -2667,24 +2706,26 @@ static void dsi_handle_framedone(void) + * DSI buffers, if any, so we'll just busyloop */ + if (l > 0) { + tmo = jiffies + msecs_to_jiffies(50); +- while (REG_GET(DSI_VC_TE(1), 23, 0) > 0) { /* TE_SIZE */ ++ te_size = REG_GET(DSI_VC_TE(channel), 23, 0); /* TE_SIZE */ ++ while (te_size > 0) { + i++; + if (time_after(jiffies, tmo)) { + DSSERR("timeout waiting TE_SIZE to zero: %u\n", +- REG_GET(DSI_VC_TE(1), 23, 0)); ++ te_size); + break; + } + schedule(); ++ te_size = REG_GET(DSI_VC_TE(channel), 23, 0); /* TE_SIZE */ + } + } + +- if (REG_GET(DSI_VC_TE(1), 30, 30)) ++ if (REG_GET(DSI_VC_TE(channel), 30, 30)) + DSSERR("TE_EN not zero\n"); + +- if (REG_GET(DSI_VC_TE(1), 31, 31)) ++ if (REG_GET(DSI_VC_TE(channel), 31, 31)) + DSSERR("TE_START not zero\n"); + +- if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) + DSSDBG("FRAMEDONE\n"); + + #if 0 +@@ -2698,6 +2739,16 @@ static void dsi_handle_framedone(void) + #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC + dispc_fake_vsync_irq(); + #endif ++ if (use_te_trigger) { ++ /* enable LP_RX_TO again after the TE */ ++ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ ++ ++ /* send BTA after the frame, because we need to BTA after ++ * every trasmission for the TE to work */ ++ r = dsi_vc_send_bta_sync(channel); ++ if (r) ++ DSSERR("BTA after framedone failed\n"); ++ } + } + + static int dsi_update_thread(void *data) +@@ -2768,25 +2819,24 @@ static int dsi_update_thread(void *data) + dispc_set_lcd_size(w, h); + } + +- /* XXX We don't need to send the update area coords to the +- * panel every time. But for some reason TE doesn't work if we +- * don't send at least a BTA here... */ +-#if 0 + if (dsi.active_update_region.dirty) { + dsi.active_update_region.dirty = false; ++ /* XXX TODO we don't need to send the coords, if they ++ * are the same that are already programmed to the ++ * panel. That should speed up manual update a bit */ + device->driver->setup_update(device, x, y, w, h); + } +-#else +- device->driver->setup_update(device, x, y, w, h); +-#endif +- +- if (dsi.te_enabled && dsi.use_ext_te && +- device->driver->wait_for_te) +- device->driver->wait_for_te(device); + + dsi_perf_mark_start(); + + if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ dsi_vc_config_vp(0); ++ ++ if (dsi.te_enabled && dsi.use_ext_te) ++ device->driver->wait_for_te(device); ++ ++ dsi.framedone_received = false; ++ + dsi_update_screen_dispc(device, x, y, w, h); + + /* wait for framedone */ +@@ -2795,8 +2845,6 @@ static int dsi_update_thread(void *data) + dsi.framedone_received == true, + timeout); + +- dsi.framedone_received = false; +- + if (timeout == 0) { + DSSERR("framedone timeout\n"); + DSSERR("failed update %d,%d %dx%d\n", +@@ -2808,6 +2856,8 @@ static int dsi_update_thread(void *data) + dsi_handle_framedone(); + dsi_perf_show("DISPC"); + } ++ ++ dsi_vc_config_l4(0); + } else { + dsi_update_screen_l4(device, x, y, w, h); + dsi_perf_show("L4"); +@@ -2913,7 +2963,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) + + /* enable interface */ + dsi_vc_enable(0, 1); +- dsi_vc_enable(1, 1); + dsi_if_enable(1); + dsi_force_tx_stop_mode_io(); + +-- +1.6.2.4 + |