From: Changhuang Liang <changhuang.liang@starfivetech.com>
To: Mauro Carvalho Chehab <mchehab@kernel.org>,
Maxime Ripard <mripard@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Hans Verkuil <hverkuil-cisco@xs4all.nl>
Cc: Jacopo Mondi <jacopo.mondi@ideasonboard.com>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>,
Jack Zhu <jack.zhu@starfivetech.com>,
Keith Zhao <keith.zhao@starfivetech.com>,
Changhuang Liang <changhuang.liang@starfivetech.com>,
Jayshri Pawar <jpawar@cadence.com>, Jai Luthra <j-luthra@ti.com>,
linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-staging@lists.linux.dev
Subject: [PATCH v2 1/5] media: cadence: csi2rx: Support runtime PM
Date: Wed, 17 Jul 2024 20:28:30 -0700 [thread overview]
Message-ID: <20240718032834.53876-2-changhuang.liang@starfivetech.com> (raw)
In-Reply-To: <20240718032834.53876-1-changhuang.liang@starfivetech.com>
Use runtime power management hooks to save power when CSI-RX is not in
use.
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
drivers/media/platform/cadence/cdns-csi2rx.c | 121 ++++++++++++-------
1 file changed, 80 insertions(+), 41 deletions(-)
diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index 6f7d27a48eff..981819adbb3a 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -211,11 +211,6 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
u32 reg;
int ret;
- ret = clk_prepare_enable(csi2rx->p_clk);
- if (ret)
- return ret;
-
- reset_control_deassert(csi2rx->p_rst);
csi2rx_reset(csi2rx);
reg = csi2rx->num_lanes << 8;
@@ -253,7 +248,7 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
if (ret) {
dev_err(csi2rx->dev,
"Failed to configure external DPHY: %d\n", ret);
- goto err_disable_pclk;
+ return ret;
}
}
@@ -268,11 +263,6 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
* hence the reference counting.
*/
for (i = 0; i < csi2rx->max_streams; i++) {
- ret = clk_prepare_enable(csi2rx->pixel_clk[i]);
- if (ret)
- goto err_disable_pixclk;
-
- reset_control_deassert(csi2rx->pixel_rst[i]);
writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
csi2rx->base + CSI2RX_STREAM_CFG_REG(i));
@@ -288,34 +278,18 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
}
- ret = clk_prepare_enable(csi2rx->sys_clk);
- if (ret)
- goto err_disable_pixclk;
-
- reset_control_deassert(csi2rx->sys_rst);
ret = v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, true);
if (ret)
- goto err_disable_sysclk;
-
- clk_disable_unprepare(csi2rx->p_clk);
+ goto err_phy_power_off;
return 0;
-err_disable_sysclk:
- clk_disable_unprepare(csi2rx->sys_clk);
-err_disable_pixclk:
- for (; i > 0; i--) {
- reset_control_assert(csi2rx->pixel_rst[i - 1]);
- clk_disable_unprepare(csi2rx->pixel_clk[i - 1]);
- }
-
+err_phy_power_off:
if (csi2rx->dphy) {
writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
phy_power_off(csi2rx->dphy);
}
-err_disable_pclk:
- clk_disable_unprepare(csi2rx->p_clk);
return ret;
}
@@ -326,10 +300,6 @@ static void csi2rx_stop(struct csi2rx_priv *csi2rx)
u32 val;
int ret;
- clk_prepare_enable(csi2rx->p_clk);
- reset_control_assert(csi2rx->sys_rst);
- clk_disable_unprepare(csi2rx->sys_clk);
-
for (i = 0; i < csi2rx->max_streams; i++) {
writel(CSI2RX_STREAM_CTRL_STOP,
csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
@@ -342,14 +312,8 @@ static void csi2rx_stop(struct csi2rx_priv *csi2rx)
if (ret)
dev_warn(csi2rx->dev,
"Failed to stop streaming on pad%u\n", i);
-
- reset_control_assert(csi2rx->pixel_rst[i]);
- clk_disable_unprepare(csi2rx->pixel_clk[i]);
}
- reset_control_assert(csi2rx->p_rst);
- clk_disable_unprepare(csi2rx->p_clk);
-
if (v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, false))
dev_warn(csi2rx->dev, "Couldn't disable our subdev\n");
@@ -374,9 +338,15 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
* enable the whole controller.
*/
if (!csi2rx->count) {
+ ret = pm_runtime_resume_and_get(csi2rx->dev);
+ if (ret < 0)
+ goto out;
+
ret = csi2rx_start(csi2rx);
- if (ret)
+ if (ret) {
+ pm_runtime_put(csi2rx->dev);
goto out;
+ }
}
csi2rx->count++;
@@ -386,8 +356,10 @@ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
/*
* Let the last user turn off the lights.
*/
- if (!csi2rx->count)
+ if (!csi2rx->count) {
csi2rx_stop(csi2rx);
+ pm_runtime_put(csi2rx->dev);
+ }
}
out:
@@ -707,6 +679,7 @@ static int csi2rx_probe(struct platform_device *pdev)
if (ret)
goto err_cleanup;
+ pm_runtime_enable(csi2rx->dev);
ret = v4l2_async_register_subdev(&csi2rx->subdev);
if (ret < 0)
goto err_free_state;
@@ -721,6 +694,7 @@ static int csi2rx_probe(struct platform_device *pdev)
err_free_state:
v4l2_subdev_cleanup(&csi2rx->subdev);
+ pm_runtime_disable(csi2rx->dev);
err_cleanup:
v4l2_async_nf_unregister(&csi2rx->notifier);
v4l2_async_nf_cleanup(&csi2rx->notifier);
@@ -739,9 +713,73 @@ static void csi2rx_remove(struct platform_device *pdev)
v4l2_async_unregister_subdev(&csi2rx->subdev);
v4l2_subdev_cleanup(&csi2rx->subdev);
media_entity_cleanup(&csi2rx->subdev.entity);
+ pm_runtime_disable(csi2rx->dev);
kfree(csi2rx);
}
+static int csi2rx_runtime_suspend(struct device *dev)
+{
+ struct csi2rx_priv *csi2rx = dev_get_drvdata(dev);
+ unsigned int i;
+
+ reset_control_assert(csi2rx->sys_rst);
+ clk_disable_unprepare(csi2rx->sys_clk);
+
+ for (i = 0; i < csi2rx->max_streams; i++) {
+ reset_control_assert(csi2rx->pixel_rst[i]);
+ clk_disable_unprepare(csi2rx->pixel_clk[i]);
+ }
+
+ reset_control_assert(csi2rx->p_rst);
+ clk_disable_unprepare(csi2rx->p_clk);
+
+ return 0;
+}
+
+static int csi2rx_runtime_resume(struct device *dev)
+{
+ struct csi2rx_priv *csi2rx = dev_get_drvdata(dev);
+ unsigned int i;
+ int ret;
+
+ ret = clk_prepare_enable(csi2rx->p_clk);
+ if (ret)
+ return ret;
+
+ reset_control_deassert(csi2rx->p_rst);
+
+ for (i = 0; i < csi2rx->max_streams; i++) {
+ ret = clk_prepare_enable(csi2rx->pixel_clk[i]);
+ if (ret)
+ goto err_disable_pixclk;
+
+ reset_control_deassert(csi2rx->pixel_rst[i]);
+ }
+
+ ret = clk_prepare_enable(csi2rx->sys_clk);
+ if (ret)
+ goto err_disable_pixclk;
+
+ reset_control_deassert(csi2rx->sys_rst);
+
+ return ret;
+
+err_disable_pixclk:
+ for (; i > 0; i--) {
+ reset_control_assert(csi2rx->pixel_rst[i - 1]);
+ clk_disable_unprepare(csi2rx->pixel_clk[i - 1]);
+ }
+
+ reset_control_assert(csi2rx->p_rst);
+ clk_disable_unprepare(csi2rx->p_clk);
+
+ return ret;
+}
+
+static const struct dev_pm_ops csi2rx_pm_ops = {
+ SET_RUNTIME_PM_OPS(csi2rx_runtime_suspend, csi2rx_runtime_resume, NULL)
+};
+
static const struct of_device_id csi2rx_of_table[] = {
{ .compatible = "starfive,jh7110-csi2rx" },
{ .compatible = "cdns,csi2rx" },
@@ -756,6 +794,7 @@ static struct platform_driver csi2rx_driver = {
.driver = {
.name = "cdns-csi2rx",
.of_match_table = csi2rx_of_table,
+ .pm = &csi2rx_pm_ops,
},
};
module_platform_driver(csi2rx_driver);
--
2.25.1
next prev parent reply other threads:[~2024-07-18 5:02 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-18 3:28 [PATCH v2 0/5] Add StarFive Camera Subsystem hibernation support Changhuang Liang
2024-07-18 3:28 ` Changhuang Liang [this message]
2024-07-18 14:24 ` [PATCH v2 1/5] media: cadence: csi2rx: Support runtime PM Jacopo Mondi
2024-07-18 14:53 ` kernel test robot
2024-07-18 3:28 ` [PATCH v2 2/5] media: cadence: csi2rx: Add system PM support Changhuang Liang
2024-07-18 14:31 ` Jacopo Mondi
2024-07-19 10:28 ` Tomi Valkeinen
2024-07-22 2:17 ` 回复: " Changhuang Liang
2024-07-22 8:53 ` Tomi Valkeinen
2024-07-22 11:25 ` Laurent Pinchart
2024-07-18 3:28 ` [PATCH v2 3/5] staging: media: starfive: Extract the ISP stream on as a helper function Changhuang Liang
2024-07-18 3:28 ` [PATCH v2 4/5] staging: media: starfive: Introduce streaming for ISP subdev Changhuang Liang
2024-07-18 3:28 ` [PATCH v2 5/5] staging: media: starfive: Add system PM support Changhuang Liang
2024-07-18 14:55 ` Jacopo Mondi
2024-07-19 2:08 ` 回复: " Changhuang Liang
2024-07-22 8:57 ` Jacopo Mondi
2024-07-22 9:25 ` 回复: " Changhuang Liang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240718032834.53876-2-changhuang.liang@starfivetech.com \
--to=changhuang.liang@starfivetech.com \
--cc=gregkh@linuxfoundation.org \
--cc=hverkuil-cisco@xs4all.nl \
--cc=j-luthra@ti.com \
--cc=jack.zhu@starfivetech.com \
--cc=jacopo.mondi@ideasonboard.com \
--cc=jpawar@cadence.com \
--cc=keith.zhao@starfivetech.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-staging@lists.linux.dev \
--cc=mchehab@kernel.org \
--cc=mripard@kernel.org \
--cc=tomi.valkeinen+renesas@ideasonboard.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox