]> www.infradead.org Git - users/hch/misc.git/commitdiff
media: rkisp1: Add support for multiple power domains
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Mon, 16 Jun 2025 01:11:14 +0000 (04:11 +0300)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Sun, 31 Aug 2025 09:10:07 +0000 (11:10 +0200)
The ISP instances in the NXP i.MX8MP need two power domains. While
single power domains are managed automatically by the device core,
support for multiple power domains requires manually attaching to the
power domains. Do so based on platform data.

Link: https://lore.kernel.org/r/20250616011115.19515-6-laurent.pinchart@ideasonboard.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c

index 4bd459edf899b0c575e8e75b1983ae53999a1425..6028ecdd23de6f69d53f77796252ee399a14436a 100644 (file)
@@ -24,6 +24,7 @@
 #include "rkisp1-regs.h"
 
 struct dentry;
+struct dev_pm_domain_list;
 struct regmap;
 
 /*
@@ -146,6 +147,8 @@ enum rkisp1_feature {
  * @features: bitmask of rkisp1_feature features implemented by the ISP
  * @max_width: maximum input frame width
  * @max_height: maximum input frame height
+ * @pm_domains.names: name of the power domains
+ * @pm_domains.count: number of power domains
  *
  * This structure contains information about the ISP specific to a particular
  * ISP model, version, or integration in a particular SoC.
@@ -158,6 +161,10 @@ struct rkisp1_info {
        unsigned int features;
        unsigned int max_width;
        unsigned int max_height;
+       struct {
+               const char * const *names;
+               unsigned int count;
+       } pm_domains;
 };
 
 /*
@@ -481,6 +488,7 @@ struct rkisp1_debug {
  * @dev:          a pointer to the struct device
  * @clk_size:     number of clocks
  * @clks:         array of clocks
+ * @pm_domains:    power domains
  * @gasket:       the gasket - i.MX8MP only
  * @gasket_id:    the gasket ID (0 or 1) - i.MX8MP only
  * @v4l2_dev:     v4l2_device variable
@@ -505,6 +513,7 @@ struct rkisp1_device {
        struct device *dev;
        unsigned int clk_size;
        struct clk_bulk_data clks[RKISP1_MAX_BUS_CLK];
+       struct dev_pm_domain_list *pm_domains;
        struct regmap *gasket;
        unsigned int gasket_id;
        struct v4l2_device v4l2_dev;
index fb4ccf497bad981bc7a59eb699172b601d68d809..1791c02a40ae18205f5eb2fd6edca6cda6b459bf 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-mc.h>
@@ -532,6 +533,11 @@ static const struct rkisp1_isr_data imx8mp_isp_isrs[] = {
        { NULL, rkisp1_isr, BIT(RKISP1_IRQ_ISP) | BIT(RKISP1_IRQ_MI) },
 };
 
+static const char * const imx8mp_isp_pm_domains[] = {
+       "isp",
+       "csi2",
+};
+
 static const struct rkisp1_info imx8mp_isp_info = {
        .num_clocks = 3,
        .isrs = imx8mp_isp_isrs,
@@ -542,6 +548,10 @@ static const struct rkisp1_info imx8mp_isp_info = {
                  | RKISP1_FEATURE_COMPAND,
        .max_width = 4096,
        .max_height = 3072,
+       .pm_domains = {
+               .names = imx8mp_isp_pm_domains,
+               .count = ARRAY_SIZE(imx8mp_isp_pm_domains),
+       },
 };
 
 static const struct of_device_id rkisp1_of_match[] = {
@@ -605,6 +615,37 @@ static int rkisp1_init_clocks(struct rkisp1_device *rkisp1)
        return 0;
 }
 
+static int rkisp1_init_pm_domains(struct rkisp1_device *rkisp1)
+{
+       const struct rkisp1_info *info = rkisp1->info;
+       struct dev_pm_domain_attach_data pm_domain_data = {
+               .pd_names = info->pm_domains.names,
+               .num_pd_names = info->pm_domains.count,
+       };
+       int ret;
+
+       /*
+        * Most platforms have a single power domain, which the PM domain core
+        * automatically attaches at probe time. When that's the case there's
+        * nothing to do here.
+        */
+       if (rkisp1->dev->pm_domain)
+               return 0;
+
+       if (!pm_domain_data.num_pd_names)
+               return 0;
+
+       ret = devm_pm_domain_attach_list(rkisp1->dev, &pm_domain_data,
+                                        &rkisp1->pm_domains);
+       if (ret < 0) {
+               dev_err_probe(rkisp1->dev, ret,
+                             "Failed to attach power domains\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static int rkisp1_probe(struct platform_device *pdev)
 {
        const struct rkisp1_info *info;
@@ -666,6 +707,10 @@ static int rkisp1_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       ret = rkisp1_init_pm_domains(rkisp1);
+       if (ret)
+               return ret;
+
        if (info->isp_ver == RKISP1_V_IMX8MP) {
                unsigned int id;