浏览代码

video: iris3: Fix the issue in power collapsing video hardware

During power collapse, video driver would power collapse video
hardware followed by video controller.
While power collapsing video hardware, it may happen that video
firmware has already power collapsed the video hardware, since
it is hardware controlled. For certain cases, like XS WD, it
may happen that video hardware may not be power collapsed by
video firmware. In such scenario, skipping power collapse sequence
of video hardware would lead to unhandled transactions from video
hardware.
There is a power status register which can clearly suggest if the
video hardware is power down or not. Added a check to confirm the
power status of video hardware before skipping or executing the
power collapse sequence for video hardware.

Change-Id: Ibd9cd708a259897262fcc6cab27b26aaf37f1b13
Signed-off-by: Vikash Garodia <[email protected]>
Vikash Garodia 3 年之前
父节点
当前提交
9f34254da3
共有 3 个文件被更改,包括 42 次插入2 次删除
  1. 36 2
      driver/variant/iris3/src/msm_vidc_iris3.c
  2. 1 0
      driver/vidc/inc/msm_vidc_core.h
  3. 5 0
      driver/vidc/src/venus_hfi.c

+ 36 - 2
driver/variant/iris3/src/msm_vidc_iris3.c

@@ -110,6 +110,7 @@
 #define WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS3	(WRAPPER_BASE_OFFS_IRIS3 + 0x58)
 #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL	(WRAPPER_BASE_OFFS_IRIS3 + 0x5C)
 #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS		(WRAPPER_BASE_OFFS_IRIS3 + 0x60)
+#define WRAPPER_CORE_POWER_STATUS		(WRAPPER_BASE_OFFS_IRIS3 + 0x80)
 #define WRAPPER_CORE_CLOCK_CONFIG_IRIS3		(WRAPPER_BASE_OFFS_IRIS3 + 0x88)
 
 /*
@@ -448,14 +449,47 @@ static int __setup_ucregion_memory_map_iris3(struct msm_vidc_core *vidc_core)
 	return 0;
 }
 
+static bool is_iris3_hw_power_collapsed(struct msm_vidc_core *core)
+{
+	int rc = 0;
+	u32 value = 0, pwr_status = 0;
+
+	rc = __read_register(core, WRAPPER_CORE_POWER_STATUS, &value);
+	if (rc)
+		return false;
+
+	/* if BIT(1) is 1 then video hw power is on else off */
+	pwr_status = value & BIT(1);
+	return pwr_status ? false : true;
+}
+
 static int __power_off_iris3_hardware(struct msm_vidc_core *core)
 {
 	int rc = 0, i;
 	u32 value = 0;
+	bool pwr_collapsed = false;
 
+	/*
+	 * Incase hw power control is enabled, when CPU WD occurred, check for power
+	 * status to decide on executing NOC reset sequence before disabling power.
+	 * If there is no CPU WD and hw_power_control is enabled, fw is expected
+	 * to power collapse video hw always.
+	 */
 	if (core->hw_power_control) {
-		d_vpr_h("%s: hardware power control enabled\n", __func__);
-		goto disable_power;
+		pwr_collapsed = is_iris3_hw_power_collapsed(core);
+		if (core->cpu_watchdog) {
+			if (pwr_collapsed) {
+				d_vpr_e("%s: CPU WD and video hw power collapsed\n", __func__);
+				goto disable_power;
+			} else {
+				d_vpr_e("%s: CPU WD and video hw is power ON\n", __func__);
+			}
+		} else {
+			if (!pwr_collapsed)
+				d_vpr_e("%s: video hw is not power collapsed\n", __func__);
+
+			goto disable_power;
+		}
 	}
 
 	/*

+ 1 - 0
driver/vidc/inc/msm_vidc_core.h

@@ -119,6 +119,7 @@ struct msm_vidc_core {
 	bool                                   handoff_done;
 	bool                                   hw_power_control;
 	bool                                   pm_suspended;
+	bool                                   cpu_watchdog;
 };
 
 #endif // _MSM_VIDC_CORE_H_

+ 5 - 0
driver/vidc/src/venus_hfi.c

@@ -2456,6 +2456,7 @@ int __load_fw(struct msm_vidc_core *core)
 	d_vpr_h("%s\n", __func__);
 	core->handoff_done = false;
 	core->hw_power_control = false;
+	core->cpu_watchdog = false;
 
 	trace_msm_v4l2_vidc_fw_load("START");
 	rc = __init_resources(core);
@@ -2533,6 +2534,8 @@ void __unload_fw(struct msm_vidc_core *core)
 	__venus_power_off(core);
 	__deinit_resources(core);
 
+	core->cpu_watchdog = false;
+
 	d_vpr_h("%s done\n", __func__);
 }
 
@@ -2542,6 +2545,8 @@ static int __response_handler(struct msm_vidc_core *core)
 
 	if (call_venus_op(core, watchdog, core, core->intr_status)) {
 		struct hfi_packet pkt = {.type = HFI_SYS_ERROR_WD_TIMEOUT};
+		core->cpu_watchdog = true;
+		d_vpr_e("%s: CPU WD error received\n", __func__);
 
 		return handle_system_error(core, &pkt);
 	}