Commit 95a337f9 authored by Vikash Garodia's avatar Vikash Garodia Committed by Hans Verkuil
Browse files

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: default avatarVishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: default avatarVishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: default avatarVikash Garodia <vikash.garodia@oss.qualcomm.com>
Reviewed-by: default avatarDikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: default avatarDmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
[bod: occassional => occasional]
Fixes: dde659d3 ("media: iris: Introduce vpu ops for vpu4 with necessary hooks")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarBryan O'Donoghue <bod@kernel.org>
Signed-off-by: default avatarHans Verkuil <hverkuil+cisco@kernel.org>
parent 4a49ae56
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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;
+4 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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,
};
+3 −6
Original line number Diff line number Diff line
@@ -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,
};
+13 −11
Original line number Diff line number Diff line
@@ -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,
};
Loading