spin_unlock_irqrestore(&vfe->output_lock, flags);
 }
 
+/*
+ * vfe_pm_domain_off - Disable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+static void vfe_pm_domain_off(struct vfe_device *vfe)
+{
+       /* nop */
+}
+
+/*
+ * vfe_pm_domain_on - Enable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+static int vfe_pm_domain_on(struct vfe_device *vfe)
+{
+       return 0;
+}
+
 /*
  * vfe_queue_buffer - Add empty buffer
  * @vid: Video device structure
        .hw_version_read = vfe_hw_version_read,
        .isr_read = vfe_isr_read,
        .isr = vfe_isr,
+       .pm_domain_off = vfe_pm_domain_off,
+       .pm_domain_on = vfe_pm_domain_on,
        .reg_update_clear = vfe_reg_update_clear,
        .reg_update = vfe_reg_update,
        .subdev_init = vfe_subdev_init,
 
        return IRQ_HANDLED;
 }
 
+/*
+ * vfe_pm_domain_off - Disable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+static void vfe_pm_domain_off(struct vfe_device *vfe)
+{
+       /* nop */
+}
+
+/*
+ * vfe_pm_domain_on - Enable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+static int vfe_pm_domain_on(struct vfe_device *vfe)
+{
+       return 0;
+}
+
 static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_1 = {
        .bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,
        .bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,
        .hw_version_read = vfe_hw_version_read,
        .isr_read = vfe_isr_read,
        .isr = vfe_isr,
+       .pm_domain_off = vfe_pm_domain_off,
+       .pm_domain_on = vfe_pm_domain_on,
        .reg_update_clear = vfe_reg_update_clear,
        .reg_update = vfe_reg_update,
        .subdev_init = vfe_subdev_init,
 
  * Copyright (C) 2015-2018 Linaro Ltd.
  */
 
+#include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
        writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
 }
 
+/*
+ * vfe_pm_domain_off - Disable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+static void vfe_pm_domain_off(struct vfe_device *vfe)
+{
+       struct camss *camss;
+
+       if (!vfe)
+               return;
+
+       camss = vfe->camss;
+
+       device_link_del(camss->genpd_link[vfe->id]);
+}
+
+/*
+ * vfe_pm_domain_on - Enable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+static int vfe_pm_domain_on(struct vfe_device *vfe)
+{
+       struct camss *camss = vfe->camss;
+       enum vfe_line_id id = vfe->id;
+
+       camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id], DL_FLAG_STATELESS |
+                                               DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
+
+       if (!camss->genpd_link[id]) {
+               dev_err(vfe->camss->dev, "Failed to add VFE#%d to power domain\n", id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static void vfe_violation_read(struct vfe_device *vfe)
 {
        u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
        .hw_version_read = vfe_hw_version_read,
        .isr_read = vfe_isr_read,
        .isr = vfe_isr,
+       .pm_domain_off = vfe_pm_domain_off,
+       .pm_domain_on = vfe_pm_domain_on,
        .reg_update_clear = vfe_reg_update_clear,
        .reg_update = vfe_reg_update,
        .subdev_init = vfe_subdev_init,
 
  * Copyright (C) 2015-2021 Linaro Ltd.
  */
 
+#include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
        writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
 }
 
