[PATCH v3 2/5] media: iris: Add hardware power on/off ops for X1P42100
From: Wangao Wang
Date: Thu Mar 19 2026 - 05:26:05 EST
On X1P42100 the Iris block has an extra BSE clock. Wire this clock into
the power on/off sequence.
The BSE clock is used to drive the Bin Stream Engine, which is a sub-block
of the video codec hardware responsible for bitstream-level processing. It
is required to be enabled separately from the core clock to ensure proper
codec operation.
Signed-off-by: Wangao Wang <wangao.wang@xxxxxxxxxxxxxxxx>
---
drivers/media/platform/qcom/iris/iris_vpu3x.c | 87 ++++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_vpu_common.h | 1 +
2 files changed, 88 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c
index fe4423b951b1e9e31d06dffc69d18071cc985731..b641a7ab1a5f9051573fe8900ba01aaf78603120 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c
@@ -71,6 +71,85 @@ static void iris_vpu3_power_off_hardware(struct iris_core *core)
iris_vpu_power_off_hw(core);
}
+static int iris_vpu3_purwa_power_on_hw(struct iris_core *core)
+{
+ int ret;
+
+ ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
+ if (ret)
+ return ret;
+
+ ret = iris_prepare_enable_clock(core, IRIS_HW_CLK);
+ if (ret)
+ goto err_disable_power;
+
+ ret = iris_prepare_enable_clock(core, IRIS_BSE_HW_CLK);
+ if (ret)
+ goto err_disable_hw_clock;
+
+ ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true);
+ if (ret)
+ goto err_disable_bse_hw_clock;
+
+ return 0;
+
+err_disable_bse_hw_clock:
+ iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK);
+err_disable_hw_clock:
+ iris_disable_unprepare_clock(core, IRIS_HW_CLK);
+err_disable_power:
+ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
+
+ return ret;
+}
+
+static void iris_vpu3_purwa_power_off_hardware(struct iris_core *core)
+{
+ u32 reg_val = 0, value, i;
+ int ret;
+
+ if (iris_vpu3x_hw_power_collapsed(core))
+ goto disable_power;
+
+ dev_err(core->dev, "video hw is power on\n");
+
+ value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
+ if (value)
+ writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
+
+ for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) {
+ ret = readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN + 4 * i,
+ reg_val, reg_val & 0x400000, 2000, 20000);
+ if (ret)
+ goto disable_power;
+ }
+
+ writel(VIDEO_NOC_RESET_REQ, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ);
+
+ ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK,
+ reg_val, reg_val & 0x3, 200, 2000);
+ if (ret)
+ goto disable_power;
+
+ writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ);
+
+ ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK,
+ reg_val, !(reg_val & 0x3), 200, 2000);
+ if (ret)
+ goto disable_power;
+
+ writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE,
+ core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
+ writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
+ writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
+
+disable_power:
+ dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false);
+ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
+ iris_disable_unprepare_clock(core, IRIS_BSE_HW_CLK);
+ iris_disable_unprepare_clock(core, IRIS_HW_CLK);
+}
+
static void iris_vpu33_power_off_hardware(struct iris_core *core)
{
bool handshake_done = false, handshake_busy = false;
@@ -268,6 +347,14 @@ const struct vpu_ops iris_vpu3_ops = {
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
};
+const struct vpu_ops iris_vpu3_purwa_ops = {
+ .power_off_hw = iris_vpu3_purwa_power_off_hardware,
+ .power_on_hw = iris_vpu3_purwa_power_on_hw,
+ .power_off_controller = iris_vpu_power_off_controller,
+ .power_on_controller = iris_vpu_power_on_controller,
+ .calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
+};
+
const struct vpu_ops iris_vpu33_ops = {
.power_off_hw = iris_vpu33_power_off_hardware,
.power_on_hw = iris_vpu_power_on_hw,
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h
index f6dffc613b822341fb21e12de6b1395202f62cde..88a23cbdc06c5b38b4c8db67718cbd538f0e0721 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h
@@ -10,6 +10,7 @@ struct iris_core;
extern const struct vpu_ops iris_vpu2_ops;
extern const struct vpu_ops iris_vpu3_ops;
+extern const struct vpu_ops iris_vpu3_purwa_ops;
extern const struct vpu_ops iris_vpu33_ops;
extern const struct vpu_ops iris_vpu35_ops;
extern const struct vpu_ops iris_vpu4x_ops;
--
2.43.0