media: iris: switch to hardware mode after firmware boot

Currently the driver switches the vcodec GDSC to hardware (HW) mode
before firmware load and boot sequence. GDSC can be powered off, keeping
in hw mode, thereby the vcodec registers programmed in TrustZone (TZ)
carry default (reset) values.
Move the transition to HW mode after firmware load and boot sequence.

The bug was exposed with driver configuring different stream ids to
different devices via iommu-map. With registers carrying reset values,
VPU would not generate desired stream-id, thereby leading to SMMU fault.

For vpu4, when GDSC is switched to HW mode, there is a need to perform
the reset operation. Without reset, there are occasional issues of
register corruption observed. Hence the vpu GDSC switch also involves
the reset.

Co-developed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Reviewed-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
[bod: occassional => occasional]
Fixes: dde659d370 ("media: iris: Introduce vpu ops for vpu4 with necessary hooks")
Cc: stable@vger.kernel.org
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
Vikash Garodia 2026-03-13 18:49:36 +05:30 committed by Hans Verkuil
parent 4a49ae56b0
commit 95a337f92f
7 changed files with 38 additions and 23 deletions

View File

@ -75,6 +75,10 @@ int iris_core_init(struct iris_core *core)
if (ret)
goto error_unload_fw;
ret = iris_vpu_switch_to_hwmode(core);
if (ret)
goto error_unload_fw;
ret = iris_hfi_core_init(core);
if (ret)
goto error_unload_fw;

View File

@ -159,6 +159,10 @@ int iris_hfi_pm_resume(struct iris_core *core)
if (ret)
goto err_suspend_hw;
ret = iris_vpu_switch_to_hwmode(core);
if (ret)
goto err_suspend_hw;
ret = ops->sys_interframe_powercollapse(core);
if (ret)
goto err_suspend_hw;

View File

@ -44,4 +44,5 @@ const struct vpu_ops iris_vpu2_ops = {
.power_off_controller = iris_vpu_power_off_controller,
.power_on_controller = iris_vpu_power_on_controller,
.calc_freq = iris_vpu2_calc_freq,
.set_hwmode = iris_vpu_set_hwmode,
};

View File

@ -234,14 +234,8 @@ static int iris_vpu35_power_on_hw(struct iris_core *core)
if (ret)
goto err_disable_hw_free_clk;
ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true);
if (ret)
goto err_disable_hw_clk;
return 0;
err_disable_hw_clk:
iris_disable_unprepare_clock(core, IRIS_HW_CLK);
err_disable_hw_free_clk:
iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK);
err_disable_axi_clk:
@ -266,6 +260,7 @@ const struct vpu_ops iris_vpu3_ops = {
.power_off_controller = iris_vpu_power_off_controller,
.power_on_controller = iris_vpu_power_on_controller,
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
};
const struct vpu_ops iris_vpu33_ops = {
@ -274,6 +269,7 @@ const struct vpu_ops iris_vpu33_ops = {
.power_off_controller = iris_vpu33_power_off_controller,
.power_on_controller = iris_vpu_power_on_controller,
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
};
const struct vpu_ops iris_vpu35_ops = {
@ -283,4 +279,5 @@ const struct vpu_ops iris_vpu35_ops = {
.power_on_controller = iris_vpu35_vpu4x_power_on_controller,
.program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers,
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
};

View File

@ -252,21 +252,10 @@ static int iris_vpu4x_power_on_hardware(struct iris_core *core)
ret = iris_vpu4x_power_on_apv(core);
if (ret)
goto disable_hw_clocks;
iris_vpu4x_ahb_sync_reset_apv(core);
}
iris_vpu4x_ahb_sync_reset_hardware(core);
ret = iris_vpu4x_genpd_set_hwmode(core, true, efuse_value);
if (ret)
goto disable_apv_power_domain;
return 0;
disable_apv_power_domain:
if (!(efuse_value & DISABLE_VIDEO_APV_BIT))
iris_vpu4x_power_off_apv(core);
disable_hw_clocks:
iris_vpu4x_disable_hardware_clocks(core, efuse_value);
disable_vpp1_power_domain:
@ -359,6 +348,18 @@ static void iris_vpu4x_power_off_hardware(struct iris_core *core)
iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
}
static int iris_vpu4x_set_hwmode(struct iris_core *core)
{
u32 efuse_value = readl(core->reg_base + WRAPPER_EFUSE_MONITOR);
if (!(efuse_value & DISABLE_VIDEO_APV_BIT))
iris_vpu4x_ahb_sync_reset_apv(core);
iris_vpu4x_ahb_sync_reset_hardware(core);
return iris_vpu4x_genpd_set_hwmode(core, true, efuse_value);
}
const struct vpu_ops iris_vpu4x_ops = {
.power_off_hw = iris_vpu4x_power_off_hardware,
.power_on_hw = iris_vpu4x_power_on_hardware,
@ -366,4 +367,5 @@ const struct vpu_ops iris_vpu4x_ops = {
.power_on_controller = iris_vpu35_vpu4x_power_on_controller,
.program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers,
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu4x_set_hwmode,
};

View File

@ -292,14 +292,8 @@ int iris_vpu_power_on_hw(struct iris_core *core)
if (ret && ret != -ENOENT)
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_hw_ahb_clock;
return 0;
err_disable_hw_ahb_clock:
iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK);
err_disable_hw_clock:
iris_disable_unprepare_clock(core, IRIS_HW_CLK);
err_disable_power:
@ -308,6 +302,16 @@ int iris_vpu_power_on_hw(struct iris_core *core)
return ret;
}
int iris_vpu_set_hwmode(struct iris_core *core)
{
return dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true);
}
int iris_vpu_switch_to_hwmode(struct iris_core *core)
{
return core->iris_platform_data->vpu_ops->set_hwmode(core);
}
int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core)
{
u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size;

View File

@ -21,6 +21,7 @@ struct vpu_ops {
int (*power_on_controller)(struct iris_core *core);
void (*program_bootup_registers)(struct iris_core *core);
u64 (*calc_freq)(struct iris_inst *inst, size_t data_size);
int (*set_hwmode)(struct iris_core *core);
};
int iris_vpu_boot_firmware(struct iris_core *core);
@ -30,6 +31,8 @@ int iris_vpu_watchdog(struct iris_core *core, u32 intr_status);
int iris_vpu_prepare_pc(struct iris_core *core);
int iris_vpu_power_on_controller(struct iris_core *core);
int iris_vpu_power_on_hw(struct iris_core *core);
int iris_vpu_set_hwmode(struct iris_core *core);
int iris_vpu_switch_to_hwmode(struct iris_core *core);
int iris_vpu_power_on(struct iris_core *core);
int iris_vpu_power_off_controller(struct iris_core *core);
void iris_vpu_power_off_hw(struct iris_core *core);