diff options
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 277 |
1 files changed, 109 insertions, 168 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index b6a57bb7a61..345757cfcbe 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -36,7 +36,6 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/debugfs.h> -#include <linux/pm_runtime.h> #include <video/omapdss.h> #include <plat/clock.h> @@ -268,12 +267,8 @@ struct dsi_isr_tables { struct dsi_data { struct platform_device *pdev; void __iomem *base; - int irq; - struct clk *dss_clk; - struct clk *sys_clk; - void (*dsi_mux_pads)(bool enable); struct dsi_clock_info current_cinfo; @@ -394,6 +389,15 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev, return __raw_readl(dsi->base + idx.idx); } + +void dsi_save_context(void) +{ +} + +void dsi_restore_context(void) +{ +} + void dsi_bus_lock(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -489,18 +493,9 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name) total_bytes * 1000 / total_us); } #else -static inline void dsi_perf_mark_setup(struct platform_device *dsidev) -{ -} - -static inline void dsi_perf_mark_start(struct platform_device *dsidev) -{ -} - -static inline void dsi_perf_show(struct platform_device *dsidev, - const char *name) -{ -} +#define dsi_perf_mark_setup(x) +#define dsi_perf_mark_start(x) +#define dsi_perf_show(x, y) #endif static void print_irq_status(u32 status) @@ -1044,27 +1039,13 @@ static u32 dsi_get_errors(struct platform_device *dsidev) return e; } -int dsi_runtime_get(struct platform_device *dsidev) +/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ +static inline void enable_clocks(bool enable) { - int r; - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - - DSSDBG("dsi_runtime_get\n"); - - r = pm_runtime_get_sync(&dsi->pdev->dev); - WARN_ON(r < 0); - return r < 0 ? r : 0; -} - -void dsi_runtime_put(struct platform_device *dsidev) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - int r; - - DSSDBG("dsi_runtime_put\n"); - - r = pm_runtime_put(&dsi->pdev->dev); - WARN_ON(r < 0); + if (enable) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + else + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } /* source clock for DSI PLL. this could also be PCLKFREE */ @@ -1074,9 +1055,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev, struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); if (enable) - clk_enable(dsi->sys_clk); + dss_clk_enable(DSS_CLK_SYSCK); else - clk_disable(dsi->sys_clk); + dss_clk_disable(DSS_CLK_SYSCK); if (enable && dsi->pll_locked) { if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) @@ -1169,11 +1150,10 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev) { unsigned long r; int dsi_module = dsi_get_dsidev_id(dsidev); - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { /* DSI FCLK source is DSS_CLK_FCK */ - r = clk_get_rate(dsi->dss_clk); + r = dss_clk_get_rate(DSS_CLK_FCK); } else { /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ r = dsi_get_pll_hsdiv_dsi_rate(dsidev); @@ -1282,7 +1262,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, return -EINVAL; if (cinfo->use_sys_clk) { - cinfo->clkin = clk_get_rate(dsi->sys_clk); + cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); /* XXX it is unclear if highfreq should be used * with DSS_SYS_CLK source also */ cinfo->highfreq = 0; @@ -1331,7 +1311,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft, int match = 0; unsigned long dss_sys_clk, max_dss_fck; - dss_sys_clk = clk_get_rate(dsi->sys_clk); + dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); @@ -1621,6 +1601,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, dsi->vdds_dsi_reg = vdds_dsi; } + enable_clocks(1); dsi_enable_pll_clock(dsidev, 1); /* * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4. @@ -1672,6 +1653,7 @@ err1: } err0: dsi_disable_scp_clk(dsidev); + enable_clocks(0); dsi_enable_pll_clock(dsidev, 0); return r; } @@ -1689,6 +1671,7 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes) } dsi_disable_scp_clk(dsidev); + enable_clocks(0); dsi_enable_pll_clock(dsidev, 0); DSSDBG("PLL uninit done\n"); @@ -1705,8 +1688,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, dispc_clk_src = dss_get_dispc_clk_source(); dsi_clk_src = dss_get_dsi_clk_source(dsi_module); - if (dsi_runtime_get(dsidev)) - return; + enable_clocks(1); seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); @@ -1749,7 +1731,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); - dsi_runtime_put(dsidev); + enable_clocks(0); } void dsi_dump_clocks(struct seq_file *s) @@ -1891,8 +1873,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev, { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r)) - if (dsi_runtime_get(dsidev)) - return; + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); dsi_enable_scp_clk(dsidev); DUMPREG(DSI_REVISION); @@ -1966,7 +1947,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev, DUMPREG(DSI_PLL_CONFIGURATION2); dsi_disable_scp_clk(dsidev); - dsi_runtime_put(dsidev); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -2482,6 +2463,28 @@ static void dsi_cio_uninit(struct platform_device *dsidev) dsi->dsi_mux_pads(false); } +static int _dsi_wait_reset(struct platform_device *dsidev) +{ + int t = 0; + + while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) { + if (++t > 5) { + DSSERR("soft reset failed\n"); + return -ENODEV; + } + udelay(1); + } + + return 0; +} + +static int _dsi_reset(struct platform_device *dsidev) +{ + /* Soft reset */ + REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1); + return _dsi_wait_reset(dsidev); +} + static void dsi_config_tx_fifo(struct platform_device *dsidev, enum fifo_size size1, enum fifo_size size2, enum fifo_size size3, enum fifo_size size4) @@ -3383,10 +3386,6 @@ static int dsi_enter_ulps(struct platform_device *dsidev) dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); - /* Reset LANEx_ULPS_SIG2 */ - REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2), - 7, 5); - dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); dsi_if_enable(dsidev, false); @@ -4199,6 +4198,22 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, dsi_pll_uninit(dsidev, disconnect_lanes); } +static int dsi_core_init(struct platform_device *dsidev) +{ + /* Autoidle */ + REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0); + + /* ENWAKEUP */ + REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2); + + /* SIDLEMODE smart-idle */ + REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3); + + _dsi_initialize_irq(dsidev); + + return 0; +} + int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -4214,37 +4229,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); - goto err_start_dev; + goto err0; } - r = dsi_runtime_get(dsidev); - if (r) - goto err_get_dsi; - + enable_clocks(1); dsi_enable_pll_clock(dsidev, 1); - _dsi_initialize_irq(dsidev); + r = _dsi_reset(dsidev); + if (r) + goto err1; + + dsi_core_init(dsidev); r = dsi_display_init_dispc(dssdev); if (r) - goto err_init_dispc; + goto err1; r = dsi_display_init_dsi(dssdev); if (r) - goto err_init_dsi; + goto err2; mutex_unlock(&dsi->lock); return 0; -err_init_dsi: +err2: dsi_display_uninit_dispc(dssdev); -err_init_dispc: +err1: + enable_clocks(0); dsi_enable_pll_clock(dsidev, 0); - dsi_runtime_put(dsidev); -err_get_dsi: omap_dss_stop_device(dssdev); -err_start_dev: +err0: mutex_unlock(&dsi->lock); DSSDBG("dsi_display_enable FAILED\n"); return r; @@ -4267,7 +4282,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); - dsi_runtime_put(dsidev); + enable_clocks(0); dsi_enable_pll_clock(dsidev, 0); omap_dss_stop_device(dssdev); @@ -4422,44 +4437,7 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev) dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); } -static int dsi_get_clocks(struct platform_device *dsidev) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - struct clk *clk; - - clk = clk_get(&dsidev->dev, "dss_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get dss_clk\n"); - return PTR_ERR(clk); - } - - dsi->dss_clk = clk; - - clk = clk_get(&dsidev->dev, "sys_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get sys_clk\n"); - clk_put(dsi->dss_clk); - dsi->dss_clk = NULL; - return PTR_ERR(clk); - } - - dsi->sys_clk = clk; - - return 0; -} - -static void dsi_put_clocks(struct platform_device *dsidev) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - - if (dsi->dss_clk) - clk_put(dsi->dss_clk); - if (dsi->sys_clk) - clk_put(dsi->sys_clk); -} - -/* DSI1 HW IP initialisation */ -static int omap_dsi1hw_probe(struct platform_device *dsidev) +static int dsi_init(struct platform_device *dsidev) { struct omap_display_platform_data *dss_plat_data; struct omap_dss_board_info *board_info; @@ -4471,7 +4449,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); if (!dsi) { r = -ENOMEM; - goto err_alloc; + goto err0; } dsi->pdev = dsidev; @@ -4494,12 +4472,6 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) mutex_init(&dsi->lock); sema_init(&dsi->bus_lock, 1); - r = dsi_get_clocks(dsidev); - if (r) - goto err_get_clk; - - pm_runtime_enable(&dsidev->dev); - INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, dsi_framedone_timeout_work_callback); @@ -4512,26 +4484,26 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) if (!dsi_mem) { DSSERR("can't get IORESOURCE_MEM DSI\n"); r = -EINVAL; - goto err_ioremap; + goto err1; } dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); if (!dsi->base) { DSSERR("can't ioremap DSI\n"); r = -ENOMEM; - goto err_ioremap; + goto err1; } dsi->irq = platform_get_irq(dsi->pdev, 0); if (dsi->irq < 0) { DSSERR("platform_get_irq failed\n"); r = -ENODEV; - goto err_get_irq; + goto err2; } r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev); if (r < 0) { DSSERR("request_irq failed\n"); - goto err_get_irq; + goto err2; } /* DSI VCs initialization */ @@ -4543,9 +4515,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) dsi_calc_clock_param_ranges(dsidev); - r = dsi_runtime_get(dsidev); - if (r) - goto err_get_dsi; + enable_clocks(1); rev = dsi_read_reg(dsidev, DSI_REVISION); dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", @@ -4553,32 +4523,21 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); - dsi_runtime_put(dsidev); + enable_clocks(0); return 0; - -err_get_dsi: - free_irq(dsi->irq, dsi->pdev); -err_get_irq: +err2: iounmap(dsi->base); -err_ioremap: - pm_runtime_disable(&dsidev->dev); -err_get_clk: +err1: kfree(dsi); -err_alloc: +err0: return r; } -static int omap_dsi1hw_remove(struct platform_device *dsidev) +static void dsi_exit(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - WARN_ON(dsi->scp_clk_refcount > 0); - - pm_runtime_disable(&dsidev->dev); - - dsi_put_clocks(dsidev); - if (dsi->vdds_dsi_reg != NULL) { if (dsi->vdds_dsi_enabled) { regulator_disable(dsi->vdds_dsi_reg); @@ -4594,56 +4553,38 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev) kfree(dsi); - return 0; + DSSDBG("omap_dsi_exit\n"); } -static int dsi_runtime_suspend(struct device *dev) +/* DSI1 HW IP initialisation */ +static int omap_dsi1hw_probe(struct platform_device *dsidev) { - struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); - - clk_disable(dsi->dss_clk); - - dispc_runtime_put(); - dss_runtime_put(); + int r; - return 0; + r = dsi_init(dsidev); + if (r) { + DSSERR("Failed to initialize DSI\n"); + goto err_dsi; + } +err_dsi: + return r; } -static int dsi_runtime_resume(struct device *dev) +static int omap_dsi1hw_remove(struct platform_device *dsidev) { - struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); - int r; - - r = dss_runtime_get(); - if (r) - goto err_get_dss; - - r = dispc_runtime_get(); - if (r) - goto err_get_dispc; - - clk_enable(dsi->dss_clk); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + dsi_exit(dsidev); + WARN_ON(dsi->scp_clk_refcount > 0); return 0; - -err_get_dispc: - dss_runtime_put(); -err_get_dss: - return r; } -static const struct dev_pm_ops dsi_pm_ops = { - .runtime_suspend = dsi_runtime_suspend, - .runtime_resume = dsi_runtime_resume, -}; - static struct platform_driver omap_dsi1hw_driver = { .probe = omap_dsi1hw_probe, .remove = omap_dsi1hw_remove, .driver = { .name = "omapdss_dsi1", .owner = THIS_MODULE, - .pm = &dsi_pm_ops, }, }; |