aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-omap-pm/dss2/0132-DSS2-DSI-use-only-1-VC.-Fixes-to-TE.patch
diff options
context:
space:
mode:
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.patch406
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
+