diff options
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 296 |
1 files changed, 179 insertions, 117 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 345757cfcbee..7adbbeb84334 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/debugfs.h> | 38 | #include <linux/debugfs.h> |
39 | #include <linux/pm_runtime.h> | ||
39 | 40 | ||
40 | #include <video/omapdss.h> | 41 | #include <video/omapdss.h> |
41 | #include <plat/clock.h> | 42 | #include <plat/clock.h> |
@@ -267,8 +268,12 @@ struct dsi_isr_tables { | |||
267 | struct dsi_data { | 268 | struct dsi_data { |
268 | struct platform_device *pdev; | 269 | struct platform_device *pdev; |
269 | void __iomem *base; | 270 | void __iomem *base; |
271 | |||
270 | int irq; | 272 | int irq; |
271 | 273 | ||
274 | struct clk *dss_clk; | ||
275 | struct clk *sys_clk; | ||
276 | |||
272 | void (*dsi_mux_pads)(bool enable); | 277 | void (*dsi_mux_pads)(bool enable); |
273 | 278 | ||
274 | struct dsi_clock_info current_cinfo; | 279 | struct dsi_clock_info current_cinfo; |
@@ -389,15 +394,6 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev, | |||
389 | return __raw_readl(dsi->base + idx.idx); | 394 | return __raw_readl(dsi->base + idx.idx); |
390 | } | 395 | } |
391 | 396 | ||
392 | |||
393 | void dsi_save_context(void) | ||
394 | { | ||
395 | } | ||
396 | |||
397 | void dsi_restore_context(void) | ||
398 | { | ||
399 | } | ||
400 | |||
401 | void dsi_bus_lock(struct omap_dss_device *dssdev) | 397 | void dsi_bus_lock(struct omap_dss_device *dssdev) |
402 | { | 398 | { |
403 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 399 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
@@ -493,9 +489,18 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name) | |||
493 | total_bytes * 1000 / total_us); | 489 | total_bytes * 1000 / total_us); |
494 | } | 490 | } |
495 | #else | 491 | #else |
496 | #define dsi_perf_mark_setup(x) | 492 | static inline void dsi_perf_mark_setup(struct platform_device *dsidev) |
497 | #define dsi_perf_mark_start(x) | 493 | { |
498 | #define dsi_perf_show(x, y) | 494 | } |
495 | |||
496 | static inline void dsi_perf_mark_start(struct platform_device *dsidev) | ||
497 | { | ||
498 | } | ||
499 | |||
500 | static inline void dsi_perf_show(struct platform_device *dsidev, | ||
501 | const char *name) | ||
502 | { | ||
503 | } | ||
499 | #endif | 504 | #endif |
500 | 505 | ||
501 | static void print_irq_status(u32 status) | 506 | static void print_irq_status(u32 status) |
@@ -1039,13 +1044,27 @@ static u32 dsi_get_errors(struct platform_device *dsidev) | |||
1039 | return e; | 1044 | return e; |
1040 | } | 1045 | } |
1041 | 1046 | ||
1042 | /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ | 1047 | int dsi_runtime_get(struct platform_device *dsidev) |
1043 | static inline void enable_clocks(bool enable) | ||
1044 | { | 1048 | { |
1045 | if (enable) | 1049 | int r; |
1046 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); | 1050 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1047 | else | 1051 | |
1048 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | 1052 | DSSDBG("dsi_runtime_get\n"); |
1053 | |||
1054 | r = pm_runtime_get_sync(&dsi->pdev->dev); | ||
1055 | WARN_ON(r < 0); | ||
1056 | return r < 0 ? r : 0; | ||
1057 | } | ||
1058 | |||
1059 | void dsi_runtime_put(struct platform_device *dsidev) | ||
1060 | { | ||
1061 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1062 | int r; | ||
1063 | |||
1064 | DSSDBG("dsi_runtime_put\n"); | ||
1065 | |||
1066 | r = pm_runtime_put(&dsi->pdev->dev); | ||
1067 | WARN_ON(r < 0); | ||
1049 | } | 1068 | } |
1050 | 1069 | ||
1051 | /* source clock for DSI PLL. this could also be PCLKFREE */ | 1070 | /* source clock for DSI PLL. this could also be PCLKFREE */ |
@@ -1055,9 +1074,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev, | |||
1055 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1074 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1056 | 1075 | ||
1057 | if (enable) | 1076 | if (enable) |
1058 | dss_clk_enable(DSS_CLK_SYSCK); | 1077 | clk_enable(dsi->sys_clk); |
1059 | else | 1078 | else |
1060 | dss_clk_disable(DSS_CLK_SYSCK); | 1079 | clk_disable(dsi->sys_clk); |
1061 | 1080 | ||
1062 | if (enable && dsi->pll_locked) { | 1081 | if (enable && dsi->pll_locked) { |
1063 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) | 1082 | if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) |
@@ -1150,10 +1169,11 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev) | |||
1150 | { | 1169 | { |
1151 | unsigned long r; | 1170 | unsigned long r; |
1152 | int dsi_module = dsi_get_dsidev_id(dsidev); | 1171 | int dsi_module = dsi_get_dsidev_id(dsidev); |
1172 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1153 | 1173 | ||
1154 | if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { | 1174 | if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { |
1155 | /* DSI FCLK source is DSS_CLK_FCK */ | 1175 | /* DSI FCLK source is DSS_CLK_FCK */ |
1156 | r = dss_clk_get_rate(DSS_CLK_FCK); | 1176 | r = clk_get_rate(dsi->dss_clk); |
1157 | } else { | 1177 | } else { |
1158 | /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ | 1178 | /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ |
1159 | r = dsi_get_pll_hsdiv_dsi_rate(dsidev); | 1179 | r = dsi_get_pll_hsdiv_dsi_rate(dsidev); |
@@ -1262,7 +1282,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
1262 | return -EINVAL; | 1282 | return -EINVAL; |
1263 | 1283 | ||
1264 | if (cinfo->use_sys_clk) { | 1284 | if (cinfo->use_sys_clk) { |
1265 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); | 1285 | cinfo->clkin = clk_get_rate(dsi->sys_clk); |
1266 | /* XXX it is unclear if highfreq should be used | 1286 | /* XXX it is unclear if highfreq should be used |
1267 | * with DSS_SYS_CLK source also */ | 1287 | * with DSS_SYS_CLK source also */ |
1268 | cinfo->highfreq = 0; | 1288 | cinfo->highfreq = 0; |
@@ -1311,7 +1331,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, | |||
1311 | int match = 0; | 1331 | int match = 0; |
1312 | unsigned long dss_sys_clk, max_dss_fck; | 1332 | unsigned long dss_sys_clk, max_dss_fck; |
1313 | 1333 | ||
1314 | dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); | 1334 | dss_sys_clk = clk_get_rate(dsi->sys_clk); |
1315 | 1335 | ||
1316 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | 1336 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
1317 | 1337 | ||
@@ -1601,7 +1621,6 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, | |||
1601 | dsi->vdds_dsi_reg = vdds_dsi; | 1621 | dsi->vdds_dsi_reg = vdds_dsi; |
1602 | } | 1622 | } |
1603 | 1623 | ||
1604 | enable_clocks(1); | ||
1605 | dsi_enable_pll_clock(dsidev, 1); | 1624 | dsi_enable_pll_clock(dsidev, 1); |
1606 | /* | 1625 | /* |
1607 | * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4. | 1626 | * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4. |
@@ -1653,7 +1672,6 @@ err1: | |||
1653 | } | 1672 | } |
1654 | err0: | 1673 | err0: |
1655 | dsi_disable_scp_clk(dsidev); | 1674 | dsi_disable_scp_clk(dsidev); |
1656 | enable_clocks(0); | ||
1657 | dsi_enable_pll_clock(dsidev, 0); | 1675 | dsi_enable_pll_clock(dsidev, 0); |
1658 | return r; | 1676 | return r; |
1659 | } | 1677 | } |
@@ -1671,7 +1689,6 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes) | |||
1671 | } | 1689 | } |
1672 | 1690 | ||
1673 | dsi_disable_scp_clk(dsidev); | 1691 | dsi_disable_scp_clk(dsidev); |
1674 | enable_clocks(0); | ||
1675 | dsi_enable_pll_clock(dsidev, 0); | 1692 | dsi_enable_pll_clock(dsidev, 0); |
1676 | 1693 | ||
1677 | DSSDBG("PLL uninit done\n"); | 1694 | DSSDBG("PLL uninit done\n"); |
@@ -1688,7 +1705,8 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, | |||
1688 | dispc_clk_src = dss_get_dispc_clk_source(); | 1705 | dispc_clk_src = dss_get_dispc_clk_source(); |
1689 | dsi_clk_src = dss_get_dsi_clk_source(dsi_module); | 1706 | dsi_clk_src = dss_get_dsi_clk_source(dsi_module); |
1690 | 1707 | ||
1691 | enable_clocks(1); | 1708 | if (dsi_runtime_get(dsidev)) |
1709 | return; | ||
1692 | 1710 | ||
1693 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); | 1711 | seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); |
1694 | 1712 | ||
@@ -1731,7 +1749,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, | |||
1731 | 1749 | ||
1732 | seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); | 1750 | seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); |
1733 | 1751 | ||
1734 | enable_clocks(0); | 1752 | dsi_runtime_put(dsidev); |
1735 | } | 1753 | } |
1736 | 1754 | ||
1737 | void dsi_dump_clocks(struct seq_file *s) | 1755 | void dsi_dump_clocks(struct seq_file *s) |
@@ -1873,7 +1891,8 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev, | |||
1873 | { | 1891 | { |
1874 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r)) | 1892 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r)) |
1875 | 1893 | ||
1876 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); | 1894 | if (dsi_runtime_get(dsidev)) |
1895 | return; | ||
1877 | dsi_enable_scp_clk(dsidev); | 1896 | dsi_enable_scp_clk(dsidev); |
1878 | 1897 | ||
1879 | DUMPREG(DSI_REVISION); | 1898 | DUMPREG(DSI_REVISION); |
@@ -1947,7 +1966,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev, | |||
1947 | DUMPREG(DSI_PLL_CONFIGURATION2); | 1966 | DUMPREG(DSI_PLL_CONFIGURATION2); |
1948 | 1967 | ||
1949 | dsi_disable_scp_clk(dsidev); | 1968 | dsi_disable_scp_clk(dsidev); |
1950 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | 1969 | dsi_runtime_put(dsidev); |
1951 | #undef DUMPREG | 1970 | #undef DUMPREG |
1952 | } | 1971 | } |
1953 | 1972 | ||
@@ -2463,28 +2482,6 @@ static void dsi_cio_uninit(struct platform_device *dsidev) | |||
2463 | dsi->dsi_mux_pads(false); | 2482 | dsi->dsi_mux_pads(false); |
2464 | } | 2483 | } |
2465 | 2484 | ||
2466 | static int _dsi_wait_reset(struct platform_device *dsidev) | ||
2467 | { | ||
2468 | int t = 0; | ||
2469 | |||
2470 | while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) { | ||
2471 | if (++t > 5) { | ||
2472 | DSSERR("soft reset failed\n"); | ||
2473 | return -ENODEV; | ||
2474 | } | ||
2475 | udelay(1); | ||
2476 | } | ||
2477 | |||
2478 | return 0; | ||
2479 | } | ||
2480 | |||
2481 | static int _dsi_reset(struct platform_device *dsidev) | ||
2482 | { | ||
2483 | /* Soft reset */ | ||
2484 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1); | ||
2485 | return _dsi_wait_reset(dsidev); | ||
2486 | } | ||
2487 | |||
2488 | static void dsi_config_tx_fifo(struct platform_device *dsidev, | 2485 | static void dsi_config_tx_fifo(struct platform_device *dsidev, |
2489 | enum fifo_size size1, enum fifo_size size2, | 2486 | enum fifo_size size1, enum fifo_size size2, |
2490 | enum fifo_size size3, enum fifo_size size4) | 2487 | enum fifo_size size3, enum fifo_size size4) |
@@ -3386,6 +3383,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev) | |||
3386 | dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, | 3383 | dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, |
3387 | DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); | 3384 | DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); |
3388 | 3385 | ||
3386 | /* Reset LANEx_ULPS_SIG2 */ | ||
3387 | REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2), | ||
3388 | 7, 5); | ||
3389 | |||
3389 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); | 3390 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); |
3390 | 3391 | ||
3391 | dsi_if_enable(dsidev, false); | 3392 | dsi_if_enable(dsidev, false); |
@@ -4198,22 +4199,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | |||
4198 | dsi_pll_uninit(dsidev, disconnect_lanes); | 4199 | dsi_pll_uninit(dsidev, disconnect_lanes); |
4199 | } | 4200 | } |
4200 | 4201 | ||
4201 | static int dsi_core_init(struct platform_device *dsidev) | ||
4202 | { | ||
4203 | /* Autoidle */ | ||
4204 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0); | ||
4205 | |||
4206 | /* ENWAKEUP */ | ||
4207 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2); | ||
4208 | |||
4209 | /* SIDLEMODE smart-idle */ | ||
4210 | REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3); | ||
4211 | |||
4212 | _dsi_initialize_irq(dsidev); | ||
4213 | |||
4214 | return 0; | ||
4215 | } | ||
4216 | |||
4217 | int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | 4202 | int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) |
4218 | { | 4203 | { |
4219 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4204 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
@@ -4229,37 +4214,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
4229 | r = omap_dss_start_device(dssdev); | 4214 | r = omap_dss_start_device(dssdev); |
4230 | if (r) { | 4215 | if (r) { |
4231 | DSSERR("failed to start device\n"); | 4216 | DSSERR("failed to start device\n"); |
4232 | goto err0; | 4217 | goto err_start_dev; |
4233 | } | 4218 | } |
4234 | 4219 | ||
4235 | enable_clocks(1); | 4220 | r = dsi_runtime_get(dsidev); |
4236 | dsi_enable_pll_clock(dsidev, 1); | ||
4237 | |||
4238 | r = _dsi_reset(dsidev); | ||
4239 | if (r) | 4221 | if (r) |
4240 | goto err1; | 4222 | goto err_get_dsi; |
4241 | 4223 | ||
4242 | dsi_core_init(dsidev); | 4224 | dsi_enable_pll_clock(dsidev, 1); |
4225 | |||
4226 | _dsi_initialize_irq(dsidev); | ||
4243 | 4227 | ||
4244 | r = dsi_display_init_dispc(dssdev); | 4228 | r = dsi_display_init_dispc(dssdev); |
4245 | if (r) | 4229 | if (r) |
4246 | goto err1; | 4230 | goto err_init_dispc; |
4247 | 4231 | ||
4248 | r = dsi_display_init_dsi(dssdev); | 4232 | r = dsi_display_init_dsi(dssdev); |
4249 | if (r) | 4233 | if (r) |
4250 | goto err2; | 4234 | goto err_init_dsi; |
4251 | 4235 | ||
4252 | mutex_unlock(&dsi->lock); | 4236 | mutex_unlock(&dsi->lock); |
4253 | 4237 | ||
4254 | return 0; | 4238 | return 0; |
4255 | 4239 | ||
4256 | err2: | 4240 | err_init_dsi: |
4257 | dsi_display_uninit_dispc(dssdev); | 4241 | dsi_display_uninit_dispc(dssdev); |
4258 | err1: | 4242 | err_init_dispc: |
4259 | enable_clocks(0); | ||
4260 | dsi_enable_pll_clock(dsidev, 0); | 4243 | dsi_enable_pll_clock(dsidev, 0); |
4244 | dsi_runtime_put(dsidev); | ||
4245 | err_get_dsi: | ||
4261 | omap_dss_stop_device(dssdev); | 4246 | omap_dss_stop_device(dssdev); |
4262 | err0: | 4247 | err_start_dev: |
4263 | mutex_unlock(&dsi->lock); | 4248 | mutex_unlock(&dsi->lock); |
4264 | DSSDBG("dsi_display_enable FAILED\n"); | 4249 | DSSDBG("dsi_display_enable FAILED\n"); |
4265 | return r; | 4250 | return r; |
@@ -4278,11 +4263,16 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, | |||
4278 | 4263 | ||
4279 | mutex_lock(&dsi->lock); | 4264 | mutex_lock(&dsi->lock); |
4280 | 4265 | ||
4266 | dsi_sync_vc(dsidev, 0); | ||
4267 | dsi_sync_vc(dsidev, 1); | ||
4268 | dsi_sync_vc(dsidev, 2); | ||
4269 | dsi_sync_vc(dsidev, 3); | ||
4270 | |||
4281 | dsi_display_uninit_dispc(dssdev); | 4271 | dsi_display_uninit_dispc(dssdev); |
4282 | 4272 | ||
4283 | dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); | 4273 | dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); |
4284 | 4274 | ||
4285 | enable_clocks(0); | 4275 | dsi_runtime_put(dsidev); |
4286 | dsi_enable_pll_clock(dsidev, 0); | 4276 | dsi_enable_pll_clock(dsidev, 0); |
4287 | 4277 | ||
4288 | omap_dss_stop_device(dssdev); | 4278 | omap_dss_stop_device(dssdev); |
@@ -4302,16 +4292,11 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
4302 | EXPORT_SYMBOL(omapdss_dsi_enable_te); | 4292 | EXPORT_SYMBOL(omapdss_dsi_enable_te); |
4303 | 4293 | ||
4304 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | 4294 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, |
4305 | u32 fifo_size, enum omap_burst_size *burst_size, | 4295 | u32 fifo_size, u32 burst_size, |
4306 | u32 *fifo_low, u32 *fifo_high) | 4296 | u32 *fifo_low, u32 *fifo_high) |
4307 | { | 4297 | { |
4308 | unsigned burst_size_bytes; | 4298 | *fifo_high = fifo_size - burst_size; |
4309 | 4299 | *fifo_low = fifo_size - burst_size * 2; | |
4310 | *burst_size = OMAP_DSS_BURST_16x32; | ||
4311 | burst_size_bytes = 16 * 32 / 8; | ||
4312 | |||
4313 | *fifo_high = fifo_size - burst_size_bytes; | ||
4314 | *fifo_low = fifo_size - burst_size_bytes * 2; | ||
4315 | } | 4300 | } |
4316 | 4301 | ||
4317 | int dsi_init_display(struct omap_dss_device *dssdev) | 4302 | int dsi_init_display(struct omap_dss_device *dssdev) |
@@ -4437,7 +4422,47 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev) | |||
4437 | dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); | 4422 | dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); |
4438 | } | 4423 | } |
4439 | 4424 | ||
4440 | static int dsi_init(struct platform_device *dsidev) | 4425 | static int dsi_get_clocks(struct platform_device *dsidev) |
4426 | { | ||
4427 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4428 | struct clk *clk; | ||
4429 | |||
4430 | clk = clk_get(&dsidev->dev, "fck"); | ||
4431 | if (IS_ERR(clk)) { | ||
4432 | DSSERR("can't get fck\n"); | ||
4433 | return PTR_ERR(clk); | ||
4434 | } | ||
4435 | |||
4436 | dsi->dss_clk = clk; | ||
4437 | |||
4438 | if (cpu_is_omap34xx() || cpu_is_omap3630()) | ||
4439 | clk = clk_get(&dsidev->dev, "dss2_alwon_fck"); | ||
4440 | else | ||
4441 | clk = clk_get(&dsidev->dev, "sys_clk"); | ||
4442 | if (IS_ERR(clk)) { | ||
4443 | DSSERR("can't get sys_clk\n"); | ||
4444 | clk_put(dsi->dss_clk); | ||
4445 | dsi->dss_clk = NULL; | ||
4446 | return PTR_ERR(clk); | ||
4447 | } | ||
4448 | |||
4449 | dsi->sys_clk = clk; | ||
4450 | |||
4451 | return 0; | ||
4452 | } | ||
4453 | |||
4454 | static void dsi_put_clocks(struct platform_device *dsidev) | ||
4455 | { | ||
4456 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4457 | |||
4458 | if (dsi->dss_clk) | ||
4459 | clk_put(dsi->dss_clk); | ||
4460 | if (dsi->sys_clk) | ||
4461 | clk_put(dsi->sys_clk); | ||
4462 | } | ||
4463 | |||
4464 | /* DSI1 HW IP initialisation */ | ||
4465 | static int omap_dsi1hw_probe(struct platform_device *dsidev) | ||
4441 | { | 4466 | { |
4442 | struct omap_display_platform_data *dss_plat_data; | 4467 | struct omap_display_platform_data *dss_plat_data; |
4443 | struct omap_dss_board_info *board_info; | 4468 | struct omap_dss_board_info *board_info; |
@@ -4449,7 +4474,7 @@ static int dsi_init(struct platform_device *dsidev) | |||
4449 | dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); | 4474 | dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); |
4450 | if (!dsi) { | 4475 | if (!dsi) { |
4451 | r = -ENOMEM; | 4476 | r = -ENOMEM; |
4452 | goto err0; | 4477 | goto err_alloc; |
4453 | } | 4478 | } |
4454 | 4479 | ||
4455 | dsi->pdev = dsidev; | 4480 | dsi->pdev = dsidev; |
@@ -4472,6 +4497,12 @@ static int dsi_init(struct platform_device *dsidev) | |||
4472 | mutex_init(&dsi->lock); | 4497 | mutex_init(&dsi->lock); |
4473 | sema_init(&dsi->bus_lock, 1); | 4498 | sema_init(&dsi->bus_lock, 1); |
4474 | 4499 | ||
4500 | r = dsi_get_clocks(dsidev); | ||
4501 | if (r) | ||
4502 | goto err_get_clk; | ||
4503 | |||
4504 | pm_runtime_enable(&dsidev->dev); | ||
4505 | |||
4475 | INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, | 4506 | INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, |
4476 | dsi_framedone_timeout_work_callback); | 4507 | dsi_framedone_timeout_work_callback); |
4477 | 4508 | ||
@@ -4484,26 +4515,26 @@ static int dsi_init(struct platform_device *dsidev) | |||
4484 | if (!dsi_mem) { | 4515 | if (!dsi_mem) { |
4485 | DSSERR("can't get IORESOURCE_MEM DSI\n"); | 4516 | DSSERR("can't get IORESOURCE_MEM DSI\n"); |
4486 | r = -EINVAL; | 4517 | r = -EINVAL; |
4487 | goto err1; | 4518 | goto err_ioremap; |
4488 | } | 4519 | } |
4489 | dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); | 4520 | dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); |
4490 | if (!dsi->base) { | 4521 | if (!dsi->base) { |
4491 | DSSERR("can't ioremap DSI\n"); | 4522 | DSSERR("can't ioremap DSI\n"); |
4492 | r = -ENOMEM; | 4523 | r = -ENOMEM; |
4493 | goto err1; | 4524 | goto err_ioremap; |
4494 | } | 4525 | } |
4495 | dsi->irq = platform_get_irq(dsi->pdev, 0); | 4526 | dsi->irq = platform_get_irq(dsi->pdev, 0); |
4496 | if (dsi->irq < 0) { | 4527 | if (dsi->irq < 0) { |
4497 | DSSERR("platform_get_irq failed\n"); | 4528 | DSSERR("platform_get_irq failed\n"); |
4498 | r = -ENODEV; | 4529 | r = -ENODEV; |
4499 | goto err2; | 4530 | goto err_get_irq; |
4500 | } | 4531 | } |
4501 | 4532 | ||
4502 | r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, | 4533 | r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, |
4503 | dev_name(&dsidev->dev), dsi->pdev); | 4534 | dev_name(&dsidev->dev), dsi->pdev); |
4504 | if (r < 0) { | 4535 | if (r < 0) { |
4505 | DSSERR("request_irq failed\n"); | 4536 | DSSERR("request_irq failed\n"); |
4506 | goto err2; | 4537 | goto err_get_irq; |
4507 | } | 4538 | } |
4508 | 4539 | ||
4509 | /* DSI VCs initialization */ | 4540 | /* DSI VCs initialization */ |
@@ -4515,7 +4546,9 @@ static int dsi_init(struct platform_device *dsidev) | |||
4515 | 4546 | ||
4516 | dsi_calc_clock_param_ranges(dsidev); | 4547 | dsi_calc_clock_param_ranges(dsidev); |
4517 | 4548 | ||
4518 | enable_clocks(1); | 4549 | r = dsi_runtime_get(dsidev); |
4550 | if (r) | ||
4551 | goto err_get_dsi; | ||
4519 | 4552 | ||
4520 | rev = dsi_read_reg(dsidev, DSI_REVISION); | 4553 | rev = dsi_read_reg(dsidev, DSI_REVISION); |
4521 | dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", | 4554 | dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", |
@@ -4523,21 +4556,32 @@ static int dsi_init(struct platform_device *dsidev) | |||
4523 | 4556 | ||
4524 | dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); | 4557 | dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); |
4525 | 4558 | ||
4526 | enable_clocks(0); | 4559 | dsi_runtime_put(dsidev); |
4527 | 4560 | ||
4528 | return 0; | 4561 | return 0; |
4529 | err2: | 4562 | |
4563 | err_get_dsi: | ||
4564 | free_irq(dsi->irq, dsi->pdev); | ||
4565 | err_get_irq: | ||
4530 | iounmap(dsi->base); | 4566 | iounmap(dsi->base); |
4531 | err1: | 4567 | err_ioremap: |
4568 | pm_runtime_disable(&dsidev->dev); | ||
4569 | err_get_clk: | ||
4532 | kfree(dsi); | 4570 | kfree(dsi); |
4533 | err0: | 4571 | err_alloc: |
4534 | return r; | 4572 | return r; |
4535 | } | 4573 | } |
4536 | 4574 | ||
4537 | static void dsi_exit(struct platform_device *dsidev) | 4575 | static int omap_dsi1hw_remove(struct platform_device *dsidev) |
4538 | { | 4576 | { |
4539 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4577 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4540 | 4578 | ||
4579 | WARN_ON(dsi->scp_clk_refcount > 0); | ||
4580 | |||
4581 | pm_runtime_disable(&dsidev->dev); | ||
4582 | |||
4583 | dsi_put_clocks(dsidev); | ||
4584 | |||
4541 | if (dsi->vdds_dsi_reg != NULL) { | 4585 | if (dsi->vdds_dsi_reg != NULL) { |
4542 | if (dsi->vdds_dsi_enabled) { | 4586 | if (dsi->vdds_dsi_enabled) { |
4543 | regulator_disable(dsi->vdds_dsi_reg); | 4587 | regulator_disable(dsi->vdds_dsi_reg); |
@@ -4553,38 +4597,56 @@ static void dsi_exit(struct platform_device *dsidev) | |||
4553 | 4597 | ||
4554 | kfree(dsi); | 4598 | kfree(dsi); |
4555 | 4599 | ||
4556 | DSSDBG("omap_dsi_exit\n"); | 4600 | return 0; |
4557 | } | 4601 | } |
4558 | 4602 | ||
4559 | /* DSI1 HW IP initialisation */ | 4603 | static int dsi_runtime_suspend(struct device *dev) |
4560 | static int omap_dsi1hw_probe(struct platform_device *dsidev) | ||
4561 | { | 4604 | { |
4562 | int r; | 4605 | struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); |
4563 | 4606 | ||
4564 | r = dsi_init(dsidev); | 4607 | clk_disable(dsi->dss_clk); |
4565 | if (r) { | 4608 | |
4566 | DSSERR("Failed to initialize DSI\n"); | 4609 | dispc_runtime_put(); |
4567 | goto err_dsi; | 4610 | dss_runtime_put(); |
4568 | } | 4611 | |
4569 | err_dsi: | 4612 | return 0; |
4570 | return r; | ||
4571 | } | 4613 | } |
4572 | 4614 | ||
4573 | static int omap_dsi1hw_remove(struct platform_device *dsidev) | 4615 | static int dsi_runtime_resume(struct device *dev) |
4574 | { | 4616 | { |
4575 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4617 | struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); |
4618 | int r; | ||
4619 | |||
4620 | r = dss_runtime_get(); | ||
4621 | if (r) | ||
4622 | goto err_get_dss; | ||
4623 | |||
4624 | r = dispc_runtime_get(); | ||
4625 | if (r) | ||
4626 | goto err_get_dispc; | ||
4627 | |||
4628 | clk_enable(dsi->dss_clk); | ||
4576 | 4629 | ||
4577 | dsi_exit(dsidev); | ||
4578 | WARN_ON(dsi->scp_clk_refcount > 0); | ||
4579 | return 0; | 4630 | return 0; |
4631 | |||
4632 | err_get_dispc: | ||
4633 | dss_runtime_put(); | ||
4634 | err_get_dss: | ||
4635 | return r; | ||
4580 | } | 4636 | } |
4581 | 4637 | ||
4638 | static const struct dev_pm_ops dsi_pm_ops = { | ||
4639 | .runtime_suspend = dsi_runtime_suspend, | ||
4640 | .runtime_resume = dsi_runtime_resume, | ||
4641 | }; | ||
4642 | |||
4582 | static struct platform_driver omap_dsi1hw_driver = { | 4643 | static struct platform_driver omap_dsi1hw_driver = { |
4583 | .probe = omap_dsi1hw_probe, | 4644 | .probe = omap_dsi1hw_probe, |
4584 | .remove = omap_dsi1hw_remove, | 4645 | .remove = omap_dsi1hw_remove, |
4585 | .driver = { | 4646 | .driver = { |
4586 | .name = "omapdss_dsi1", | 4647 | .name = "omapdss_dsi1", |
4587 | .owner = THIS_MODULE, | 4648 | .owner = THIS_MODULE, |
4649 | .pm = &dsi_pm_ops, | ||
4588 | }, | 4650 | }, |
4589 | }; | 4651 | }; |
4590 | 4652 | ||