+/*
+ * vfe_pm_domain_off - Disable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+static void vfe_pm_domain_off(struct vfe_device *vfe)
+{
+       struct camss *camss = vfe->camss;
+
+       device_link_del(camss->genpd_link[vfe->id]);
+}
+
+/*
+ * vfe_pm_domain_on - Enable power domains specific to this VFE.
+ * @vfe: VFE Device
+ */
+static int vfe_pm_domain_on(struct vfe_device *vfe)
+{
+       struct camss *camss = vfe->camss;
+       enum vfe_line_id id = vfe->id;
+
+       camss->genpd_link[id] = device_link_add(camss->dev, camss->genpd[id], DL_FLAG_STATELESS |
+                                               DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
+
+       if (!camss->genpd_link[id]) {
+               dev_err(vfe->camss->dev, "Failed to add VFE#%d to power domain\n", id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static void vfe_violation_read(struct vfe_device *vfe)
 {
        u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
        .hw_version_read = vfe_hw_version_read,
        .isr_read = vfe_isr_read,
        .isr = vfe_isr,
+       .pm_domain_off = vfe_pm_domain_off,
+       .pm_domain_on = vfe_pm_domain_on,
        .reg_update_clear = vfe_reg_update_clear,
        .reg_update = vfe_reg_update,
        .subdev_init = vfe_subdev_init,
 
        mutex_lock(&vfe->power_lock);
 
        if (vfe->power_count == 0) {
-               ret = camss_pm_domain_on(vfe->camss, vfe->id);
+               ret = vfe->ops->pm_domain_on(vfe);
                if (ret < 0)
                        goto error_pm_domain;
 
 
 error_pm_runtime_get:
        pm_runtime_put_sync(vfe->camss->dev);
-       camss_pm_domain_off(vfe->camss, vfe->id);
+       vfe->ops->pm_domain_off(vfe);
 
 error_pm_domain:
        mutex_unlock(&vfe->power_lock);
                }
                camss_disable_clocks(vfe->nclocks, vfe->clock);
                pm_runtime_put_sync(vfe->camss->dev);
-               camss_pm_domain_off(vfe->camss, vfe->id);
+               vfe->ops->pm_domain_off(vfe);
        }
 
        vfe->power_count--;
 
        void (*hw_version_read)(struct vfe_device *vfe, struct device *dev);
        irqreturn_t (*isr)(int irq, void *dev);
        void (*isr_read)(struct vfe_device *vfe, u32 *value0, u32 *value1);
+       void (*pm_domain_off)(struct vfe_device *vfe);
+       int (*pm_domain_on)(struct vfe_device *vfe);
        void (*reg_update)(struct vfe_device *vfe, enum vfe_line_id line_id);
        void (*reg_update_clear)(struct vfe_device *vfe,
                                 enum vfe_line_id line_id);
 
 
 int camss_pm_domain_on(struct camss *camss, int id)
 {
-       if (camss->version == CAMSS_8x96 ||
-           camss->version == CAMSS_660) {
-               camss->genpd_link[id] = device_link_add(camss->dev,
-                               camss->genpd[id], DL_FLAG_STATELESS |
-                               DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
+       int ret = 0;
+
+       if (id < camss->vfe_num) {
+               struct vfe_device *vfe = &camss->vfe[id];
 
-               if (!camss->genpd_link[id])
-                       return -EINVAL;
+               ret = vfe->ops->pm_domain_on(vfe);
        }
 
-       return 0;
+       return ret;
 }
 
 void camss_pm_domain_off(struct camss *camss, int id)
 {
-       if (camss->version == CAMSS_8x96 ||
-           camss->version == CAMSS_660)
-               device_link_del(camss->genpd_link[id]);
+       if (id < camss->vfe_num) {
+               struct vfe_device *vfe = &camss->vfe[id];
+
+               vfe->ops->pm_domain_off(vfe);
+       }
 }
 
 /*
        .link_notify = v4l2_pipeline_link_notify,
 };
 
+static int camss_configure_pd(struct camss *camss)
+{
+       int nbr_pm_domains = 0;
+       int last_pm_domain = 0;
+       int i;
+       int ret;
+
+       if (camss->version == CAMSS_8x96 ||
+           camss->version == CAMSS_660)
+               nbr_pm_domains = PM_DOMAIN_GEN1_COUNT;
+
+       for (i = 0; i < nbr_pm_domains; i++) {
+               camss->genpd[i] = dev_pm_domain_attach_by_id(camss->dev, i);
+               if (IS_ERR(camss->genpd[i])) {
+                       ret = PTR_ERR(camss->genpd[i]);
+                       goto fail_pm;
+               }
+
+               camss->genpd_link[i] = device_link_add(camss->dev, camss->genpd[i],
+                                                      DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME |
+                                                      DL_FLAG_RPM_ACTIVE);
+               if (!camss->genpd_link[i]) {
+                       dev_pm_domain_detach(camss->genpd[i], true);
+                       ret = -EINVAL;
+                       goto fail_pm;
+               }
+
+               last_pm_domain = i;
+       }
+
+       return 0;
+
+fail_pm:
+       for (i = 0; i < last_pm_domain; i++) {
+               device_link_del(camss->genpd_link[i]);
+               dev_pm_domain_detach(camss->genpd[i], true);
+       }
+
+       return ret;
+}
+
 /*
  * camss_probe - Probe CAMSS platform device
  * @pdev: Pointer to CAMSS platform device
                }
        }
 
-       if (camss->version == CAMSS_8x96 ||
-           camss->version == CAMSS_660) {
-               camss->genpd[PM_DOMAIN_VFE0] = dev_pm_domain_attach_by_id(
-                                               camss->dev, PM_DOMAIN_VFE0);
-               if (IS_ERR(camss->genpd[PM_DOMAIN_VFE0]))
-                       return PTR_ERR(camss->genpd[PM_DOMAIN_VFE0]);
-
-               camss->genpd[PM_DOMAIN_VFE1] = dev_pm_domain_attach_by_id(
-                                               camss->dev, PM_DOMAIN_VFE1);
-               if (IS_ERR(camss->genpd[PM_DOMAIN_VFE1])) {
-                       dev_pm_domain_detach(camss->genpd[PM_DOMAIN_VFE0],
-                                            true);
-                       return PTR_ERR(camss->genpd[PM_DOMAIN_VFE1]);
-               }
+       ret = camss_configure_pd(camss);
+       if (ret < 0) {
+               dev_err(dev, "Failed to configure power domains: %d\n", ret);
+               return ret;
        }
 
        pm_runtime_enable(dev);
 
 void camss_delete(struct camss *camss)
 {
+       int nbr_pm_domains = 0;
+       int i;
+
        v4l2_device_unregister(&camss->v4l2_dev);
        media_device_unregister(&camss->media_dev);
        media_device_cleanup(&camss->media_dev);
        pm_runtime_disable(camss->dev);
 
        if (camss->version == CAMSS_8x96 ||
-           camss->version == CAMSS_660) {
-               dev_pm_domain_detach(camss->genpd[PM_DOMAIN_VFE0], true);
-               dev_pm_domain_detach(camss->genpd[PM_DOMAIN_VFE1], true);
+           camss->version == CAMSS_660)
+               nbr_pm_domains = PM_DOMAIN_GEN1_COUNT;
+
+       for (i = 0; i < nbr_pm_domains; i++) {
+               device_link_del(camss->genpd_link[i]);
+               dev_pm_domain_detach(camss->genpd[i], true);
        }
 
        kfree(camss);
 
 };
 
 enum pm_domain {
-       PM_DOMAIN_VFE0,
-       PM_DOMAIN_VFE1,
-       PM_DOMAIN_COUNT
+       PM_DOMAIN_VFE0 = 0,
+       PM_DOMAIN_VFE1 = 1,
+       PM_DOMAIN_GEN1_COUNT = 2,       /* CAMSS series of ISPs */
 };
 
 enum camss_version {
        int vfe_num;
        struct vfe_device *vfe;
        atomic_t ref_count;
-       struct device *genpd[PM_DOMAIN_COUNT];
-       struct device_link *genpd_link[PM_DOMAIN_COUNT];
+       struct device *genpd[PM_DOMAIN_GEN1_COUNT];
+       struct device_link *genpd_link[PM_DOMAIN_GEN1_COUNT];
 };
 
 struct camss_camera_interface {