aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArchit Taneja <archit@ti.com>2011-03-23 05:59:34 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-05-11 07:10:55 -0400
commitcf398fb3e6aed8e7a9b3bcf77f6de2d34ccd2078 (patch)
tree7e5fe4d850f3021a6117cdcde6b5f583dedc0d0a
parent9613c02b5feba3ea03ab34f1422dd122c6e54f57 (diff)
OMAP: DSS2: DSI: Introduce sync_vc functions
The DSI protocol engine has no interrupt for signalling the end of a Frame transfer. The present approach is to send a BTA after DISPC generates a FRAMEDONE interrupt, and unlock the dsi bus only when the BTA Ack is received. The assumption made with this approach was that OMAP will send a BTA only after the long packet corresponding to the last line is sent. However, it is possible that on the DISPC FRAMEDONE interrupt there are 2 (or more) lines of pixel data in the DSI line buffer. Hence, the BTA Ack could be received for the long packet corresponding to the second last line (or the third last and so on..). Therefore, the current method doesn't ensure that the complete frame data is sent before we start a new transfer. A similar explanation holds valid if we send a BTA in between multiple short/long command packets from the slave port. Introduce dsi_sync_vc functions, based on Tomi Valkeinen's idea, which ensure that the DSI Virtual Channel in use(update_channel) completes its previous work before proceeding to the next Frame/Command. For a frame update, the DSI driver now sends a callback to the Panel Driver on the FRAMEDONE interrupt itself. The callback in the panel driver then unlocks the bus. dsi_sync_vc() functions are placed in dsi_vc_config_l4() and dsi_vc_config_vp() to ensure that the previous task of the Virtual Channel is completed. Signed-off-by: Archit Taneja <archit@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/video/omap2/dss/dsi.c180
1 files changed, 117 insertions, 63 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 5ce99667e7ee..39d942607362 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -2037,6 +2037,114 @@ static int dsi_force_tx_stop_mode_io(void)
2037 return 0; 2037 return 0;
2038} 2038}
2039 2039
2040static bool dsi_vc_is_enabled(int channel)
2041{
2042 return REG_GET(DSI_VC_CTRL(channel), 0, 0);
2043}
2044
2045static void dsi_packet_sent_handler_vp(void *data, u32 mask)
2046{
2047 const int channel = dsi.update_channel;
2048 u8 bit = dsi.te_enabled ? 30 : 31;
2049
2050 if (REG_GET(DSI_VC_TE(channel), bit, bit) == 0)
2051 complete((struct completion *)data);
2052}
2053
2054static int dsi_sync_vc_vp(int channel)
2055{
2056 int r = 0;
2057 u8 bit;
2058
2059 DECLARE_COMPLETION_ONSTACK(completion);
2060
2061 bit = dsi.te_enabled ? 30 : 31;
2062
2063 r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_vp,
2064 &completion, DSI_VC_IRQ_PACKET_SENT);
2065 if (r)
2066 goto err0;
2067
2068 /* Wait for completion only if TE_EN/TE_START is still set */
2069 if (REG_GET(DSI_VC_TE(channel), bit, bit)) {
2070 if (wait_for_completion_timeout(&completion,
2071 msecs_to_jiffies(10)) == 0) {
2072 DSSERR("Failed to complete previous frame transfer\n");
2073 r = -EIO;
2074 goto err1;
2075 }
2076 }
2077
2078 dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp,
2079 &completion, DSI_VC_IRQ_PACKET_SENT);
2080
2081 return 0;
2082err1:
2083 dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp, &completion,
2084 DSI_VC_IRQ_PACKET_SENT);
2085err0:
2086 return r;
2087}
2088
2089static void dsi_packet_sent_handler_l4(void *data, u32 mask)
2090{
2091 const int channel = dsi.update_channel;
2092
2093 if (REG_GET(DSI_VC_CTRL(channel), 5, 5) == 0)
2094 complete((struct completion *)data);
2095}
2096
2097static int dsi_sync_vc_l4(int channel)
2098{
2099 int r = 0;
2100
2101 DECLARE_COMPLETION_ONSTACK(completion);
2102
2103 r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_l4,
2104 &completion, DSI_VC_IRQ_PACKET_SENT);
2105 if (r)
2106 goto err0;
2107
2108 /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */
2109 if (REG_GET(DSI_VC_CTRL(channel), 5, 5)) {
2110 if (wait_for_completion_timeout(&completion,
2111 msecs_to_jiffies(10)) == 0) {
2112 DSSERR("Failed to complete previous l4 transfer\n");
2113 r = -EIO;
2114 goto err1;
2115 }
2116 }
2117
2118 dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4,
2119 &completion, DSI_VC_IRQ_PACKET_SENT);
2120
2121 return 0;
2122err1:
2123 dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4,
2124 &completion, DSI_VC_IRQ_PACKET_SENT);
2125err0:
2126 return r;
2127}
2128
2129static int dsi_sync_vc(int channel)
2130{
2131 WARN_ON(!dsi_bus_is_locked());
2132
2133 WARN_ON(in_interrupt());
2134
2135 if (!dsi_vc_is_enabled(channel))
2136 return 0;
2137
2138 switch (dsi.vc[channel].mode) {
2139 case DSI_VC_MODE_VP:
2140 return dsi_sync_vc_vp(channel);
2141 case DSI_VC_MODE_L4:
2142 return dsi_sync_vc_l4(channel);
2143 default:
2144 BUG();
2145 }
2146}
2147
2040static int dsi_vc_enable(int channel, bool enable) 2148static int dsi_vc_enable(int channel, bool enable)
2041{ 2149{
2042 DSSDBG("dsi_vc_enable channel %d, enable %d\n", 2150 DSSDBG("dsi_vc_enable channel %d, enable %d\n",
@@ -2089,6 +2197,8 @@ static int dsi_vc_config_l4(int channel)
2089 2197
2090 DSSDBGF("%d", channel); 2198 DSSDBGF("%d", channel);
2091 2199
2200 dsi_sync_vc(channel);
2201
2092 dsi_vc_enable(channel, 0); 2202 dsi_vc_enable(channel, 0);
2093 2203
2094 /* VC_BUSY */ 2204 /* VC_BUSY */
@@ -2117,6 +2227,8 @@ static int dsi_vc_config_vp(int channel)
2117 2227
2118 DSSDBGF("%d", channel); 2228 DSSDBGF("%d", channel);
2119 2229
2230 dsi_sync_vc(channel);
2231
2120 dsi_vc_enable(channel, 0); 2232 dsi_vc_enable(channel, 0);
2121 2233
2122 /* VC_BUSY */ 2234 /* VC_BUSY */
@@ -3109,17 +3221,8 @@ static void dsi_te_timeout(unsigned long arg)
3109} 3221}
3110#endif 3222#endif
3111 3223
3112static void dsi_framedone_bta_callback(void *data, u32 mask);
3113
3114static void dsi_handle_framedone(int error) 3224static void dsi_handle_framedone(int error)
3115{ 3225{
3116 const int channel = dsi.update_channel;
3117
3118 dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
3119 NULL, DSI_VC_IRQ_BTA);
3120
3121 cancel_delayed_work(&dsi.framedone_timeout_work);
3122
3123 /* SIDLEMODE back to smart-idle */ 3226 /* SIDLEMODE back to smart-idle */
3124 dispc_enable_sidle(); 3227 dispc_enable_sidle();
3125 3228
@@ -3128,14 +3231,6 @@ static void dsi_handle_framedone(int error)
3128 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ 3231 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
3129 } 3232 }
3130 3233
3131 /* RX_FIFO_NOT_EMPTY */
3132 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
3133 DSSERR("Received error during frame transfer:\n");
3134 dsi_vc_flush_receive_data(channel);
3135 if (!error)
3136 error = -EIO;
3137 }
3138
3139 dsi.framedone_callback(error, dsi.framedone_data); 3234 dsi.framedone_callback(error, dsi.framedone_data);
3140 3235
3141 if (!error) 3236 if (!error)
@@ -3156,61 +3251,20 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
3156 dsi_handle_framedone(-ETIMEDOUT); 3251 dsi_handle_framedone(-ETIMEDOUT);
3157} 3252}
3158 3253
3159static void dsi_framedone_bta_callback(void *data, u32 mask)
3160{
3161 dsi_handle_framedone(0);
3162
3163#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
3164 dispc_fake_vsync_irq();
3165#endif
3166}
3167
3168static void dsi_framedone_irq_callback(void *data, u32 mask) 3254static void dsi_framedone_irq_callback(void *data, u32 mask)
3169{ 3255{
3170 const int channel = dsi.update_channel;
3171 int r;
3172
3173 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 3256 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
3174 * turns itself off. However, DSI still has the pixels in its buffers, 3257 * turns itself off. However, DSI still has the pixels in its buffers,
3175 * and is sending the data. 3258 * and is sending the data.
3176 */ 3259 */
3177 3260
3178 if (dsi.te_enabled) { 3261 __cancel_delayed_work(&dsi.framedone_timeout_work);
3179 /* enable LP_RX_TO again after the TE */
3180 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
3181 }
3182 3262
3183 /* Send BTA after the frame. We need this for the TE to work, as TE 3263 dsi_handle_framedone(0);
3184 * trigger is only sent for BTAs without preceding packet. Thus we need
3185 * to BTA after the pixel packets so that next BTA will cause TE
3186 * trigger.
3187 *
3188 * This is not needed when TE is not in use, but we do it anyway to
3189 * make sure that the transfer has been completed. It would be more
3190 * optimal, but more complex, to wait only just before starting next
3191 * transfer.
3192 *
3193 * Also, as there's no interrupt telling when the transfer has been
3194 * done and the channel could be reconfigured, the only way is to
3195 * busyloop until TE_SIZE is zero. With BTA we can do this
3196 * asynchronously.
3197 * */
3198
3199 r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback,
3200 NULL, DSI_VC_IRQ_BTA);
3201 if (r) {
3202 DSSERR("Failed to register BTA ISR\n");
3203 dsi_handle_framedone(-EIO);
3204 return;
3205 }
3206 3264
3207 r = dsi_vc_send_bta(channel); 3265#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
3208 if (r) { 3266 dispc_fake_vsync_irq();
3209 DSSERR("BTA after framedone failed\n"); 3267#endif
3210 dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
3211 NULL, DSI_VC_IRQ_BTA);
3212 dsi_handle_framedone(-EIO);
3213 }
3214} 3268}
3215 3269
3216int omap_dsi_prepare_update(struct omap_dss_device *dssdev, 3270int omap_dsi_prepare_update(struct omap_dss_device *dssdev,