diff options
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 537 |
1 files changed, 338 insertions, 199 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 662d14f8c2c3..ec363d8390ed 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -256,14 +256,13 @@ struct dsi_data { | |||
256 | struct platform_device *pdev; | 256 | struct platform_device *pdev; |
257 | void __iomem *base; | 257 | void __iomem *base; |
258 | 258 | ||
259 | int module_id; | ||
260 | |||
259 | int irq; | 261 | int irq; |
260 | 262 | ||
261 | struct clk *dss_clk; | 263 | struct clk *dss_clk; |
262 | struct clk *sys_clk; | 264 | struct clk *sys_clk; |
263 | 265 | ||
264 | int (*enable_pads)(int dsi_id, unsigned lane_mask); | ||
265 | void (*disable_pads)(int dsi_id, unsigned lane_mask); | ||
266 | |||
267 | struct dsi_clock_info current_cinfo; | 266 | struct dsi_clock_info current_cinfo; |
268 | 267 | ||
269 | bool vdds_dsi_enabled; | 268 | bool vdds_dsi_enabled; |
@@ -361,11 +360,6 @@ struct platform_device *dsi_get_dsidev_from_id(int module) | |||
361 | return dsi_pdev_map[module]; | 360 | return dsi_pdev_map[module]; |
362 | } | 361 | } |
363 | 362 | ||
364 | static inline int dsi_get_dsidev_id(struct platform_device *dsidev) | ||
365 | { | ||
366 | return dsidev->id; | ||
367 | } | ||
368 | |||
369 | static inline void dsi_write_reg(struct platform_device *dsidev, | 363 | static inline void dsi_write_reg(struct platform_device *dsidev, |
370 | const struct dsi_reg idx, u32 val) | 364 | const struct dsi_reg idx, u32 val) |
371 | { | 365 | { |
@@ -452,6 +446,7 @@ u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) | |||
452 | return 16; | 446 | return 16; |
453 | default: | 447 | default: |
454 | BUG(); | 448 | BUG(); |
449 | return 0; | ||
455 | } | 450 | } |
456 | } | 451 | } |
457 | 452 | ||
@@ -1184,10 +1179,9 @@ static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev) | |||
1184 | static unsigned long dsi_fclk_rate(struct platform_device *dsidev) | 1179 | static unsigned long dsi_fclk_rate(struct platform_device *dsidev) |
1185 | { | 1180 | { |
1186 | unsigned long r; | 1181 | unsigned long r; |
1187 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
1188 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1182 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1189 | 1183 | ||
1190 | if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { | 1184 | if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) { |
1191 | /* DSI FCLK source is DSS_CLK_FCK */ | 1185 | /* DSI FCLK source is DSS_CLK_FCK */ |
1192 | r = clk_get_rate(dsi->dss_clk); | 1186 | r = clk_get_rate(dsi->dss_clk); |
1193 | } else { | 1187 | } else { |
@@ -1279,10 +1273,9 @@ static int dsi_pll_power(struct platform_device *dsidev, | |||
1279 | } | 1273 | } |
1280 | 1274 | ||
1281 | /* calculate clock rates using dividers in cinfo */ | 1275 | /* calculate clock rates using dividers in cinfo */ |
1282 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | 1276 | static int dsi_calc_clock_rates(struct platform_device *dsidev, |
1283 | struct dsi_clock_info *cinfo) | 1277 | struct dsi_clock_info *cinfo) |
1284 | { | 1278 | { |
1285 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
1286 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1279 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1287 | 1280 | ||
1288 | if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) | 1281 | if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) |
@@ -1297,21 +1290,8 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
1297 | if (cinfo->regm_dsi > dsi->regm_dsi_max) | 1290 | if (cinfo->regm_dsi > dsi->regm_dsi_max) |
1298 | return -EINVAL; | 1291 | return -EINVAL; |
1299 | 1292 | ||
1300 | if (cinfo->use_sys_clk) { | 1293 | cinfo->clkin = clk_get_rate(dsi->sys_clk); |
1301 | cinfo->clkin = clk_get_rate(dsi->sys_clk); | 1294 | cinfo->fint = cinfo->clkin / cinfo->regn; |
1302 | /* XXX it is unclear if highfreq should be used | ||
1303 | * with DSS_SYS_CLK source also */ | ||
1304 | cinfo->highfreq = 0; | ||
1305 | } else { | ||
1306 | cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id); | ||
1307 | |||
1308 | if (cinfo->clkin < 32000000) | ||
1309 | cinfo->highfreq = 0; | ||
1310 | else | ||
1311 | cinfo->highfreq = 1; | ||
1312 | } | ||
1313 | |||
1314 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); | ||
1315 | 1295 | ||
1316 | if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) | 1296 | if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) |
1317 | return -EINVAL; | 1297 | return -EINVAL; |
@@ -1378,27 +1358,21 @@ retry: | |||
1378 | 1358 | ||
1379 | memset(&cur, 0, sizeof(cur)); | 1359 | memset(&cur, 0, sizeof(cur)); |
1380 | cur.clkin = dss_sys_clk; | 1360 | cur.clkin = dss_sys_clk; |
1381 | cur.use_sys_clk = 1; | ||
1382 | cur.highfreq = 0; | ||
1383 | 1361 | ||
1384 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ | 1362 | /* 0.75MHz < Fint = clkin / regn < 2.1MHz */ |
1385 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ | ||
1386 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ | 1363 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ |
1387 | for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { | 1364 | for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { |
1388 | if (cur.highfreq == 0) | 1365 | cur.fint = cur.clkin / cur.regn; |
1389 | cur.fint = cur.clkin / cur.regn; | ||
1390 | else | ||
1391 | cur.fint = cur.clkin / (2 * cur.regn); | ||
1392 | 1366 | ||
1393 | if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) | 1367 | if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) |
1394 | continue; | 1368 | continue; |
1395 | 1369 | ||
1396 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ | 1370 | /* DSIPHY(MHz) = (2 * regm / regn) * clkin */ |
1397 | for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { | 1371 | for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { |
1398 | unsigned long a, b; | 1372 | unsigned long a, b; |
1399 | 1373 | ||
1400 | a = 2 * cur.regm * (cur.clkin/1000); | 1374 | a = 2 * cur.regm * (cur.clkin/1000); |
1401 | b = cur.regn * (cur.highfreq + 1); | 1375 | b = cur.regn; |
1402 | cur.clkin4ddr = a / b * 1000; | 1376 | cur.clkin4ddr = a / b * 1000; |
1403 | 1377 | ||
1404 | if (cur.clkin4ddr > 1800 * 1000 * 1000) | 1378 | if (cur.clkin4ddr > 1800 * 1000 * 1000) |
@@ -1486,9 +1460,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, | |||
1486 | 1460 | ||
1487 | DSSDBGF(); | 1461 | DSSDBGF(); |
1488 | 1462 | ||
1489 | dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk; | 1463 | dsi->current_cinfo.clkin = cinfo->clkin; |
1490 | dsi->current_cinfo.highfreq = cinfo->highfreq; | ||
1491 | |||
1492 | dsi->current_cinfo.fint = cinfo->fint; | 1464 | dsi->current_cinfo.fint = cinfo->fint; |
1493 | dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; | 1465 | dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; |
1494 | dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = | 1466 | dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = |
@@ -1503,17 +1475,13 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, | |||
1503 | 1475 | ||
1504 | DSSDBG("DSI Fint %ld\n", cinfo->fint); | 1476 | DSSDBG("DSI Fint %ld\n", cinfo->fint); |
1505 | 1477 | ||
1506 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", | 1478 | DSSDBG("clkin rate %ld\n", cinfo->clkin); |
1507 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", | ||
1508 | cinfo->clkin, | ||
1509 | cinfo->highfreq); | ||
1510 | 1479 | ||
1511 | /* DSIPHY == CLKIN4DDR */ | 1480 | /* DSIPHY == CLKIN4DDR */ |
1512 | DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n", | 1481 | DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n", |
1513 | cinfo->regm, | 1482 | cinfo->regm, |
1514 | cinfo->regn, | 1483 | cinfo->regn, |
1515 | cinfo->clkin, | 1484 | cinfo->clkin, |
1516 | cinfo->highfreq + 1, | ||
1517 | cinfo->clkin4ddr); | 1485 | cinfo->clkin4ddr); |
1518 | 1486 | ||
1519 | DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", | 1487 | DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", |
@@ -1568,10 +1536,6 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, | |||
1568 | 1536 | ||
1569 | if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) | 1537 | if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) |
1570 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ | 1538 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ |
1571 | l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, | ||
1572 | 11, 11); /* DSI_PLL_CLKSEL */ | ||
1573 | l = FLD_MOD(l, cinfo->highfreq, | ||
1574 | 12, 12); /* DSI_PLL_HIGHFREQ */ | ||
1575 | l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ | 1539 | l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ |
1576 | l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ | 1540 | l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ |
1577 | l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ | 1541 | l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ |
@@ -1716,7 +1680,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, | |||
1716 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1680 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1717 | struct dsi_clock_info *cinfo = &dsi->current_cinfo; | 1681 | struct dsi_clock_info *cinfo = &dsi->current_cinfo; |
1718 | enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; | 1682 | enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; |
1719 | int dsi_module = dsi_get_dsidev_id(dsidev); | 1683 | int dsi_module = dsi->module_id; |
1720 | 1684 | ||
1721 | dispc_clk_src = dss_get_dispc_clk_source(); | 1685 | dispc_clk_src = dss_get_dispc_clk_source(); |
1722 | dsi_clk_src = dss_get_dsi_clk_source(dsi_module); | 1686 | dsi_clk_src = dss_get_dsi_clk_source(dsi_module); |
@@ -1726,8 +1690,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, | |||
1726 | 1690 | ||
1727 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); | 1691 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); |
1728 | 1692 | ||
1729 | seq_printf(s, "dsi pll source = %s\n", | 1693 | seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin); |
1730 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree"); | ||
1731 | 1694 | ||
1732 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); | 1695 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); |
1733 | 1696 | ||
@@ -1789,7 +1752,6 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, | |||
1789 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1752 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1790 | unsigned long flags; | 1753 | unsigned long flags; |
1791 | struct dsi_irq_stats stats; | 1754 | struct dsi_irq_stats stats; |
1792 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
1793 | 1755 | ||
1794 | spin_lock_irqsave(&dsi->irq_stats_lock, flags); | 1756 | spin_lock_irqsave(&dsi->irq_stats_lock, flags); |
1795 | 1757 | ||
@@ -1806,7 +1768,7 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev, | |||
1806 | #define PIS(x) \ | 1768 | #define PIS(x) \ |
1807 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); | 1769 | seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); |
1808 | 1770 | ||
1809 | seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1); | 1771 | seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1); |
1810 | PIS(VC0); | 1772 | PIS(VC0); |
1811 | PIS(VC1); | 1773 | PIS(VC1); |
1812 | PIS(VC2); | 1774 | PIS(VC2); |
@@ -1886,22 +1848,6 @@ static void dsi2_dump_irqs(struct seq_file *s) | |||
1886 | 1848 | ||
1887 | dsi_dump_dsidev_irqs(dsidev, s); | 1849 | dsi_dump_dsidev_irqs(dsidev, s); |
1888 | } | 1850 | } |
1889 | |||
1890 | void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir, | ||
1891 | const struct file_operations *debug_fops) | ||
1892 | { | ||
1893 | struct platform_device *dsidev; | ||
1894 | |||
1895 | dsidev = dsi_get_dsidev_from_id(0); | ||
1896 | if (dsidev) | ||
1897 | debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir, | ||
1898 | &dsi1_dump_irqs, debug_fops); | ||
1899 | |||
1900 | dsidev = dsi_get_dsidev_from_id(1); | ||
1901 | if (dsidev) | ||
1902 | debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir, | ||
1903 | &dsi2_dump_irqs, debug_fops); | ||
1904 | } | ||
1905 | #endif | 1851 | #endif |
1906 | 1852 | ||
1907 | static void dsi_dump_dsidev_regs(struct platform_device *dsidev, | 1853 | static void dsi_dump_dsidev_regs(struct platform_device *dsidev, |
@@ -2002,21 +1948,6 @@ static void dsi2_dump_regs(struct seq_file *s) | |||
2002 | dsi_dump_dsidev_regs(dsidev, s); | 1948 | dsi_dump_dsidev_regs(dsidev, s); |
2003 | } | 1949 | } |
2004 | 1950 | ||
2005 | void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | ||
2006 | const struct file_operations *debug_fops) | ||
2007 | { | ||
2008 | struct platform_device *dsidev; | ||
2009 | |||
2010 | dsidev = dsi_get_dsidev_from_id(0); | ||
2011 | if (dsidev) | ||
2012 | debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir, | ||
2013 | &dsi1_dump_regs, debug_fops); | ||
2014 | |||
2015 | dsidev = dsi_get_dsidev_from_id(1); | ||
2016 | if (dsidev) | ||
2017 | debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir, | ||
2018 | &dsi2_dump_regs, debug_fops); | ||
2019 | } | ||
2020 | enum dsi_cio_power_state { | 1951 | enum dsi_cio_power_state { |
2021 | DSI_COMPLEXIO_POWER_OFF = 0x0, | 1952 | DSI_COMPLEXIO_POWER_OFF = 0x0, |
2022 | DSI_COMPLEXIO_POWER_ON = 0x1, | 1953 | DSI_COMPLEXIO_POWER_ON = 0x1, |
@@ -2073,68 +2004,10 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) | |||
2073 | return 1365 * 3; /* 1365x24 bits */ | 2004 | return 1365 * 3; /* 1365x24 bits */ |
2074 | default: | 2005 | default: |
2075 | BUG(); | 2006 | BUG(); |
2007 | return 0; | ||
2076 | } | 2008 | } |
2077 | } | 2009 | } |
2078 | 2010 | ||
2079 | static int dsi_parse_lane_config(struct omap_dss_device *dssdev) | ||
2080 | { | ||
2081 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
2082 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2083 | u8 lanes[DSI_MAX_NR_LANES]; | ||
2084 | u8 polarities[DSI_MAX_NR_LANES]; | ||
2085 | int num_lanes, i; | ||
2086 | |||
2087 | static const enum dsi_lane_function functions[] = { | ||
2088 | DSI_LANE_CLK, | ||
2089 | DSI_LANE_DATA1, | ||
2090 | DSI_LANE_DATA2, | ||
2091 | DSI_LANE_DATA3, | ||
2092 | DSI_LANE_DATA4, | ||
2093 | }; | ||
2094 | |||
2095 | lanes[0] = dssdev->phy.dsi.clk_lane; | ||
2096 | lanes[1] = dssdev->phy.dsi.data1_lane; | ||
2097 | lanes[2] = dssdev->phy.dsi.data2_lane; | ||
2098 | lanes[3] = dssdev->phy.dsi.data3_lane; | ||
2099 | lanes[4] = dssdev->phy.dsi.data4_lane; | ||
2100 | polarities[0] = dssdev->phy.dsi.clk_pol; | ||
2101 | polarities[1] = dssdev->phy.dsi.data1_pol; | ||
2102 | polarities[2] = dssdev->phy.dsi.data2_pol; | ||
2103 | polarities[3] = dssdev->phy.dsi.data3_pol; | ||
2104 | polarities[4] = dssdev->phy.dsi.data4_pol; | ||
2105 | |||
2106 | num_lanes = 0; | ||
2107 | |||
2108 | for (i = 0; i < dsi->num_lanes_supported; ++i) | ||
2109 | dsi->lanes[i].function = DSI_LANE_UNUSED; | ||
2110 | |||
2111 | for (i = 0; i < dsi->num_lanes_supported; ++i) { | ||
2112 | int num; | ||
2113 | |||
2114 | if (lanes[i] == DSI_LANE_UNUSED) | ||
2115 | break; | ||
2116 | |||
2117 | num = lanes[i] - 1; | ||
2118 | |||
2119 | if (num >= dsi->num_lanes_supported) | ||
2120 | return -EINVAL; | ||
2121 | |||
2122 | if (dsi->lanes[num].function != DSI_LANE_UNUSED) | ||
2123 | return -EINVAL; | ||
2124 | |||
2125 | dsi->lanes[num].function = functions[i]; | ||
2126 | dsi->lanes[num].polarity = polarities[i]; | ||
2127 | num_lanes++; | ||
2128 | } | ||
2129 | |||
2130 | if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported) | ||
2131 | return -EINVAL; | ||
2132 | |||
2133 | dsi->num_lanes_used = num_lanes; | ||
2134 | |||
2135 | return 0; | ||
2136 | } | ||
2137 | |||
2138 | static int dsi_set_lane_config(struct omap_dss_device *dssdev) | 2011 | static int dsi_set_lane_config(struct omap_dss_device *dssdev) |
2139 | { | 2012 | { |
2140 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 2013 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
@@ -2396,7 +2269,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
2396 | 2269 | ||
2397 | DSSDBGF(); | 2270 | DSSDBGF(); |
2398 | 2271 | ||
2399 | r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); | 2272 | r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); |
2400 | if (r) | 2273 | if (r) |
2401 | return r; | 2274 | return r; |
2402 | 2275 | ||
@@ -2506,7 +2379,7 @@ err_cio_pwr: | |||
2506 | dsi_cio_disable_lane_override(dsidev); | 2379 | dsi_cio_disable_lane_override(dsidev); |
2507 | err_scp_clk_dom: | 2380 | err_scp_clk_dom: |
2508 | dsi_disable_scp_clk(dsidev); | 2381 | dsi_disable_scp_clk(dsidev); |
2509 | dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); | 2382 | dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); |
2510 | return r; | 2383 | return r; |
2511 | } | 2384 | } |
2512 | 2385 | ||
@@ -2520,7 +2393,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev) | |||
2520 | 2393 | ||
2521 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); | 2394 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); |
2522 | dsi_disable_scp_clk(dsidev); | 2395 | dsi_disable_scp_clk(dsidev); |
2523 | dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); | 2396 | dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); |
2524 | } | 2397 | } |
2525 | 2398 | ||
2526 | static void dsi_config_tx_fifo(struct platform_device *dsidev, | 2399 | static void dsi_config_tx_fifo(struct platform_device *dsidev, |
@@ -2544,6 +2417,7 @@ static void dsi_config_tx_fifo(struct platform_device *dsidev, | |||
2544 | if (add + size > 4) { | 2417 | if (add + size > 4) { |
2545 | DSSERR("Illegal FIFO configuration\n"); | 2418 | DSSERR("Illegal FIFO configuration\n"); |
2546 | BUG(); | 2419 | BUG(); |
2420 | return; | ||
2547 | } | 2421 | } |
2548 | 2422 | ||
2549 | v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); | 2423 | v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); |
@@ -2576,6 +2450,7 @@ static void dsi_config_rx_fifo(struct platform_device *dsidev, | |||
2576 | if (add + size > 4) { | 2450 | if (add + size > 4) { |
2577 | DSSERR("Illegal FIFO configuration\n"); | 2451 | DSSERR("Illegal FIFO configuration\n"); |
2578 | BUG(); | 2452 | BUG(); |
2453 | return; | ||
2579 | } | 2454 | } |
2580 | 2455 | ||
2581 | v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); | 2456 | v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); |
@@ -2717,6 +2592,7 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel) | |||
2717 | return dsi_sync_vc_l4(dsidev, channel); | 2592 | return dsi_sync_vc_l4(dsidev, channel); |
2718 | default: | 2593 | default: |
2719 | BUG(); | 2594 | BUG(); |
2595 | return -EINVAL; | ||
2720 | } | 2596 | } |
2721 | } | 2597 | } |
2722 | 2598 | ||
@@ -3285,6 +3161,7 @@ static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, | |||
3285 | data = reqdata[0] | (reqdata[1] << 8); | 3161 | data = reqdata[0] | (reqdata[1] << 8); |
3286 | } else { | 3162 | } else { |
3287 | BUG(); | 3163 | BUG(); |
3164 | return -EINVAL; | ||
3288 | } | 3165 | } |
3289 | 3166 | ||
3290 | r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); | 3167 | r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); |
@@ -3399,7 +3276,6 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel, | |||
3399 | goto err; | 3276 | goto err; |
3400 | } | 3277 | } |
3401 | 3278 | ||
3402 | BUG(); | ||
3403 | err: | 3279 | err: |
3404 | DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, | 3280 | DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, |
3405 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); | 3281 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); |
@@ -3794,6 +3670,186 @@ static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) | |||
3794 | dsi_write_reg(dsidev, DSI_CTRL, r); | 3670 | dsi_write_reg(dsidev, DSI_CTRL, r); |
3795 | } | 3671 | } |
3796 | 3672 | ||
3673 | /* | ||
3674 | * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3 | ||
3675 | * results in maximum transition time for data and clock lanes to enter and | ||
3676 | * exit HS mode. Hence, this is the scenario where the least amount of command | ||
3677 | * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS | ||
3678 | * clock cycles that can be used to interleave command mode data in HS so that | ||
3679 | * all scenarios are satisfied. | ||
3680 | */ | ||
3681 | static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs, | ||
3682 | int exit_hs, int exiths_clk, int ddr_pre, int ddr_post) | ||
3683 | { | ||
3684 | int transition; | ||
3685 | |||
3686 | /* | ||
3687 | * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition | ||
3688 | * time of data lanes only, if it isn't set, we need to consider HS | ||
3689 | * transition time of both data and clock lanes. HS transition time | ||
3690 | * of Scenario 3 is considered. | ||
3691 | */ | ||
3692 | if (ddr_alwon) { | ||
3693 | transition = enter_hs + exit_hs + max(enter_hs, 2) + 1; | ||
3694 | } else { | ||
3695 | int trans1, trans2; | ||
3696 | trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1; | ||
3697 | trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre + | ||
3698 | enter_hs + 1; | ||
3699 | transition = max(trans1, trans2); | ||
3700 | } | ||
3701 | |||
3702 | return blank > transition ? blank - transition : 0; | ||
3703 | } | ||
3704 | |||
3705 | /* | ||
3706 | * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1 | ||
3707 | * results in maximum transition time for data lanes to enter and exit LP mode. | ||
3708 | * Hence, this is the scenario where the least amount of command mode data can | ||
3709 | * be interleaved. We program the minimum amount of bytes that can be | ||
3710 | * interleaved in LP so that all scenarios are satisfied. | ||
3711 | */ | ||
3712 | static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs, | ||
3713 | int lp_clk_div, int tdsi_fclk) | ||
3714 | { | ||
3715 | int trans_lp; /* time required for a LP transition, in TXBYTECLKHS */ | ||
3716 | int tlp_avail; /* time left for interleaving commands, in CLKIN4DDR */ | ||
3717 | int ttxclkesc; /* period of LP transmit escape clock, in CLKIN4DDR */ | ||
3718 | int thsbyte_clk = 16; /* Period of TXBYTECLKHS clock, in CLKIN4DDR */ | ||
3719 | int lp_inter; /* cmd mode data that can be interleaved, in bytes */ | ||
3720 | |||
3721 | /* maximum LP transition time according to Scenario 1 */ | ||
3722 | trans_lp = exit_hs + max(enter_hs, 2) + 1; | ||
3723 | |||
3724 | /* CLKIN4DDR = 16 * TXBYTECLKHS */ | ||
3725 | tlp_avail = thsbyte_clk * (blank - trans_lp); | ||
3726 | |||
3727 | ttxclkesc = tdsi_fclk / lp_clk_div; | ||
3728 | |||
3729 | lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc - | ||
3730 | 26) / 16; | ||
3731 | |||
3732 | return max(lp_inter, 0); | ||
3733 | } | ||
3734 | |||
3735 | static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) | ||
3736 | { | ||
3737 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3738 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
3739 | int blanking_mode; | ||
3740 | int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode; | ||
3741 | int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div; | ||
3742 | int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; | ||
3743 | int tclk_trail, ths_exit, exiths_clk; | ||
3744 | bool ddr_alwon; | ||
3745 | struct omap_video_timings *timings = &dssdev->panel.timings; | ||
3746 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
3747 | int ndl = dsi->num_lanes_used - 1; | ||
3748 | int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1; | ||
3749 | int hsa_interleave_hs = 0, hsa_interleave_lp = 0; | ||
3750 | int hfp_interleave_hs = 0, hfp_interleave_lp = 0; | ||
3751 | int hbp_interleave_hs = 0, hbp_interleave_lp = 0; | ||
3752 | int bl_interleave_hs = 0, bl_interleave_lp = 0; | ||
3753 | u32 r; | ||
3754 | |||
3755 | r = dsi_read_reg(dsidev, DSI_CTRL); | ||
3756 | blanking_mode = FLD_GET(r, 20, 20); | ||
3757 | hfp_blanking_mode = FLD_GET(r, 21, 21); | ||
3758 | hbp_blanking_mode = FLD_GET(r, 22, 22); | ||
3759 | hsa_blanking_mode = FLD_GET(r, 23, 23); | ||
3760 | |||
3761 | r = dsi_read_reg(dsidev, DSI_VM_TIMING1); | ||
3762 | hbp = FLD_GET(r, 11, 0); | ||
3763 | hfp = FLD_GET(r, 23, 12); | ||
3764 | hsa = FLD_GET(r, 31, 24); | ||
3765 | |||
3766 | r = dsi_read_reg(dsidev, DSI_CLK_TIMING); | ||
3767 | ddr_clk_post = FLD_GET(r, 7, 0); | ||
3768 | ddr_clk_pre = FLD_GET(r, 15, 8); | ||
3769 | |||
3770 | r = dsi_read_reg(dsidev, DSI_VM_TIMING7); | ||
3771 | exit_hs_mode_lat = FLD_GET(r, 15, 0); | ||
3772 | enter_hs_mode_lat = FLD_GET(r, 31, 16); | ||
3773 | |||
3774 | r = dsi_read_reg(dsidev, DSI_CLK_CTRL); | ||
3775 | lp_clk_div = FLD_GET(r, 12, 0); | ||
3776 | ddr_alwon = FLD_GET(r, 13, 13); | ||
3777 | |||
3778 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); | ||
3779 | ths_exit = FLD_GET(r, 7, 0); | ||
3780 | |||
3781 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); | ||
3782 | tclk_trail = FLD_GET(r, 15, 8); | ||
3783 | |||
3784 | exiths_clk = ths_exit + tclk_trail; | ||
3785 | |||
3786 | width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); | ||
3787 | bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl); | ||
3788 | |||
3789 | if (!hsa_blanking_mode) { | ||
3790 | hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon, | ||
3791 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
3792 | exiths_clk, ddr_clk_pre, ddr_clk_post); | ||
3793 | hsa_interleave_lp = dsi_compute_interleave_lp(hsa, | ||
3794 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
3795 | lp_clk_div, dsi_fclk_hsdiv); | ||
3796 | } | ||
3797 | |||
3798 | if (!hfp_blanking_mode) { | ||
3799 | hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon, | ||
3800 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
3801 | exiths_clk, ddr_clk_pre, ddr_clk_post); | ||
3802 | hfp_interleave_lp = dsi_compute_interleave_lp(hfp, | ||
3803 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
3804 | lp_clk_div, dsi_fclk_hsdiv); | ||
3805 | } | ||
3806 | |||
3807 | if (!hbp_blanking_mode) { | ||
3808 | hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon, | ||
3809 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
3810 | exiths_clk, ddr_clk_pre, ddr_clk_post); | ||
3811 | |||
3812 | hbp_interleave_lp = dsi_compute_interleave_lp(hbp, | ||
3813 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
3814 | lp_clk_div, dsi_fclk_hsdiv); | ||
3815 | } | ||
3816 | |||
3817 | if (!blanking_mode) { | ||
3818 | bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon, | ||
3819 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
3820 | exiths_clk, ddr_clk_pre, ddr_clk_post); | ||
3821 | |||
3822 | bl_interleave_lp = dsi_compute_interleave_lp(bllp, | ||
3823 | enter_hs_mode_lat, exit_hs_mode_lat, | ||
3824 | lp_clk_div, dsi_fclk_hsdiv); | ||
3825 | } | ||
3826 | |||
3827 | DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n", | ||
3828 | hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs, | ||
3829 | bl_interleave_hs); | ||
3830 | |||
3831 | DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n", | ||
3832 | hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp, | ||
3833 | bl_interleave_lp); | ||
3834 | |||
3835 | r = dsi_read_reg(dsidev, DSI_VM_TIMING4); | ||
3836 | r = FLD_MOD(r, hsa_interleave_hs, 23, 16); | ||
3837 | r = FLD_MOD(r, hfp_interleave_hs, 15, 8); | ||
3838 | r = FLD_MOD(r, hbp_interleave_hs, 7, 0); | ||
3839 | dsi_write_reg(dsidev, DSI_VM_TIMING4, r); | ||
3840 | |||
3841 | r = dsi_read_reg(dsidev, DSI_VM_TIMING5); | ||
3842 | r = FLD_MOD(r, hsa_interleave_lp, 23, 16); | ||
3843 | r = FLD_MOD(r, hfp_interleave_lp, 15, 8); | ||
3844 | r = FLD_MOD(r, hbp_interleave_lp, 7, 0); | ||
3845 | dsi_write_reg(dsidev, DSI_VM_TIMING5, r); | ||
3846 | |||
3847 | r = dsi_read_reg(dsidev, DSI_VM_TIMING6); | ||
3848 | r = FLD_MOD(r, bl_interleave_hs, 31, 15); | ||
3849 | r = FLD_MOD(r, bl_interleave_lp, 16, 0); | ||
3850 | dsi_write_reg(dsidev, DSI_VM_TIMING6, r); | ||
3851 | } | ||
3852 | |||
3797 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 3853 | static int dsi_proto_config(struct omap_dss_device *dssdev) |
3798 | { | 3854 | { |
3799 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3855 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
@@ -3828,6 +3884,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
3828 | break; | 3884 | break; |
3829 | default: | 3885 | default: |
3830 | BUG(); | 3886 | BUG(); |
3887 | return -EINVAL; | ||
3831 | } | 3888 | } |
3832 | 3889 | ||
3833 | r = dsi_read_reg(dsidev, DSI_CTRL); | 3890 | r = dsi_read_reg(dsidev, DSI_CTRL); |
@@ -3852,6 +3909,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
3852 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { | 3909 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { |
3853 | dsi_config_vp_sync_events(dssdev); | 3910 | dsi_config_vp_sync_events(dssdev); |
3854 | dsi_config_blanking_modes(dssdev); | 3911 | dsi_config_blanking_modes(dssdev); |
3912 | dsi_config_cmd_mode_interleaving(dssdev); | ||
3855 | } | 3913 | } |
3856 | 3914 | ||
3857 | dsi_vc_initial_config(dsidev, 0); | 3915 | dsi_vc_initial_config(dsidev, 0); |
@@ -3975,6 +4033,74 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
3975 | } | 4033 | } |
3976 | } | 4034 | } |
3977 | 4035 | ||
4036 | int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev, | ||
4037 | const struct omap_dsi_pin_config *pin_cfg) | ||
4038 | { | ||
4039 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4040 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4041 | int num_pins; | ||
4042 | const int *pins; | ||
4043 | struct dsi_lane_config lanes[DSI_MAX_NR_LANES]; | ||
4044 | int num_lanes; | ||
4045 | int i; | ||
4046 | |||
4047 | static const enum dsi_lane_function functions[] = { | ||
4048 | DSI_LANE_CLK, | ||
4049 | DSI_LANE_DATA1, | ||
4050 | DSI_LANE_DATA2, | ||
4051 | DSI_LANE_DATA3, | ||
4052 | DSI_LANE_DATA4, | ||
4053 | }; | ||
4054 | |||
4055 | num_pins = pin_cfg->num_pins; | ||
4056 | pins = pin_cfg->pins; | ||
4057 | |||
4058 | if (num_pins < 4 || num_pins > dsi->num_lanes_supported * 2 | ||
4059 | || num_pins % 2 != 0) | ||
4060 | return -EINVAL; | ||
4061 | |||
4062 | for (i = 0; i < DSI_MAX_NR_LANES; ++i) | ||
4063 | lanes[i].function = DSI_LANE_UNUSED; | ||
4064 | |||
4065 | num_lanes = 0; | ||
4066 | |||
4067 | for (i = 0; i < num_pins; i += 2) { | ||
4068 | u8 lane, pol; | ||
4069 | int dx, dy; | ||
4070 | |||
4071 | dx = pins[i]; | ||
4072 | dy = pins[i + 1]; | ||
4073 | |||
4074 | if (dx < 0 || dx >= dsi->num_lanes_supported * 2) | ||
4075 | return -EINVAL; | ||
4076 | |||
4077 | if (dy < 0 || dy >= dsi->num_lanes_supported * 2) | ||
4078 | return -EINVAL; | ||
4079 | |||
4080 | if (dx & 1) { | ||
4081 | if (dy != dx - 1) | ||
4082 | return -EINVAL; | ||
4083 | pol = 1; | ||
4084 | } else { | ||
4085 | if (dy != dx + 1) | ||
4086 | return -EINVAL; | ||
4087 | pol = 0; | ||
4088 | } | ||
4089 | |||
4090 | lane = dx / 2; | ||
4091 | |||
4092 | lanes[lane].function = functions[i / 2]; | ||
4093 | lanes[lane].polarity = pol; | ||
4094 | num_lanes++; | ||
4095 | } | ||
4096 | |||
4097 | memcpy(dsi->lanes, lanes, sizeof(dsi->lanes)); | ||
4098 | dsi->num_lanes_used = num_lanes; | ||
4099 | |||
4100 | return 0; | ||
4101 | } | ||
4102 | EXPORT_SYMBOL(omapdss_dsi_configure_pins); | ||
4103 | |||
3978 | int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) | 4104 | int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) |
3979 | { | 4105 | { |
3980 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4106 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
@@ -3999,6 +4125,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) | |||
3999 | break; | 4125 | break; |
4000 | default: | 4126 | default: |
4001 | BUG(); | 4127 | BUG(); |
4128 | return -EINVAL; | ||
4002 | }; | 4129 | }; |
4003 | 4130 | ||
4004 | dsi_if_enable(dsidev, false); | 4131 | dsi_if_enable(dsidev, false); |
@@ -4183,10 +4310,6 @@ static void dsi_framedone_irq_callback(void *data, u32 mask) | |||
4183 | __cancel_delayed_work(&dsi->framedone_timeout_work); | 4310 | __cancel_delayed_work(&dsi->framedone_timeout_work); |
4184 | 4311 | ||
4185 | dsi_handle_framedone(dsidev, 0); | 4312 | dsi_handle_framedone(dsidev, 0); |
4186 | |||
4187 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC | ||
4188 | dispc_fake_vsync_irq(); | ||
4189 | #endif | ||
4190 | } | 4313 | } |
4191 | 4314 | ||
4192 | int omap_dsi_update(struct omap_dss_device *dssdev, int channel, | 4315 | int omap_dsi_update(struct omap_dss_device *dssdev, int channel, |
@@ -4250,13 +4373,12 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
4250 | dispc_mgr_enable_stallmode(dssdev->manager->id, true); | 4373 | dispc_mgr_enable_stallmode(dssdev->manager->id, true); |
4251 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); | 4374 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); |
4252 | 4375 | ||
4253 | dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); | 4376 | dss_mgr_set_timings(dssdev->manager, &timings); |
4254 | } else { | 4377 | } else { |
4255 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); | 4378 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); |
4256 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); | 4379 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); |
4257 | 4380 | ||
4258 | dispc_mgr_set_lcd_timings(dssdev->manager->id, | 4381 | dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); |
4259 | &dssdev->panel.timings); | ||
4260 | } | 4382 | } |
4261 | 4383 | ||
4262 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, | 4384 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, |
@@ -4285,13 +4407,11 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
4285 | struct dsi_clock_info cinfo; | 4407 | struct dsi_clock_info cinfo; |
4286 | int r; | 4408 | int r; |
4287 | 4409 | ||
4288 | /* we always use DSS_CLK_SYSCK as input clock */ | ||
4289 | cinfo.use_sys_clk = true; | ||
4290 | cinfo.regn = dssdev->clocks.dsi.regn; | 4410 | cinfo.regn = dssdev->clocks.dsi.regn; |
4291 | cinfo.regm = dssdev->clocks.dsi.regm; | 4411 | cinfo.regm = dssdev->clocks.dsi.regm; |
4292 | cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; | 4412 | cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; |
4293 | cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; | 4413 | cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; |
4294 | r = dsi_calc_clock_rates(dssdev, &cinfo); | 4414 | r = dsi_calc_clock_rates(dsidev, &cinfo); |
4295 | if (r) { | 4415 | if (r) { |
4296 | DSSERR("Failed to calc dsi clocks\n"); | 4416 | DSSERR("Failed to calc dsi clocks\n"); |
4297 | return r; | 4417 | return r; |
@@ -4336,15 +4456,9 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
4336 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | 4456 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) |
4337 | { | 4457 | { |
4338 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4458 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4339 | int dsi_module = dsi_get_dsidev_id(dsidev); | 4459 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4340 | int r; | 4460 | int r; |
4341 | 4461 | ||
4342 | r = dsi_parse_lane_config(dssdev); | ||
4343 | if (r) { | ||
4344 | DSSERR("illegal lane config"); | ||
4345 | goto err0; | ||
4346 | } | ||
4347 | |||
4348 | r = dsi_pll_init(dsidev, true, true); | 4462 | r = dsi_pll_init(dsidev, true, true); |
4349 | if (r) | 4463 | if (r) |
4350 | goto err0; | 4464 | goto err0; |
@@ -4354,7 +4468,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
4354 | goto err1; | 4468 | goto err1; |
4355 | 4469 | ||
4356 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); | 4470 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
4357 | dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src); | 4471 | dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); |
4358 | dss_select_lcd_clk_source(dssdev->manager->id, | 4472 | dss_select_lcd_clk_source(dssdev->manager->id, |
4359 | dssdev->clocks.dispc.channel.lcd_clk_src); | 4473 | dssdev->clocks.dispc.channel.lcd_clk_src); |
4360 | 4474 | ||
@@ -4393,7 +4507,7 @@ err3: | |||
4393 | dsi_cio_uninit(dssdev); | 4507 | dsi_cio_uninit(dssdev); |
4394 | err2: | 4508 | err2: |
4395 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | 4509 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
4396 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | 4510 | dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); |
4397 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); | 4511 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); |
4398 | 4512 | ||
4399 | err1: | 4513 | err1: |
@@ -4407,7 +4521,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | |||
4407 | { | 4521 | { |
4408 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4522 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4409 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4523 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4410 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
4411 | 4524 | ||
4412 | if (enter_ulps && !dsi->ulps_enabled) | 4525 | if (enter_ulps && !dsi->ulps_enabled) |
4413 | dsi_enter_ulps(dsidev); | 4526 | dsi_enter_ulps(dsidev); |
@@ -4420,7 +4533,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | |||
4420 | dsi_vc_enable(dsidev, 3, 0); | 4533 | dsi_vc_enable(dsidev, 3, 0); |
4421 | 4534 | ||
4422 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | 4535 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
4423 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | 4536 | dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); |
4424 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); | 4537 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); |
4425 | dsi_cio_uninit(dssdev); | 4538 | dsi_cio_uninit(dssdev); |
4426 | dsi_pll_uninit(dsidev, disconnect_lanes); | 4539 | dsi_pll_uninit(dsidev, disconnect_lanes); |
@@ -4524,7 +4637,7 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
4524 | } | 4637 | } |
4525 | EXPORT_SYMBOL(omapdss_dsi_enable_te); | 4638 | EXPORT_SYMBOL(omapdss_dsi_enable_te); |
4526 | 4639 | ||
4527 | int dsi_init_display(struct omap_dss_device *dssdev) | 4640 | static int __init dsi_init_display(struct omap_dss_device *dssdev) |
4528 | { | 4641 | { |
4529 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4642 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4530 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4643 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
@@ -4677,13 +4790,39 @@ static void dsi_put_clocks(struct platform_device *dsidev) | |||
4677 | clk_put(dsi->sys_clk); | 4790 | clk_put(dsi->sys_clk); |
4678 | } | 4791 | } |
4679 | 4792 | ||
4793 | static void __init dsi_probe_pdata(struct platform_device *dsidev) | ||
4794 | { | ||
4795 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4796 | struct omap_dss_board_info *pdata = dsidev->dev.platform_data; | ||
4797 | int i, r; | ||
4798 | |||
4799 | for (i = 0; i < pdata->num_devices; ++i) { | ||
4800 | struct omap_dss_device *dssdev = pdata->devices[i]; | ||
4801 | |||
4802 | if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) | ||
4803 | continue; | ||
4804 | |||
4805 | if (dssdev->phy.dsi.module != dsi->module_id) | ||
4806 | continue; | ||
4807 | |||
4808 | r = dsi_init_display(dssdev); | ||
4809 | if (r) { | ||
4810 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
4811 | continue; | ||
4812 | } | ||
4813 | |||
4814 | r = omap_dss_register_device(dssdev, &dsidev->dev, i); | ||
4815 | if (r) | ||
4816 | DSSERR("device %s register failed: %d\n", | ||
4817 | dssdev->name, r); | ||
4818 | } | ||
4819 | } | ||
4820 | |||
4680 | /* DSI1 HW IP initialisation */ | 4821 | /* DSI1 HW IP initialisation */ |
4681 | static int omap_dsihw_probe(struct platform_device *dsidev) | 4822 | static int __init omap_dsihw_probe(struct platform_device *dsidev) |
4682 | { | 4823 | { |
4683 | struct omap_display_platform_data *dss_plat_data; | ||
4684 | struct omap_dss_board_info *board_info; | ||
4685 | u32 rev; | 4824 | u32 rev; |
4686 | int r, i, dsi_module = dsi_get_dsidev_id(dsidev); | 4825 | int r, i; |
4687 | struct resource *dsi_mem; | 4826 | struct resource *dsi_mem; |
4688 | struct dsi_data *dsi; | 4827 | struct dsi_data *dsi; |
4689 | 4828 | ||
@@ -4691,15 +4830,11 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
4691 | if (!dsi) | 4830 | if (!dsi) |
4692 | return -ENOMEM; | 4831 | return -ENOMEM; |
4693 | 4832 | ||
4833 | dsi->module_id = dsidev->id; | ||
4694 | dsi->pdev = dsidev; | 4834 | dsi->pdev = dsidev; |
4695 | dsi_pdev_map[dsi_module] = dsidev; | 4835 | dsi_pdev_map[dsi->module_id] = dsidev; |
4696 | dev_set_drvdata(&dsidev->dev, dsi); | 4836 | dev_set_drvdata(&dsidev->dev, dsi); |
4697 | 4837 | ||
4698 | dss_plat_data = dsidev->dev.platform_data; | ||
4699 | board_info = dss_plat_data->board_data; | ||
4700 | dsi->enable_pads = board_info->dsi_enable_pads; | ||
4701 | dsi->disable_pads = board_info->dsi_disable_pads; | ||
4702 | |||
4703 | spin_lock_init(&dsi->irq_lock); | 4838 | spin_lock_init(&dsi->irq_lock); |
4704 | spin_lock_init(&dsi->errors_lock); | 4839 | spin_lock_init(&dsi->errors_lock); |
4705 | dsi->errors = 0; | 4840 | dsi->errors = 0; |
@@ -4777,8 +4912,21 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
4777 | else | 4912 | else |
4778 | dsi->num_lanes_supported = 3; | 4913 | dsi->num_lanes_supported = 3; |
4779 | 4914 | ||
4915 | dsi_probe_pdata(dsidev); | ||
4916 | |||
4780 | dsi_runtime_put(dsidev); | 4917 | dsi_runtime_put(dsidev); |
4781 | 4918 | ||
4919 | if (dsi->module_id == 0) | ||
4920 | dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs); | ||
4921 | else if (dsi->module_id == 1) | ||
4922 | dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs); | ||
4923 | |||
4924 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
4925 | if (dsi->module_id == 0) | ||
4926 | dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs); | ||
4927 | else if (dsi->module_id == 1) | ||
4928 | dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs); | ||
4929 | #endif | ||
4782 | return 0; | 4930 | return 0; |
4783 | 4931 | ||
4784 | err_runtime_get: | 4932 | err_runtime_get: |
@@ -4787,12 +4935,14 @@ err_runtime_get: | |||
4787 | return r; | 4935 | return r; |
4788 | } | 4936 | } |
4789 | 4937 | ||
4790 | static int omap_dsihw_remove(struct platform_device *dsidev) | 4938 | static int __exit omap_dsihw_remove(struct platform_device *dsidev) |
4791 | { | 4939 | { |
4792 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4940 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4793 | 4941 | ||
4794 | WARN_ON(dsi->scp_clk_refcount > 0); | 4942 | WARN_ON(dsi->scp_clk_refcount > 0); |
4795 | 4943 | ||
4944 | omap_dss_unregister_child_devices(&dsidev->dev); | ||
4945 | |||
4796 | pm_runtime_disable(&dsidev->dev); | 4946 | pm_runtime_disable(&dsidev->dev); |
4797 | 4947 | ||
4798 | dsi_put_clocks(dsidev); | 4948 | dsi_put_clocks(dsidev); |
@@ -4813,7 +4963,6 @@ static int omap_dsihw_remove(struct platform_device *dsidev) | |||
4813 | static int dsi_runtime_suspend(struct device *dev) | 4963 | static int dsi_runtime_suspend(struct device *dev) |
4814 | { | 4964 | { |
4815 | dispc_runtime_put(); | 4965 | dispc_runtime_put(); |
4816 | dss_runtime_put(); | ||
4817 | 4966 | ||
4818 | return 0; | 4967 | return 0; |
4819 | } | 4968 | } |
@@ -4822,20 +4971,11 @@ static int dsi_runtime_resume(struct device *dev) | |||
4822 | { | 4971 | { |
4823 | int r; | 4972 | int r; |
4824 | 4973 | ||
4825 | r = dss_runtime_get(); | ||
4826 | if (r) | ||
4827 | goto err_get_dss; | ||
4828 | |||
4829 | r = dispc_runtime_get(); | 4974 | r = dispc_runtime_get(); |
4830 | if (r) | 4975 | if (r) |
4831 | goto err_get_dispc; | 4976 | return r; |
4832 | 4977 | ||
4833 | return 0; | 4978 | return 0; |
4834 | |||
4835 | err_get_dispc: | ||
4836 | dss_runtime_put(); | ||
4837 | err_get_dss: | ||
4838 | return r; | ||
4839 | } | 4979 | } |
4840 | 4980 | ||
4841 | static const struct dev_pm_ops dsi_pm_ops = { | 4981 | static const struct dev_pm_ops dsi_pm_ops = { |
@@ -4844,8 +4984,7 @@ static const struct dev_pm_ops dsi_pm_ops = { | |||
4844 | }; | 4984 | }; |
4845 | 4985 | ||
4846 | static struct platform_driver omap_dsihw_driver = { | 4986 | static struct platform_driver omap_dsihw_driver = { |
4847 | .probe = omap_dsihw_probe, | 4987 | .remove = __exit_p(omap_dsihw_remove), |
4848 | .remove = omap_dsihw_remove, | ||
4849 | .driver = { | 4988 | .driver = { |
4850 | .name = "omapdss_dsi", | 4989 | .name = "omapdss_dsi", |
4851 | .owner = THIS_MODULE, | 4990 | .owner = THIS_MODULE, |
@@ -4853,12 +4992,12 @@ static struct platform_driver omap_dsihw_driver = { | |||
4853 | }, | 4992 | }, |
4854 | }; | 4993 | }; |
4855 | 4994 | ||
4856 | int dsi_init_platform_driver(void) | 4995 | int __init dsi_init_platform_driver(void) |
4857 | { | 4996 | { |
4858 | return platform_driver_register(&omap_dsihw_driver); | 4997 | return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe); |
4859 | } | 4998 | } |
4860 | 4999 | ||
4861 | void dsi_uninit_platform_driver(void) | 5000 | void __exit dsi_uninit_platform_driver(void) |
4862 | { | 5001 | { |
4863 | return platform_driver_unregister(&omap_dsihw_driver); | 5002 | platform_driver_unregister(&omap_dsihw_driver); |
4864 | } | 5003 | } |