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

Commit 79041933 authored by Gurpreet Singh Dhami's avatar Gurpreet Singh Dhami
Browse files

drm/msm/sde: enable lm misr after frame trigger



Perform MISR enable after frame trigger and then collect misr after
status bit is set. Previously misr was enabled through debugfs, so if
system goes into idle power collapse before commit, then misr enable
status was not retained. Also it was not waiting for misr status bit.

Change-Id: Ifc3030c08c3e43e0bd58e81ce15208c1938c76a2
Signed-off-by: default avatarGurpreet Singh Dhami <gdhami@codeaurora.org>
parent a4f0340b
Loading
Loading
Loading
Loading
+66 −48
Original line number Diff line number Diff line
@@ -3640,8 +3640,7 @@ static void sde_crtc_handle_power_event(u32 event_type, void *arg)
	struct sde_crtc_state *cstate;
	struct drm_plane *plane;
	struct drm_encoder *encoder;
	struct sde_crtc_mixer *m;
	u32 i, misr_status, power_on;
	u32 power_on;
	unsigned long flags;
	struct sde_crtc_irq_info *node = NULL;
	int ret = 0;
@@ -3689,16 +3688,6 @@ static void sde_crtc_handle_power_event(u32 event_type, void *arg)
		spin_unlock_irqrestore(&sde_crtc->spin_lock, flags);

		sde_cp_crtc_post_ipc(crtc);

		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:
		/* enable mdp LUT memory retention */
@@ -3721,17 +3710,6 @@ static void sde_crtc_handle_power_event(u32 event_type, void *arg)
			sde_encoder_control_te(encoder, false);
		}

		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];
		}

		spin_lock_irqsave(&sde_crtc->spin_lock, flags);
		node = NULL;
		list_for_each_entry(node, &sde_crtc->user_event_list, list) {
@@ -5223,10 +5201,9 @@ void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count)
	}
	sde_crtc = to_sde_crtc(crtc);

	sde_crtc->misr_enable = enable;
	sde_crtc->misr_enable_sui = 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 || !m->hw_lm->ops.setup_misr)
			continue;
@@ -5235,6 +5212,40 @@ void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count)
	}
}

void sde_crtc_get_misr_info(struct drm_crtc *crtc,
			struct sde_crtc_misr_info *crtc_misr_info)
{
	struct sde_crtc *sde_crtc;
	struct sde_kms *sde_kms;

	if (!crtc_misr_info) {
		SDE_ERROR("invalid misr info\n");
		return;
	}

	crtc_misr_info->misr_enable = false;
	crtc_misr_info->misr_frame_count = 0;

	if (!crtc) {
		SDE_ERROR("invalid crtc\n");
		return;
	}

	sde_kms = _sde_crtc_get_kms(crtc);
	if (!sde_kms) {
		SDE_ERROR("invalid sde_kms\n");
		return;
	}

	if (sde_kms_is_secure_session_inprogress(sde_kms))
		return;

	sde_crtc = to_sde_crtc(crtc);
	crtc_misr_info->misr_enable =
			sde_crtc->misr_enable_debugfs ? true : false;
	crtc_misr_info->misr_frame_count = sde_crtc->misr_frame_count;
}

