Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 925f5828 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Restore the threshold registers after GDSC hand offs"

parents 4c7d27bf fadcc721
Loading
Loading
Loading
Loading
+47 −5
Original line number Diff line number Diff line
@@ -59,11 +59,12 @@ struct tzbsp_resp {

enum tzbsp_video_state {
	TZBSP_VIDEO_STATE_SUSPEND = 0,
	TZBSP_VIDEO_STATE_RESUME
	TZBSP_VIDEO_STATE_RESUME = 1,
	TZBSP_VIDEO_STATE_RESTORE_THRESHOLD = 2,
};

struct tzbsp_video_set_state_req {
	u32 state; /*shoud be tzbsp_video_state enum value*/
	u32 state; /* should be tzbsp_video_state enum value */
	u32 spare; /* reserved for future, should be zero */
};

@@ -93,6 +94,7 @@ static int __iface_cmdq_write(struct venus_hfi_device *device,
					void *pkt);
static int __load_fw(struct venus_hfi_device *device);
static void __unload_fw(struct venus_hfi_device *device);
static int __tzbsp_set_video_state(enum tzbsp_video_state state);


/**
@@ -698,6 +700,25 @@ static void __set_registers(struct venus_hfi_device *device)
	}
}

/*
 * The existence of this function is a hack for 8996 (or certain Venus versions)
 * to overcome a hardware bug.  Whenever the GDSCs momentarily power collapse
 * (after calling __hand_off_regulators()), the values of the threshold
 * registers (typically programmed by TZ) are incorrectly reset.  As a result
 * reprogram these registers at certain agreed upon points.
 */
static void __set_threshold_registers(struct venus_hfi_device *device)
{
	u32 version = __read_register(device, VIDC_WRAPPER_HW_VERSION);

	version &= ~GENMASK(15, 0);
	if (version != (0x3 << 28 | 0x43 << 16))
		return;

	if (__tzbsp_set_video_state(TZBSP_VIDEO_STATE_RESTORE_THRESHOLD))
		dprintk(VIDC_ERR, "Failed to restore threshold values\n");
}

static void __iommu_detach(struct venus_hfi_device *device)
{
	struct context_bank_info *cb;
@@ -1196,7 +1217,7 @@ free_failed:
	return rc;
}

static inline int __tzbsp_set_video_state(enum tzbsp_video_state state)
static int __tzbsp_set_video_state(enum tzbsp_video_state state)
{
	struct tzbsp_video_set_state_req cmd = {0};
	int tzbsp_rsp = 0;
@@ -3429,6 +3450,16 @@ static int __response_handler(struct venus_hfi_device *device)
			 */
			--packet_count;
			break;
		case HAL_SESSION_LOAD_RESOURCE_DONE:
			/*
			 * Work around for H/W bug, need to re-program these
			 * registers as part of a handshake agreement with the
			 * firmware.  This strictly only needs to be done for
			 * decoder secure sessions, but there's no harm in doing
			 * so for all sessions as it's at worst a NO-OP.
			 */
			__set_threshold_registers(device);
			break;
		default:
			break;
		}
@@ -4173,7 +4204,12 @@ static int __venus_power_on(struct venus_hfi_device *device)
	device->intr_status = 0;
	enable_irq(device->hal_data->irq);

	/* Hand off control of regulators to h/w _after_ enabling clocks */
	/*
	 * Hand off control of regulators to h/w _after_ enabling clocks.
	 * Note that the GDSC will turn off when switching from normal
	 * (s/w triggered) to fast (HW triggered) unless the h/w vote is
	 * present. Since Venus isn't up yet, the GDSC will be off briefly.
	 */
	if (__enable_hw_power_collapse(device))
		dprintk(VIDC_ERR, "Failed to enabled inter-frame PC\n");

@@ -4307,6 +4343,12 @@ static inline int __resume(struct venus_hfi_device *device)
		goto err_reset_core;
	}

	/*
	 * Work around for H/W bug, need to reprogram these registers once
	 * firmware is out reset
	 */
	__set_threshold_registers(device);

	dprintk(VIDC_INFO, "Resumed from power collapse\n");
	return rc;
err_reset_core: