On MMP3, the camera block lives on na separate power island. We want to turn it off if the CCIC is not in use to conserve power. Signed-off-by: Lubomir Rintel <lkundrak@xxxxx> --- Changes since v1: (all at suggestions from Sakari Ailus) - s/on na separate/on a separate/ in commit message - Move clock management into PM callbacks .../media/platform/marvell-ccic/mcam-core.c | 31 ++----------- .../media/platform/marvell-ccic/mmp-driver.c | 43 +++++++++++++++++-- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 3d4242b8182ba..a967f010341fa 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -24,6 +24,7 @@ #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/videodev2.h> +#include <linux/pm_runtime.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> @@ -893,30 +894,6 @@ static void mcam_ctlr_power_down(struct mcam_camera *cam) spin_unlock_irqrestore(&cam->dev_lock, flags); } -/* ---------------------------------------------------------------------- */ -/* - * Controller clocks. - */ -static void mcam_clk_enable(struct mcam_camera *mcam) -{ - unsigned int i; - - for (i = 0; i < NR_MCAM_CLK; i++) { - if (!IS_ERR(mcam->clk[i])) - clk_prepare_enable(mcam->clk[i]); - } -} - -static void mcam_clk_disable(struct mcam_camera *mcam) -{ - int i; - - for (i = NR_MCAM_CLK - 1; i >= 0; i--) { - if (!IS_ERR(mcam->clk[i])) - clk_disable_unprepare(mcam->clk[i]); - } -} - /* ---------------------------------------------------------------------- */ /* * Master sensor clock. @@ -1633,7 +1610,7 @@ static int mcam_v4l_open(struct file *filp) ret = sensor_call(cam, core, s_power, 1); if (ret) goto out; - mcam_clk_enable(cam); + pm_runtime_get_sync(cam->dev); __mcam_cam_reset(cam); mcam_set_config_needed(cam, 1); } @@ -1656,7 +1633,7 @@ static int mcam_v4l_release(struct file *filp) if (last_open) { mcam_disable_mipi(cam); sensor_call(cam, core, s_power, 0); - mcam_clk_disable(cam); + pm_runtime_put(cam->dev); if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) mcam_free_dma_bufs(cam); } @@ -1977,7 +1954,6 @@ void mccic_suspend(struct mcam_camera *cam) mcam_ctlr_stop_dma(cam); sensor_call(cam, core, s_power, 0); - mcam_clk_disable(cam); cam->state = cstate; } mutex_unlock(&cam->s_mutex); @@ -1990,7 +1966,6 @@ int mccic_resume(struct mcam_camera *cam) mutex_lock(&cam->s_mutex); if (!list_empty(&cam->vdev.fh_list)) { - mcam_clk_enable(cam); ret = sensor_call(cam, core, s_power, 1); if (ret) { mutex_unlock(&cam->s_mutex); diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index 78263e746cad2..c4b28a00a3a24 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -20,6 +20,7 @@ #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/io.h> #include <linux/list.h> #include <linux/pm.h> @@ -274,6 +275,7 @@ static int mmpcam_probe(struct platform_device *pdev) if (ret) goto out; + pm_runtime_enable(&pdev->dev); return 0; out: fwnode_handle_put(mcam->asd.match.fwnode); @@ -288,6 +290,7 @@ static int mmpcam_remove(struct mmp_camera *cam) struct mcam_camera *mcam = &cam->mcam; mccic_shutdown(mcam); + pm_runtime_force_suspend(mcam->dev); return 0; } @@ -304,11 +307,40 @@ static int mmpcam_platform_remove(struct platform_device *pdev) * Suspend/resume support. */ +static int mmpcam_runtime_resume(struct device *dev) +{ + struct mmp_camera *cam = dev_get_drvdata(dev); + struct mcam_camera *mcam = &cam->mcam; + unsigned int i; + + for (i = 0; i < NR_MCAM_CLK; i++) { + if (!IS_ERR(mcam->clk[i])) + clk_prepare_enable(mcam->clk[i]); + } + + return 0; +} + +static int mmpcam_runtime_suspend(struct device *dev) +{ + struct mmp_camera *cam = dev_get_drvdata(dev); + struct mcam_camera *mcam = &cam->mcam; + int i; + + for (i = NR_MCAM_CLK - 1; i >= 0; i--) { + if (!IS_ERR(mcam->clk[i])) + clk_disable_unprepare(mcam->clk[i]); + } + + return 0; +} + static int mmpcam_suspend(struct device *dev) { struct mmp_camera *cam = dev_get_drvdata(dev); - mccic_suspend(&cam->mcam); + if (!pm_runtime_suspended(dev)) + mccic_suspend(&cam->mcam); return 0; } @@ -316,10 +348,15 @@ static int mmpcam_resume(struct device *dev) { struct mmp_camera *cam = dev_get_drvdata(dev); - return mccic_resume(&cam->mcam); + if (!pm_runtime_suspended(dev)) + return mccic_resume(&cam->mcam); + return 0; } -static SIMPLE_DEV_PM_OPS(mmpcam_pm_ops, mmpcam_suspend, mmpcam_resume); +static const struct dev_pm_ops mmpcam_pm_ops = { + SET_RUNTIME_PM_OPS(mmpcam_runtime_suspend, mmpcam_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(mmpcam_suspend, mmpcam_resume) +}; static const struct of_device_id mmpcam_of_match[] = { { .compatible = "marvell,mmp2-ccic", }, -- 2.26.2