#ifdef CONFIG_DEBUG_FS
static int _sde_debugfs_status_show(struct seq_file *s, void *data)
{
@@ -5414,20 +5425,18 @@ static ssize_t _sde_crtc_misr_setup(struct file *file,
	if (sscanf(buf, "%u %u", &enable, &frame_count) != 2)
		return -EINVAL;

	rc = _sde_crtc_power_enable(sde_crtc, true);
	if (rc)
		return rc;

	mutex_lock(&sde_crtc->crtc_lock);
	if (sde_kms_is_secure_session_inprogress(sde_kms)) {
		SDE_DEBUG("crtc:%d misr enable/disable not allowed\n",
				DRMID(crtc));
		goto end;
		return -EINVAL;
	}
	sde_crtc_misr_setup(crtc, enable, frame_count);

end:
	mutex_unlock(&sde_crtc->crtc_lock);
	rc = _sde_crtc_power_enable(sde_crtc, true);
	if (rc)
		return rc;

	sde_crtc->misr_enable_debugfs = enable;
	sde_crtc_misr_setup(crtc, enable, frame_count);
	_sde_crtc_power_enable(sde_crtc, false);

	return count;
@@ -5441,7 +5450,6 @@ static ssize_t _sde_crtc_misr_read(struct file *file,
	struct sde_kms *sde_kms;
	struct sde_crtc_mixer *m;
	int i = 0, rc;
	u32 misr_status;
	ssize_t len = 0;
	char buf[MISR_BUFF_SIZE + 1] = {'\0'};

@@ -5461,30 +5469,41 @@ static ssize_t _sde_crtc_misr_read(struct file *file,
	if (rc)
		return rc;

	mutex_lock(&sde_crtc->crtc_lock);
	if (sde_kms_is_secure_session_inprogress(sde_kms)) {
		SDE_DEBUG("crtc:%d misr read not allowed\n", DRMID(crtc));
		goto end;
	}

	if (!sde_crtc->misr_enable) {
		len += snprintf(buf + len, MISR_BUFF_SIZE - len,
	if (!sde_crtc->misr_enable_debugfs) {
		len += scnprintf(buf + len, MISR_BUFF_SIZE - len,
				"disabled\n");
		goto buff_check;
	}

	for (i = 0; i < sde_crtc->num_mixers; ++i) {
		u32 misr_value = 0;

		m = &sde_crtc->mixers[i];
		if (!m->hw_lm || !m->hw_lm->ops.collect_misr)
		if (!m->hw_lm || !m->hw_lm->ops.collect_misr) {
			len += scnprintf(buf + len, MISR_BUFF_SIZE - len,
					"invalid\n");
			SDE_ERROR("crtc:%d invalid misr ops\n", DRMID(crtc));
			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",
							sde_crtc->misr_data[i]);
		rc = m->hw_lm->ops.collect_misr(m->hw_lm, false, &misr_value);
		if (rc) {
			len += scnprintf(buf + len, MISR_BUFF_SIZE - len,
					"invalid\n");
			SDE_ERROR("crtc:%d failed to collect misr %d\n",
					DRMID(crtc), rc);
			continue;
		} else {
			len += scnprintf(buf + len, MISR_BUFF_SIZE - len,
					"lm idx:%d\n", m->hw_lm->idx - LM_0);
			len += scnprintf(buf + len, MISR_BUFF_SIZE - len,
					"0x%x\n", misr_value);
		}
	}

buff_check:
@@ -5501,7 +5520,6 @@ static ssize_t _sde_crtc_misr_read(struct file *file,
	*ppos += len;   /* increase offset */

end:
	mutex_unlock(&sde_crtc->crtc_lock);
	_sde_crtc_power_enable(sde_crtc, false);
	return len;
}
+25 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
 * Copyright (C) 2013 Red Hat
 * Author: Rob Clark <robdclark@gmail.com>
 *
@@ -184,6 +184,16 @@ struct sde_ltm_buffer {
	struct list_head node;
};

/**
 * struct sde_crtc_misr_info - structure for misr information
 * @misr_enable : enable/disable flag
 * @misr_frame_count : Number of frames for misr calculation.
 */
struct sde_crtc_misr_info {
	bool misr_enable;
	u32 misr_frame_count;
};

/*
 * Maximum number of free event structures to cache
 */
@@ -234,7 +244,10 @@ struct sde_ltm_buffer {
 * @event_cache   : Local cache of event worker structures
 * @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_enable_sui : boolean entry indicates misr enable/disable status
 *                    for secure cases.
 * @misr_enable_debugfs : boolean entry indicates misr enable/disable status
 *                        from debugfs.
 * @misr_frame_count  : misr frame count provided by client
 * @misr_data     : store misr data before turning off the clocks.
 * @idle_notify_work: delayed worker to notify idle timeout to user space
@@ -304,10 +317,9 @@ struct sde_crtc {
	struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT];
	struct list_head event_free_list;
	spinlock_t event_lock;
	bool misr_enable;
	bool misr_enable_sui;
	bool misr_enable_debugfs;
	u32 misr_frame_count;
	u32 misr_data[CRTC_DUAL_MIXERS];

	struct kthread_delayed_work idle_notify_work;

	struct sde_power_event *power_event;
@@ -751,4 +763,12 @@ void sde_crtc_update_cont_splash_settings(
 */
void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count);

/**
 * sde_crtc_get_misr_info - to configure and enable/disable MISR
 * @crtc: Pointer to drm crtc structure
 * @crtc_misr_info: Pointer to crtc misr info structure
 */
void sde_crtc_get_misr_info(struct drm_crtc *crtc,
		struct sde_crtc_misr_info *crtc_misr_info);

#endif /* _SDE_CRTC_H_ */
+6 −0
Original line number Diff line number Diff line
@@ -3906,6 +3906,7 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc)
	struct msm_drm_private *priv = NULL;
	struct sde_kms *sde_kms = NULL;
	bool is_vid_mode = false;
	struct sde_crtc_misr_info crtc_misr_info = {false, 0};

	if (!sde_enc) {
		SDE_ERROR("invalid encoder\n");
@@ -3975,6 +3976,11 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc)
		sde_encoder_misr_configure(&sde_enc->base, true,
				sde_enc->misr_frame_count);

	sde_crtc_get_misr_info(sde_enc->crtc, &crtc_misr_info);
	if (crtc_misr_info.misr_enable)
		sde_crtc_misr_setup(sde_enc->crtc, true,
				crtc_misr_info.misr_frame_count);

	_sde_encoder_trigger_start(sde_enc->cur_master);

	if (sde_enc->elevated_ahb_vote) {
+28 −3
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 */

#include <linux/iopoll.h>

#include "sde_kms.h"
#include "sde_hw_catalog.h"
#include "sde_hwio.h"
@@ -243,11 +245,34 @@ static void sde_hw_lm_setup_misr(struct sde_hw_mixer *ctx,
	SDE_REG_WRITE(c, LM_MISR_CTRL, config);
}

static u32 sde_hw_lm_collect_misr(struct sde_hw_mixer *ctx)
static int sde_hw_lm_collect_misr(struct sde_hw_mixer *ctx, bool nonblock,
		u32 *misr_value)
{
	struct sde_hw_blk_reg_map *c = &ctx->hw;
	u32 ctrl = 0;

	if (!misr_value)
		return -EINVAL;

	ctrl = SDE_REG_READ(c, LM_MISR_CTRL);
	if (!nonblock) {
		if (ctrl & MISR_CTRL_ENABLE) {
			int rc;

			rc = readl_poll_timeout(c->base_off + c->blk_off +
					LM_MISR_CTRL, ctrl,
					(ctrl & MISR_CTRL_STATUS) > 0, 500,
					84000);
			if (rc)
				return rc;
		} else {
			return -EINVAL;
		}
	}

	*misr_value  = SDE_REG_READ(c, LM_MISR_SIGNATURE);

	return SDE_REG_READ(c, LM_MISR_SIGNATURE);
	return 0;
}

static void _setup_mixer_ops(struct sde_mdss_cfg *m,
+3 −2
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 */

#ifndef _SDE_HW_LM_H
@@ -79,7 +79,8 @@ struct sde_hw_lm_ops {
			bool enable, u32 frame_count);

	/* collect_misr: reads and stores MISR data from HW register */
	u32 (*collect_misr)(struct sde_hw_mixer *ctx);
	int (*collect_misr)(struct sde_hw_mixer *ctx, bool nonblock,
			u32 *misr_value);
};

struct sde_hw_mixer {