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

Commit 010f517c authored by Dhaval Patel's avatar Dhaval Patel
Browse files

drm/msm/sde: return last misr status during idle pc



Certain SDE clients like ad4 may want to collect the last
misr status during idle power collapse state. MISR enable
should not leave the leave the mdp clock in enabled state
because it may conflict with ad4 + retention mode. This patch
stores the last misr state on layer mixer and returns to
client when clocks are off. It also re-enable this feature
during power restore state.

Change-Id: I9bc66bed25640230169c11cd9c398dc0a1eba9c8
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 9e017f3e
Loading
Loading
Loading
Loading
+42 −9
Original line number Diff line number Diff line
@@ -2421,9 +2421,11 @@ static void sde_crtc_handle_power_event(u32 event_type, void *arg)
{
	struct drm_crtc *crtc = arg;
	struct sde_crtc *sde_crtc;
	struct drm_plane *plane;
	struct drm_encoder *encoder;
	struct sde_crtc_mixer *m;
	struct drm_event event;
	u32 power_on = 0;
	u32 power_on = 0, i, misr_status;

	if (!crtc) {
		SDE_ERROR("invalid crtc\n");
@@ -2435,7 +2437,8 @@ static void sde_crtc_handle_power_event(u32 event_type, void *arg)

	SDE_EVT32(DRMID(crtc), event_type);

	if (event_type == SDE_POWER_EVENT_POST_ENABLE) {
	switch (event_type) {
	case SDE_POWER_EVENT_POST_ENABLE:
		/* restore encoder; crtc will be programmed during commit */
		drm_for_each_encoder(encoder, crtc->dev) {
			if (encoder->crtc != crtc)
@@ -2450,9 +2453,31 @@ static void sde_crtc_handle_power_event(u32 event_type, void *arg)
		power_on = 1;
		msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
				(u8 *)&power_on);
	} else if (event_type == SDE_POWER_EVENT_POST_DISABLE) {
		struct drm_plane *plane;

		for (i = 0; i < sde_crtc->num_mixers; ++i) {
			m = &sde_crtc->mixers[i];
			if (!m->hw_lm || !m->hw_lm->ops.setup_misr ||
					!sde_crtc->misr_enable)
				continue;

			m->hw_lm->ops.setup_misr(m->hw_lm, true,
					sde_crtc->misr_frame_count);
		}
		break;
	case SDE_POWER_EVENT_PRE_DISABLE:
		for (i = 0; i < sde_crtc->num_mixers; ++i) {
			m = &sde_crtc->mixers[i];
			if (!m->hw_lm || !m->hw_lm->ops.collect_misr ||
					!sde_crtc->misr_enable)
				continue;

			misr_status = m->hw_lm->ops.collect_misr(m->hw_lm);
			sde_crtc->misr_data[i] = misr_status ? misr_status :
							sde_crtc->misr_data[i];
		}
		sde_cp_crtc_pre_ipc(crtc);
		break;
	case SDE_POWER_EVENT_POST_DISABLE:
		/*
		 * set revalidate flag in planes, so it will be re-programmed
		 * in the next frame update
@@ -2467,8 +2492,10 @@ static void sde_crtc_handle_power_event(u32 event_type, void *arg)
		power_on = 0;
		msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
				(u8 *)&power_on);
	} else if (event_type == SDE_POWER_EVENT_PRE_DISABLE) {
		sde_cp_crtc_pre_ipc(crtc);
		break;
	default:
		SDE_DEBUG("event:%d not handled\n", event_type);
		break;
	}

	mutex_unlock(&sde_crtc->crtc_lock);
@@ -3631,9 +3658,11 @@ static ssize_t _sde_crtc_misr_setup(struct file *file,

	mutex_lock(&sde_crtc->crtc_lock);
	sde_crtc->misr_enable = enable;
	sde_crtc->misr_frame_count = frame_count;
	for (i = 0; i < sde_crtc->num_mixers; ++i) {
		sde_crtc->misr_data[i] = 0;
		m = &sde_crtc->mixers[i];
		if (!m->hw_lm)
		if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
			continue;

		m->hw_lm->ops.setup_misr(m->hw_lm, enable, frame_count);
@@ -3650,6 +3679,7 @@ static ssize_t _sde_crtc_misr_read(struct file *file,
	struct sde_crtc *sde_crtc;
	struct sde_crtc_mixer *m;
	int i = 0, rc;
	u32 misr_status;
	ssize_t len = 0;
	char buf[MISR_BUFF_SIZE + 1] = {'\0'};

@@ -3673,13 +3703,16 @@ static ssize_t _sde_crtc_misr_read(struct file *file,

	for (i = 0; i < sde_crtc->num_mixers; ++i) {
		m = &sde_crtc->mixers[i];
		if (!m->hw_lm)
		if (!m->hw_lm || !m->hw_lm->ops.collect_misr)
			continue;

		misr_status = m->hw_lm->ops.collect_misr(m->hw_lm);
		sde_crtc->misr_data[i] = misr_status ? misr_status :
							sde_crtc->misr_data[i];
		len += snprintf(buf + len, MISR_BUFF_SIZE - len, "lm idx:%d\n",
					m->hw_lm->idx - LM_0);
		len += snprintf(buf + len, MISR_BUFF_SIZE - len, "0x%x\n",
				m->hw_lm->ops.collect_misr(m->hw_lm));
							sde_crtc->misr_data[i]);
	}

buff_check:
+4 −0
Original line number Diff line number Diff line
@@ -142,6 +142,8 @@ struct sde_crtc_event {
 * @event_free_list : List of available event structures
 * @event_lock    : Spinlock around event handling code
 * @misr_enable   : boolean entry indicates misr enable/disable status.
 * @misr_frame_count  : misr frame count provided by client
 * @misr_data     : store misr data before turning off the clocks.
 * @power_event   : registered power event handle
 * @cur_perf      : current performance committed to clock/bandwidth driver
 */
@@ -194,6 +196,8 @@ struct sde_crtc {
	struct list_head event_free_list;
	spinlock_t event_lock;
	bool misr_enable;
	u32 misr_frame_count;
	u32 misr_data[CRTC_DUAL_MIXERS];

	struct sde_power_event *power_event;

+8 −0
Original line number Diff line number Diff line
@@ -185,6 +185,7 @@ enum sde_enc_rc_states {
 * @disp_info:			local copy of msm_display_info struct
 * @mode_info:			local copy of msm_mode_info struct
 * @misr_enable:		misr enable/disable status
 * @misr_frame_count:		misr frame count before start capturing the data
 * @idle_pc_supported:		indicate if idle power collaps is supported
 * @rc_lock:			resource control mutex lock to protect
 *				virt encoder over various state changes
@@ -229,6 +230,7 @@ struct sde_encoder_virt {
	struct msm_display_info disp_info;
	struct msm_mode_info mode_info;
	bool misr_enable;
	u32 misr_frame_count;

	bool idle_pc_supported;
	struct mutex rc_lock;
@@ -2021,6 +2023,11 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
			else if (phys->ops.enable)
				phys->ops.enable(phys);
		}

		if (sde_enc->misr_enable && (sde_enc->disp_info.capabilities &
		     MSM_DISPLAY_CAP_VID_MODE) && phys->ops.setup_misr)
			phys->ops.setup_misr(phys, true,
						sde_enc->misr_frame_count);
	}

	if (msm_is_mode_seamless_dms(cur_mode) &&
@@ -2926,6 +2933,7 @@ static ssize_t _sde_encoder_misr_setup(struct file *file,

	mutex_lock(&sde_enc->enc_lock);
	sde_enc->misr_enable = enable;
	sde_enc->misr_frame_count = frame_count;
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];