From nobody Fri Oct 3 11:22:53 2025 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BD15B2F6197; Tue, 2 Sep 2025 10:57:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756810645; cv=none; b=ccbR41HXv3rkODHv4vJn1c83Q/7HyBd/7DcCI2IBdhZnsIB0Z7Cw8nzVl2xEcnZn+S2SaWlfp5t6xd9lf8Otutor2E6YUkOATZcvj2kR6V9EVKl67Ok0nbYigEjLw8nLuI3n/lLJug9HlyJR+DBjJZ5nB+mxxSQkUgQjziwZiWg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756810645; c=relaxed/simple; bh=huBM6u3sNxRpnxJBrZpY0B7keydyhtbBnOV4Aft0+Tg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rrnHniZ5joRw2zJllspz3EtndQEvs5T1utF53qV8JbPwpRYJ6448OdeNy7bnISumD7Dx4NJP/2SEbTWYOYBGGNKD9IyFGs6rWKtzfgVjatQOQRYAnOTaxC+jTK242hL6fHFazHeHf+3QxChluz34o15LlzEl6CenFUMAz0mnDos= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=bVR3NfNJ; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="bVR3NfNJ" Received: from mail.ideasonboard.com (unknown [IPv6:2401:4900:1c69:480e:e039:1d0b:c5ff:a9e2]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B806BC72; Tue, 2 Sep 2025 12:56:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1756810574; bh=huBM6u3sNxRpnxJBrZpY0B7keydyhtbBnOV4Aft0+Tg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bVR3NfNJXo19V+OFTH52Pf7nSF1ZdTLYNVYhB8F4oJTKduI2L6yKRff+uxlo6eg1Q +8XmKPvMgZ/ONQ+qCTL/XBuPzUfeZdrWH2cGU0DqBll36jL9KqQa80nxUBZ8aAsWMd 3KUnm0vssVh6G5UOXZHlzrz0sDhnN9MiE0n2zoOE= From: Jai Luthra Date: Tue, 02 Sep 2025 16:26:49 +0530 Subject: [PATCH v2 1/3] media: cadence: csi2rx: Support runtime PM Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250902-ti_csi_pm-v2-1-59a3be199940@ideasonboard.com> References: <20250902-ti_csi_pm-v2-0-59a3be199940@ideasonboard.com> In-Reply-To: <20250902-ti_csi_pm-v2-0-59a3be199940@ideasonboard.com> To: Mauro Carvalho Chehab , Maxime Ripard , Philipp Zabel , Sakari Ailus Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Laurent Pinchart , Tomi Valkeinen , Changhuang Liang , Devarsh Thakkar , Rishikesh Donadkar , Jai Luthra X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7583; i=jai.luthra@ideasonboard.com; h=from:subject:message-id; bh=aqs7ljfIPQcuvWd4u15PtiVXmyox+XqlctCH69f8xUo=; b=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBots2EsH2ECW4WrkGMf9IhFc2guYWfLpMy+syRB 7lQZFhWEmGJAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCaLbNhAAKCRBD3pH5JJpx ReOvD/0W9Znq3jQz4qU/8xuF80OFy1F1Xwa8z405/6mt8FV4bce5NyIXczf5dxsxNsAlK3NL/D1 ryKJ1eRLoitCn0Ypzx5bVnhzzMEW7cgILYdr+/BLOismVhSZ7bCyIWvzxf6aG2vsKrdSGwj4rmL xGR0LpW8lEDXXusIUl3J3McfsEocZm00i2wdMv9uiB1aTxeiiyJf07DR55JvL7lMUOsqybgZh00 KwF6inao7g+/cXnTsxBYnmSDxJtyDVDDB9uyVR8n6tZjPKGKhGY6IaeVloHiXnHrhrjE/a16cUS GtO9gE0gZGRnqlwGZOFT8hlWwBM++u6AuVvtRdvx+M/kyKQv8fYOBv3gg/RpucewtPXqSvt/XwI FSpQwv9YDQFN+RDsZenio9bh6DWwRtHmU7HfVlfmHb1sjAu2UK/X/EcrZC9tUPw+zQaazT1Mpdn RaO3/V296tzLdJsB5Fho6YRYEudHT42Zq681sRwPJlQYRe7CTemk3xk1fjGKFpClLIvvxAg8vyv xTbkLLpj60W41swjF4IEzTnnXdg/z52RFUqVpv3OEOS8fqxrF9+FahCMA6ugfoucCgnMZHT/5t/ 8RJEaIAv2X2sko4GWw6vLwRuKDMsVOhNTJiDYdglFSrUog3oYlnWrtZ756BRs8AHcRAEjxbuyFL 8wlatMiGlAlFMfA== X-Developer-Key: i=jai.luthra@ideasonboard.com; a=openpgp; fpr=4DE0D818E5D575E8D45AAFC543DE91F9249A7145 From: Changhuang Liang Use runtime power management hooks to save power when CSI-RX is not in use. Signed-off-by: Changhuang Liang Tested-by: Rishikesh Donadkar Reviewed-by: Rishikesh Donadkar Signed-off-by: Jai Luthra --- drivers/media/platform/cadence/Kconfig | 1 + drivers/media/platform/cadence/cdns-csi2rx.c | 129 +++++++++++++++++------= ---- 2 files changed, 83 insertions(+), 47 deletions(-) diff --git a/drivers/media/platform/cadence/Kconfig b/drivers/media/platfor= m/cadence/Kconfig index 1aa608c00dbce9b52d0d48b5ac8c877db7494fd7..ea85ef82760e694c1e03fa323fc= 7a468b135e2e1 100644 --- a/drivers/media/platform/cadence/Kconfig +++ b/drivers/media/platform/cadence/Kconfig @@ -5,6 +5,7 @@ comment "Cadence media platform drivers" config VIDEO_CADENCE_CSI2RX tristate "Cadence MIPI-CSI2 RX Controller" depends on VIDEO_DEV + depends on PM select MEDIA_CONTROLLER select VIDEO_V4L2_SUBDEV_API select V4L2_FWNODE diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/p= latform/cadence/cdns-csi2rx.c index 11b73c79adff8c2be0b363eea3b54dd050842c81..fce9397448cda253d4de2c69050= ff47059e0e1f1 100644 --- a/drivers/media/platform/cadence/cdns-csi2rx.c +++ b/drivers/media/platform/cadence/cdns-csi2rx.c @@ -343,11 +343,6 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) u32 reg; int ret; =20 - ret =3D clk_prepare_enable(csi2rx->p_clk); - if (ret) - return ret; - - reset_control_deassert(csi2rx->p_rst); csi2rx_reset(csi2rx); =20 if (csi2rx->error_irq >=3D 0) @@ -388,7 +383,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; } } =20 @@ -403,12 +398,6 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) * hence the reference counting. */ for (i =3D 0; i < csi2rx->max_streams; i++) { - ret =3D 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 | FIELD_PREP(CSI2RX_STREAM_CFG_NUM_PIXELS_MASK, csi2rx->num_pixels[i]), @@ -421,30 +410,8 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) csi2rx->base + CSI2RX_STREAM_CTRL_REG(i)); } =20 - ret =3D clk_prepare_enable(csi2rx->sys_clk); - if (ret) - goto err_disable_pixclk; - - reset_control_deassert(csi2rx->sys_rst); - - clk_disable_unprepare(csi2rx->p_clk); =20 return 0; - -err_disable_pixclk: - for (; i > 0; i--) { - reset_control_assert(csi2rx->pixel_rst[i - 1]); - clk_disable_unprepare(csi2rx->pixel_clk[i - 1]); - } - - 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; } =20 static void csi2rx_stop(struct csi2rx_priv *csi2rx) @@ -453,10 +420,6 @@ static void csi2rx_stop(struct csi2rx_priv *csi2rx) u32 val; int ret; =20 - clk_prepare_enable(csi2rx->p_clk); - reset_control_assert(csi2rx->sys_rst); - clk_disable_unprepare(csi2rx->sys_clk); - writel(0, csi2rx->base + CSI2RX_ERROR_IRQS_MASK_REG); =20 for (i =3D 0; i < csi2rx->max_streams; i++) { @@ -471,14 +434,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]); } =20 - reset_control_assert(csi2rx->p_rst); - clk_disable_unprepare(csi2rx->p_clk); - if (csi2rx->dphy) { writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); =20 @@ -555,10 +512,17 @@ static int csi2rx_enable_streams(struct v4l2_subdev *= subdev, * enable the whole controller. */ if (!csi2rx->count) { + ret =3D pm_runtime_resume_and_get(csi2rx->dev); + if (ret < 0) + return ret; + csi2rx_update_vc_select(csi2rx, state); + ret =3D csi2rx_start(csi2rx); - if (ret) + if (ret) { + pm_runtime_put(csi2rx->dev); return ret; + } } =20 /* Start streaming on the source */ @@ -568,8 +532,10 @@ static int csi2rx_enable_streams(struct v4l2_subdev *s= ubdev, dev_err(csi2rx->dev, "Failed to start streams %#llx on subdev\n", sink_streams); - if (!csi2rx->count) + if (!csi2rx->count) { csi2rx_stop(csi2rx); + pm_runtime_put(csi2rx->dev); + } return ret; } =20 @@ -597,8 +563,10 @@ static int csi2rx_disable_streams(struct v4l2_subdev *= subdev, csi2rx->count--; =20 /* Let the last user turn off the lights. */ - if (!csi2rx->count) + if (!csi2rx->count) { csi2rx_stop(csi2rx); + pm_runtime_put(csi2rx->dev); + } =20 return 0; } @@ -1101,6 +1069,7 @@ static int csi2rx_probe(struct platform_device *pdev) if (ret) goto err_cleanup; =20 + pm_runtime_enable(csi2rx->dev); ret =3D v4l2_async_register_subdev(&csi2rx->subdev); if (ret < 0) goto err_free_state; @@ -1115,6 +1084,7 @@ static int csi2rx_probe(struct platform_device *pdev) =20 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); @@ -1133,9 +1103,73 @@ static void csi2rx_remove(struct platform_device *pd= ev) v4l2_async_unregister_subdev(&csi2rx->subdev); v4l2_subdev_cleanup(&csi2rx->subdev); media_entity_cleanup(&csi2rx->subdev.entity); + pm_runtime_disable(csi2rx->dev); kfree(csi2rx); } =20 +static int csi2rx_runtime_suspend(struct device *dev) +{ + struct csi2rx_priv *csi2rx =3D dev_get_drvdata(dev); + unsigned int i; + + reset_control_assert(csi2rx->sys_rst); + clk_disable_unprepare(csi2rx->sys_clk); + + for (i =3D 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 =3D dev_get_drvdata(dev); + unsigned int i; + int ret; + + ret =3D clk_prepare_enable(csi2rx->p_clk); + if (ret) + return ret; + + reset_control_deassert(csi2rx->p_rst); + + for (i =3D 0; i < csi2rx->max_streams; i++) { + ret =3D clk_prepare_enable(csi2rx->pixel_clk[i]); + if (ret) + goto err_disable_pixclk; + + reset_control_deassert(csi2rx->pixel_rst[i]); + } + + ret =3D clk_prepare_enable(csi2rx->sys_clk); + if (ret) + goto err_disable_pixclk; + + reset_control_deassert(csi2rx->sys_rst); + + return 0; + +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 =3D { + RUNTIME_PM_OPS(csi2rx_runtime_suspend, csi2rx_runtime_resume, NULL) +}; + static const struct of_device_id csi2rx_of_table[] =3D { { .compatible =3D "starfive,jh7110-csi2rx" }, { .compatible =3D "cdns,csi2rx" }, @@ -1150,6 +1184,7 @@ static struct platform_driver csi2rx_driver =3D { .driver =3D { .name =3D "cdns-csi2rx", .of_match_table =3D csi2rx_of_table, + .pm =3D &csi2rx_pm_ops, }, }; module_platform_driver(csi2rx_driver); --=20 2.50.1