diff options
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 159 |
1 files changed, 144 insertions, 15 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 5936487b5def..6122178f5f85 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -204,6 +204,14 @@ struct dsi_update_region { | |||
204 | struct omap_dss_device *device; | 204 | struct omap_dss_device *device; |
205 | }; | 205 | }; |
206 | 206 | ||
207 | struct dsi_irq_stats { | ||
208 | unsigned long last_reset; | ||
209 | unsigned irq_count; | ||
210 | unsigned dsi_irqs[32]; | ||
211 | unsigned vc_irqs[4][32]; | ||
212 | unsigned cio_irqs[32]; | ||
213 | }; | ||
214 | |||
207 | static struct | 215 | static struct |
208 | { | 216 | { |
209 | void __iomem *base; | 217 | void __iomem *base; |
@@ -258,6 +266,11 @@ static struct | |||
258 | #endif | 266 | #endif |
259 | int debug_read; | 267 | int debug_read; |
260 | int debug_write; | 268 | int debug_write; |
269 | |||
270 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
271 | spinlock_t irq_stats_lock; | ||
272 | struct dsi_irq_stats irq_stats; | ||
273 | #endif | ||
261 | } dsi; | 274 | } dsi; |
262 | 275 | ||
263 | #ifdef DEBUG | 276 | #ifdef DEBUG |
@@ -528,6 +541,12 @@ void dsi_irq_handler(void) | |||
528 | 541 | ||
529 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); | 542 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); |
530 | 543 | ||
544 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
545 | spin_lock(&dsi.irq_stats_lock); | ||
546 | dsi.irq_stats.irq_count++; | ||
547 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); | ||
548 | #endif | ||
549 | |||
531 | if (irqstatus & DSI_IRQ_ERROR_MASK) { | 550 | if (irqstatus & DSI_IRQ_ERROR_MASK) { |
532 | DSSERR("DSI error, irqstatus %x\n", irqstatus); | 551 | DSSERR("DSI error, irqstatus %x\n", irqstatus); |
533 | print_irq_status(irqstatus); | 552 | print_irq_status(irqstatus); |
@@ -549,6 +568,10 @@ void dsi_irq_handler(void) | |||
549 | 568 | ||
550 | vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 569 | vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); |
551 | 570 | ||
571 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
572 | dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); | ||
573 | #endif | ||
574 | |||
552 | if (vcstatus & DSI_VC_IRQ_BTA) | 575 | if (vcstatus & DSI_VC_IRQ_BTA) |
553 | complete(&dsi.bta_completion); | 576 | complete(&dsi.bta_completion); |
554 | 577 | ||
@@ -568,6 +591,10 @@ void dsi_irq_handler(void) | |||
568 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { | 591 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { |
569 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 592 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
570 | 593 | ||
594 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
595 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | ||
596 | #endif | ||
597 | |||
571 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); | 598 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); |
572 | /* flush posted write */ | 599 | /* flush posted write */ |
573 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 600 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
@@ -579,6 +606,10 @@ void dsi_irq_handler(void) | |||
579 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | 606 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); |
580 | /* flush posted write */ | 607 | /* flush posted write */ |
581 | dsi_read_reg(DSI_IRQSTATUS); | 608 | dsi_read_reg(DSI_IRQSTATUS); |
609 | |||
610 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
611 | spin_unlock(&dsi.irq_stats_lock); | ||
612 | #endif | ||
582 | } | 613 | } |
583 | 614 | ||
584 | 615 | ||
@@ -797,12 +828,12 @@ static int dsi_pll_power(enum dsi_pll_power_state state) | |||
797 | 828 | ||
798 | /* PLL_PWR_STATUS */ | 829 | /* PLL_PWR_STATUS */ |
799 | while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { | 830 | while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { |
800 | udelay(1); | 831 | if (++t > 1000) { |
801 | if (t++ > 1000) { | ||
802 | DSSERR("Failed to set DSI PLL power mode to %d\n", | 832 | DSSERR("Failed to set DSI PLL power mode to %d\n", |
803 | state); | 833 | state); |
804 | return -ENODEV; | 834 | return -ENODEV; |
805 | } | 835 | } |
836 | udelay(1); | ||
806 | } | 837 | } |
807 | 838 | ||
808 | return 0; | 839 | return 0; |
@@ -1226,6 +1257,95 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1226 | enable_clocks(0); | 1257 | enable_clocks(0); |
1227 | } | 1258 | } |
1228 | 1259 | ||
1260 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
1261 | void dsi_dump_irqs(struct seq_file *s) | ||
1262 | { | ||
1263 | unsigned long flags; | ||
1264 | struct dsi_irq_stats stats; | ||
1265 | |||
1266 | spin_lock_irqsave(&dsi.irq_stats_lock, flags); | ||
1267 | |||
1268 | stats = dsi.irq_stats; | ||
1269 | memset(&dsi.irq_stats, 0, sizeof(dsi.irq_stats)); | ||
1270 | dsi.irq_stats.last_reset = jiffies; | ||
1271 | |||
1272 | spin_unlock_irqrestore(&dsi.irq_stats_lock, flags); | ||
1273 | |||
1274 | seq_printf(s, "period %u ms\n", | ||
1275 | jiffies_to_msecs(jiffies - stats.last_reset)); | ||
1276 | |||
1277 | seq_printf(s, "irqs %d\n", stats.irq_count); | ||
1278 | #define PIS(x) \ | ||
1279 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); | ||
1280 | |||
1281 | seq_printf(s, "-- DSI interrupts --\n"); | ||
1282 | PIS(VC0); | ||
1283 | PIS(VC1); | ||
1284 | PIS(VC2); | ||
1285 | PIS(VC3); | ||
1286 | PIS(WAKEUP); | ||
1287 | PIS(RESYNC); | ||
1288 | PIS(PLL_LOCK); | ||
1289 | PIS(PLL_UNLOCK); | ||
1290 | PIS(PLL_RECALL); | ||
1291 | PIS(COMPLEXIO_ERR); | ||
1292 | PIS(HS_TX_TIMEOUT); | ||
1293 | PIS(LP_RX_TIMEOUT); | ||
1294 | PIS(TE_TRIGGER); | ||
1295 | PIS(ACK_TRIGGER); | ||
1296 | PIS(SYNC_LOST); | ||
1297 | PIS(LDO_POWER_GOOD); | ||
1298 | PIS(TA_TIMEOUT); | ||
1299 | #undef PIS | ||
1300 | |||
1301 | #define PIS(x) \ | ||
1302 | seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \ | ||
1303 | stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \ | ||
1304 | stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \ | ||
1305 | stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \ | ||
1306 | stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]); | ||
1307 | |||
1308 | seq_printf(s, "-- VC interrupts --\n"); | ||
1309 | PIS(CS); | ||
1310 | PIS(ECC_CORR); | ||
1311 | PIS(PACKET_SENT); | ||
1312 | PIS(FIFO_TX_OVF); | ||
1313 | PIS(FIFO_RX_OVF); | ||
1314 | PIS(BTA); | ||
1315 | PIS(ECC_NO_CORR); | ||
1316 | PIS(FIFO_TX_UDF); | ||
1317 | PIS(PP_BUSY_CHANGE); | ||
1318 | #undef PIS | ||
1319 | |||
1320 | #define PIS(x) \ | ||
1321 | seq_printf(s, "%-20s %10d\n", #x, \ | ||
1322 | stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]); | ||
1323 | |||
1324 | seq_printf(s, "-- CIO interrupts --\n"); | ||
1325 | PIS(ERRSYNCESC1); | ||
1326 | PIS(ERRSYNCESC2); | ||
1327 | PIS(ERRSYNCESC3); | ||
1328 | PIS(ERRESC1); | ||
1329 | PIS(ERRESC2); | ||
1330 | PIS(ERRESC3); | ||
1331 | PIS(ERRCONTROL1); | ||
1332 | PIS(ERRCONTROL2); | ||
1333 | PIS(ERRCONTROL3); | ||
1334 | PIS(STATEULPS1); | ||
1335 | PIS(STATEULPS2); | ||
1336 | PIS(STATEULPS3); | ||
1337 | PIS(ERRCONTENTIONLP0_1); | ||
1338 | PIS(ERRCONTENTIONLP1_1); | ||
1339 | PIS(ERRCONTENTIONLP0_2); | ||
1340 | PIS(ERRCONTENTIONLP1_2); | ||
1341 | PIS(ERRCONTENTIONLP0_3); | ||
1342 | PIS(ERRCONTENTIONLP1_3); | ||
1343 | PIS(ULPSACTIVENOT_ALL0); | ||
1344 | PIS(ULPSACTIVENOT_ALL1); | ||
1345 | #undef PIS | ||
1346 | } | ||
1347 | #endif | ||
1348 | |||
1229 | void dsi_dump_regs(struct seq_file *s) | 1349 | void dsi_dump_regs(struct seq_file *s) |
1230 | { | 1350 | { |
1231 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) | 1351 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) |
@@ -1321,12 +1441,12 @@ static int dsi_complexio_power(enum dsi_complexio_power_state state) | |||
1321 | 1441 | ||
1322 | /* PWR_STATUS */ | 1442 | /* PWR_STATUS */ |
1323 | while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { | 1443 | while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { |
1324 | udelay(1); | 1444 | if (++t > 1000) { |
1325 | if (t++ > 1000) { | ||
1326 | DSSERR("failed to set complexio power state to " | 1445 | DSSERR("failed to set complexio power state to " |
1327 | "%d\n", state); | 1446 | "%d\n", state); |
1328 | return -ENODEV; | 1447 | return -ENODEV; |
1329 | } | 1448 | } |
1449 | udelay(1); | ||
1330 | } | 1450 | } |
1331 | 1451 | ||
1332 | return 0; | 1452 | return 0; |
@@ -1526,10 +1646,10 @@ static void dsi_complexio_uninit(void) | |||
1526 | 1646 | ||
1527 | static int _dsi_wait_reset(void) | 1647 | static int _dsi_wait_reset(void) |
1528 | { | 1648 | { |
1529 | int i = 0; | 1649 | int t = 0; |
1530 | 1650 | ||
1531 | while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { | 1651 | while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { |
1532 | if (i++ > 5) { | 1652 | if (++t > 5) { |
1533 | DSSERR("soft reset failed\n"); | 1653 | DSSERR("soft reset failed\n"); |
1534 | return -ENODEV; | 1654 | return -ENODEV; |
1535 | } | 1655 | } |
@@ -1999,7 +2119,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) | |||
1999 | return -EINVAL; | 2119 | return -EINVAL; |
2000 | } | 2120 | } |
2001 | 2121 | ||
2002 | data_id = data_type | channel << 6; | 2122 | data_id = data_type | dsi.vc[channel].dest_per << 6; |
2003 | 2123 | ||
2004 | r = (data_id << 0) | (data << 8) | (ecc << 24); | 2124 | r = (data_id << 0) | (data << 8) | (ecc << 24); |
2005 | 2125 | ||
@@ -2011,7 +2131,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) | |||
2011 | int dsi_vc_send_null(int channel) | 2131 | int dsi_vc_send_null(int channel) |
2012 | { | 2132 | { |
2013 | u8 nullpkg[] = {0, 0, 0, 0}; | 2133 | u8 nullpkg[] = {0, 0, 0, 0}; |
2014 | return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0); | 2134 | return dsi_vc_send_long(channel, DSI_DT_NULL_PACKET, nullpkg, 4, 0); |
2015 | } | 2135 | } |
2016 | EXPORT_SYMBOL(dsi_vc_send_null); | 2136 | EXPORT_SYMBOL(dsi_vc_send_null); |
2017 | 2137 | ||
@@ -2058,7 +2178,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) | |||
2058 | int r; | 2178 | int r; |
2059 | 2179 | ||
2060 | if (dsi.debug_read) | 2180 | if (dsi.debug_read) |
2061 | DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd); | 2181 | DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); |
2062 | 2182 | ||
2063 | r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); | 2183 | r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); |
2064 | if (r) | 2184 | if (r) |
@@ -2586,7 +2706,6 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2586 | /* using fifo not empty */ | 2706 | /* using fifo not empty */ |
2587 | /* TX_FIFO_NOT_EMPTY */ | 2707 | /* TX_FIFO_NOT_EMPTY */ |
2588 | while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { | 2708 | while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { |
2589 | udelay(1); | ||
2590 | fifo_stalls++; | 2709 | fifo_stalls++; |
2591 | if (fifo_stalls > 0xfffff) { | 2710 | if (fifo_stalls > 0xfffff) { |
2592 | DSSERR("fifo stalls overflow, pixels left %d\n", | 2711 | DSSERR("fifo stalls overflow, pixels left %d\n", |
@@ -2594,6 +2713,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | |||
2594 | dsi_if_enable(0); | 2713 | dsi_if_enable(0); |
2595 | return -EIO; | 2714 | return -EIO; |
2596 | } | 2715 | } |
2716 | udelay(1); | ||
2597 | } | 2717 | } |
2598 | #elif 1 | 2718 | #elif 1 |
2599 | /* using fifo emptiness */ | 2719 | /* using fifo emptiness */ |
@@ -2812,11 +2932,15 @@ static int dsi_set_update_mode(struct omap_dss_device *dssdev, | |||
2812 | 2932 | ||
2813 | static int dsi_set_te(struct omap_dss_device *dssdev, bool enable) | 2933 | static int dsi_set_te(struct omap_dss_device *dssdev, bool enable) |
2814 | { | 2934 | { |
2815 | int r; | 2935 | int r = 0; |
2816 | r = dssdev->driver->enable_te(dssdev, enable); | 2936 | |
2817 | /* XXX for some reason, DSI TE breaks if we don't wait here. | 2937 | if (dssdev->driver->enable_te) { |
2818 | * Panel bug? Needs more studying */ | 2938 | r = dssdev->driver->enable_te(dssdev, enable); |
2819 | msleep(100); | 2939 | /* XXX for some reason, DSI TE breaks if we don't wait here. |
2940 | * Panel bug? Needs more studying */ | ||
2941 | msleep(100); | ||
2942 | } | ||
2943 | |||
2820 | return r; | 2944 | return r; |
2821 | } | 2945 | } |
2822 | 2946 | ||
@@ -3637,6 +3761,11 @@ int dsi_init(struct platform_device *pdev) | |||
3637 | spin_lock_init(&dsi.errors_lock); | 3761 | spin_lock_init(&dsi.errors_lock); |
3638 | dsi.errors = 0; | 3762 | dsi.errors = 0; |
3639 | 3763 | ||
3764 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3765 | spin_lock_init(&dsi.irq_stats_lock); | ||
3766 | dsi.irq_stats.last_reset = jiffies; | ||
3767 | #endif | ||
3768 | |||
3640 | init_completion(&dsi.bta_completion); | 3769 | init_completion(&dsi.bta_completion); |
3641 | init_completion(&dsi.update_completion); | 3770 | init_completion(&dsi.update_completion); |
3642 | 3771 | ||