diff options
Diffstat (limited to 'drivers/media/video/s5p-fimc/mipi-csis.c')
-rw-r--r-- | drivers/media/video/s5p-fimc/mipi-csis.c | 90 |
1 files changed, 48 insertions, 42 deletions
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c index ef056d6605ca..59d79bc2f58a 100644 --- a/drivers/media/video/s5p-fimc/mipi-csis.c +++ b/drivers/media/video/s5p-fimc/mipi-csis.c @@ -81,6 +81,12 @@ static char *csi_clock_name[] = { }; #define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name) +static const char * const csis_supply_name[] = { + "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */ + "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */ +}; +#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name) + enum { ST_POWERED = 1, ST_STREAMING = 2, @@ -109,9 +115,9 @@ struct csis_state { struct platform_device *pdev; struct resource *regs_res; void __iomem *regs; + struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; struct clk *clock[NUM_CSIS_CLOCKS]; int irq; - struct regulator *supply; u32 flags; const struct csis_pix_format *csis_fmt; struct v4l2_mbus_framefmt format; @@ -460,6 +466,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) struct resource *regs_res; struct csis_state *state; int ret = -ENOMEM; + int i; state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) @@ -519,14 +526,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) goto e_clkput; } - if (!pdata->fixed_phy_vdd) { - state->supply = regulator_get(&pdev->dev, "vdd"); - if (IS_ERR(state->supply)) { - ret = PTR_ERR(state->supply); - state->supply = NULL; - goto e_clkput; - } - } + for (i = 0; i < CSIS_NUM_SUPPLIES; i++) + state->supplies[i].supply = csis_supply_name[i]; + + ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, + state->supplies); + if (ret) + goto e_clkput; ret = request_irq(state->irq, s5pcsis_irq_handler, 0, dev_name(&pdev->dev), state); @@ -553,7 +559,6 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) /* .. and a pointer to the subdev. */ platform_set_drvdata(pdev, &state->sd); - state->flags = ST_SUSPENDED; pm_runtime_enable(&pdev->dev); return 0; @@ -561,8 +566,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) e_irqfree: free_irq(state->irq, state); e_regput: - if (state->supply) - regulator_put(state->supply); + regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); e_clkput: clk_disable(state->clock[CSIS_CLK_MUX]); s5pcsis_clk_put(state); @@ -575,7 +579,7 @@ e_free: return ret; } -static int s5pcsis_suspend(struct device *dev) +static int s5pcsis_pm_suspend(struct device *dev, bool runtime) { struct s5p_platform_mipi_csis *pdata = dev->platform_data; struct platform_device *pdev = to_platform_device(dev); @@ -592,21 +596,21 @@ static int s5pcsis_suspend(struct device *dev) ret = pdata->phy_enable(state->pdev, false); if (ret) goto unlock; - if (state->supply) { - ret = regulator_disable(state->supply); - if (ret) - goto unlock; - } + ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES, + state->supplies); + if (ret) + goto unlock; clk_disable(state->clock[CSIS_CLK_GATE]); state->flags &= ~ST_POWERED; + if (!runtime) + state->flags |= ST_SUSPENDED; } - state->flags |= ST_SUSPENDED; unlock: mutex_unlock(&state->lock); return ret ? -EAGAIN : 0; } -static int s5pcsis_resume(struct device *dev) +static int s5pcsis_pm_resume(struct device *dev, bool runtime) { struct s5p_platform_mipi_csis *pdata = dev->platform_data; struct platform_device *pdev = to_platform_device(dev); @@ -618,20 +622,20 @@ static int s5pcsis_resume(struct device *dev) __func__, state->flags); mutex_lock(&state->lock); - if (!(state->flags & ST_SUSPENDED)) + if (!runtime && !(state->flags & ST_SUSPENDED)) goto unlock; if (!(state->flags & ST_POWERED)) { - if (state->supply) - ret = regulator_enable(state->supply); + ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES, + state->supplies); if (ret) goto unlock; - ret = pdata->phy_enable(state->pdev, true); if (!ret) { state->flags |= ST_POWERED; - } else if (state->supply) { - regulator_disable(state->supply); + } else { + regulator_bulk_disable(CSIS_NUM_SUPPLIES, + state->supplies); goto unlock; } clk_enable(state->clock[CSIS_CLK_GATE]); @@ -646,24 +650,26 @@ static int s5pcsis_resume(struct device *dev) } #ifdef CONFIG_PM_SLEEP -static int s5pcsis_pm_suspend(struct device *dev) +static int s5pcsis_suspend(struct device *dev) { - return s5pcsis_suspend(dev); + return s5pcsis_pm_suspend(dev, false); } -static int s5pcsis_pm_resume(struct device *dev) +static int s5pcsis_resume(struct device *dev) { - int ret; - - ret = s5pcsis_resume(dev); + return s5pcsis_pm_resume(dev, false); +} +#endif - if (!ret) { - pm_runtime_disable(dev); - ret = pm_runtime_set_active(dev); - pm_runtime_enable(dev); - } +#ifdef CONFIG_PM_RUNTIME +static int s5pcsis_runtime_suspend(struct device *dev) +{ + return s5pcsis_pm_suspend(dev, true); +} - return ret; +static int s5pcsis_runtime_resume(struct device *dev) +{ + return s5pcsis_pm_resume(dev, true); } #endif @@ -679,8 +685,7 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev) pm_runtime_set_suspended(&pdev->dev); s5pcsis_clk_put(state); - if (state->supply) - regulator_put(state->supply); + regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); media_entity_cleanup(&state->sd.entity); free_irq(state->irq, state); @@ -692,8 +697,9 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev) } static const struct dev_pm_ops s5pcsis_pm_ops = { - SET_RUNTIME_PM_OPS(s5pcsis_suspend, s5pcsis_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_pm_suspend, s5pcsis_pm_resume) + SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume) }; static struct platform_driver s5pcsis_driver = { |