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

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

Merge "drm/msm/sde: update misr support for crtc and encoder" into msm-4.9

parents 98a4092c f9245d60
Loading
Loading
Loading
Loading
+144 −14
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ struct sde_crtc_irq_info {
#define LEFT_MIXER 0
#define RIGHT_MIXER 1

#define MISR_BUFF_SIZE			256

static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
{
	struct msm_drm_private *priv;
@@ -76,6 +78,35 @@ static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
	return to_sde_kms(priv->kms);
}

static inline int _sde_crtc_power_enable(struct sde_crtc *sde_crtc, bool enable)
{
	struct drm_crtc *crtc;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;

	if (!sde_crtc) {
		SDE_ERROR("invalid sde crtc\n");
		return -EINVAL;
	}

	crtc = &sde_crtc->base;
	if (!crtc->dev || !crtc->dev->dev_private) {
		SDE_ERROR("invalid drm device\n");
		return -EINVAL;
	}

	priv = crtc->dev->dev_private;
	if (!priv->kms) {
		SDE_ERROR("invalid kms\n");
		return -EINVAL;
	}

	sde_kms = to_sde_kms(priv->kms);

	return sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
									enable);
}

static void _sde_crtc_deinit_events(struct sde_crtc *sde_crtc)
{
	if (!sde_crtc)
@@ -1104,8 +1135,6 @@ static void _sde_crtc_vblank_enable_nolock(
	struct drm_device *dev;
	struct drm_crtc *crtc;
	struct drm_encoder *enc;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;

	if (!sde_crtc) {
		SDE_ERROR("invalid crtc\n");
@@ -1114,17 +1143,11 @@ static void _sde_crtc_vblank_enable_nolock(

	crtc = &sde_crtc->base;
	dev = crtc->dev;
	priv = dev->dev_private;

	if (!priv->kms) {
		SDE_ERROR("invalid kms\n");
	if (enable) {
		if (_sde_crtc_power_enable(sde_crtc, true))
			return;
	}
	sde_kms = to_sde_kms(priv->kms);

	if (enable) {
		sde_power_resource_enable(&priv->phandle,
				sde_kms->core_client, true);
		list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
			if (enc->crtc != crtc)
				continue;
@@ -1143,8 +1166,7 @@ static void _sde_crtc_vblank_enable_nolock(

			sde_encoder_register_vblank_callback(enc, NULL, NULL);
		}
		sde_power_resource_enable(&priv->phandle,
				sde_kms->core_client, false);
		_sde_crtc_power_enable(sde_crtc, false);
	}
}

@@ -2059,6 +2081,107 @@ static int _sde_debugfs_status_open(struct inode *inode, struct file *file)
	return single_open(file, _sde_debugfs_status_show, inode->i_private);
}

static ssize_t _sde_crtc_misr_setup(struct file *file,
		const char __user *user_buf, size_t count, loff_t *ppos)
{
	struct sde_crtc *sde_crtc;
	struct sde_crtc_mixer *m;
	int i = 0, rc;
	char buf[MISR_BUFF_SIZE + 1];
	u32 frame_count, enable;
	size_t buff_copy;

	if (!file || !file->private_data)
		return -EINVAL;

	sde_crtc = file->private_data;
	buff_copy = min_t(size_t, count, MISR_BUFF_SIZE);
	if (copy_from_user(buf, user_buf, buff_copy)) {
		SDE_ERROR("buffer copy failed\n");
		return -EINVAL;
	}

	buf[buff_copy] = 0; /* end of string */

	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);
	sde_crtc->misr_enable = enable;
	for (i = 0; i < sde_crtc->num_mixers; ++i) {
		m = &sde_crtc->mixers[i];
		if (!m->hw_lm)
			continue;

		m->hw_lm->ops.setup_misr(m->hw_lm, enable, frame_count);
	}
	mutex_unlock(&sde_crtc->crtc_lock);
	_sde_crtc_power_enable(sde_crtc, false);

	return count;
}

static ssize_t _sde_crtc_misr_read(struct file *file,
		char __user *user_buff, size_t count, loff_t *ppos)
{
	struct sde_crtc *sde_crtc;
	struct sde_crtc_mixer *m;
	int i = 0, rc;
	ssize_t len = 0;
	char buf[MISR_BUFF_SIZE + 1] = {'\0'};

	if (*ppos)
		return 0;

	if (!file || !file->private_data)
		return -EINVAL;

	sde_crtc = file->private_data;
	rc = _sde_crtc_power_enable(sde_crtc, true);
	if (rc)
		return rc;

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

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

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

buff_check:
	if (count <= len) {
		len = 0;
		goto end;
	}

	if (copy_to_user(user_buff, buf, len)) {
		len = -EFAULT;
		goto end;
	}

	*ppos += len;   /* increase offset */

end:
	mutex_unlock(&sde_crtc->crtc_lock);
	_sde_crtc_power_enable(sde_crtc, false);
	return len;
}

#define DEFINE_SDE_DEBUGFS_SEQ_FOPS(__prefix)                          \
static int __prefix ## _open(struct inode *inode, struct file *file)	\
{									\
@@ -2100,6 +2223,11 @@ static int _sde_crtc_init_debugfs(struct drm_crtc *crtc)
		.llseek =	seq_lseek,
		.release =	single_release,
	};
	static const struct file_operations debugfs_misr_fops = {
		.open =		simple_open,
		.read =		_sde_crtc_misr_read,
		.write =	_sde_crtc_misr_setup,
	};

	if (!crtc)
		return -EINVAL;
@@ -2122,6 +2250,8 @@ static int _sde_crtc_init_debugfs(struct drm_crtc *crtc)
			sde_crtc->debugfs_root,
			&sde_crtc->base,
			&sde_crtc_debugfs_state_fops);
	debugfs_create_file("misr_data", 0644, sde_crtc->debugfs_root,
					sde_crtc, &debugfs_misr_fops);

	return 0;
}
+2 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ struct sde_crtc_event {
 * @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.
 */
struct sde_crtc {
	struct drm_crtc base;
@@ -184,6 +185,7 @@ 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;
};

#define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
+104 −73
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@

#define MAX_CHANNELS_PER_ENC 2

#define MISR_BUFF_SIZE			256

/**
 * struct sde_encoder_virt - virtual encoder. Container of one or more physical
 *	encoders. Virtual encoder manages one "logical" display. Physical
@@ -90,6 +92,7 @@
 * @crtc_frame_event:		callback event
 * @frame_done_timeout:		frame done timeout in Hz
 * @frame_done_timer:		watchdog timer for frame done event
 * @misr_enable:		misr enable/disable status
 */
struct sde_encoder_virt {
	struct drm_encoder base;
@@ -120,6 +123,7 @@ struct sde_encoder_virt {
	struct sde_rsc_client *rsc_client;
	struct msm_display_info disp_info;
	bool rsc_state_update;
	bool misr_enable;
};

#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
@@ -131,6 +135,36 @@ inline bool _sde_is_dsc_enabled(struct sde_encoder_virt *sde_enc)
	return (comp_info->comp_type == MSM_DISPLAY_COMPRESSION_DSC);
}

static inline int _sde_encoder_power_enable(struct sde_encoder_virt *sde_enc,
								bool enable)
{
	struct drm_encoder *drm_enc;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;

	if (!sde_enc) {
		SDE_ERROR("invalid sde enc\n");
		return -EINVAL;
	}

	drm_enc = &sde_enc->base;
	if (!drm_enc->dev || !drm_enc->dev->dev_private) {
		SDE_ERROR("drm device invalid\n");
		return -EINVAL;
	}

	priv = drm_enc->dev->dev_private;
	if (!priv->kms) {
		SDE_ERROR("invalid kms\n");
		return -EINVAL;
	}

	sde_kms = to_sde_kms(priv->kms);

	return sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
									enable);
}

void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc,
		struct sde_encoder_hw_resources *hw_res,
		struct drm_connector_state *conn_state)
@@ -706,8 +740,6 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc = NULL;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	int i = 0;
	int ret = 0;

@@ -723,13 +755,13 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
	}

	sde_enc = to_sde_encoder_virt(drm_enc);
	priv = drm_enc->dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);

	SDE_DEBUG_ENC(sde_enc, "\n");
	SDE_EVT32(DRMID(drm_enc));

	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
	ret = _sde_encoder_power_enable(sde_enc, true);
	if (ret)
		return;

	sde_enc->cur_master = NULL;

@@ -810,7 +842,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)

	sde_rm_release(&sde_kms->rm, drm_enc);

	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
	_sde_encoder_power_enable(sde_enc, false);
}

static enum sde_intf sde_encoder_get_intf(struct sde_mdss_cfg *catalog,
@@ -1389,105 +1421,108 @@ static int _sde_encoder_debugfs_status_open(struct inode *inode,
	return single_open(file, _sde_encoder_status_show, inode->i_private);
}

static void _sde_set_misr_params(struct sde_encoder_phys *phys, u32 enable,
					u32 frame_count)
{
	int j;

	if (!phys->misr_map)
		return;

	phys->misr_map->enable = enable;

	if (frame_count <= SDE_CRC_BATCH_SIZE)
		phys->misr_map->frame_count = frame_count;
	else if (frame_count <= 0)
		phys->misr_map->frame_count = 0;
	else
		phys->misr_map->frame_count = SDE_CRC_BATCH_SIZE;

	if (!enable) {
		phys->misr_map->last_idx = 0;
		phys->misr_map->frame_count = 0;
		for (j = 0; j < SDE_CRC_BATCH_SIZE; j++)
			phys->misr_map->crc_value[j] = 0;
	}
}

static ssize_t _sde_encoder_misr_set(struct file *file,
static ssize_t _sde_encoder_misr_setup(struct file *file,
		const char __user *user_buf, size_t count, loff_t *ppos)
{
	struct sde_encoder_virt *sde_enc;
	struct drm_encoder *drm_enc;
	int i = 0;
	char buf[10];
	u32 enable, frame_count;
	int i = 0, rc;
	char buf[MISR_BUFF_SIZE + 1];
	size_t buff_copy;
	u32 frame_count, enable;

	drm_enc = file->private_data;
	sde_enc = to_sde_encoder_virt(drm_enc);
	if (!file || !file->private_data)
		return -EINVAL;

	if (copy_from_user(buf, user_buf, count))
		return -EFAULT;
	sde_enc = file->private_data;

	buf[count] = 0; /* end of string */
	buff_copy = min_t(size_t, count, MISR_BUFF_SIZE);
	if (copy_from_user(buf, user_buf, buff_copy))
		return -EINVAL;

	buf[buff_copy] = 0; /* end of string */

	if (sscanf(buf, "%u %u", &enable, &frame_count) != 2)
		return -EFAULT;
		return -EINVAL;

	rc = _sde_encoder_power_enable(sde_enc, true);
	if (rc)
		return rc;

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

		if (!phys || !phys->misr_map || !phys->ops.setup_misr)
		if (!phys || !phys->ops.setup_misr)
			continue;

		_sde_set_misr_params(phys, enable, frame_count);
		phys->ops.setup_misr(phys, phys->misr_map);
		phys->ops.setup_misr(phys, enable, frame_count);
	}
	mutex_unlock(&sde_enc->enc_lock);
	_sde_encoder_power_enable(sde_enc, false);

	return count;
}

static ssize_t _sde_encoder_misr_read(
		struct file *file,
		char __user *buff, size_t count, loff_t *ppos)
static ssize_t _sde_encoder_misr_read(struct file *file,
		char __user *user_buff, size_t count, loff_t *ppos)
{
	struct sde_encoder_virt *sde_enc;
	struct drm_encoder *drm_enc;
	int i = 0, j = 0, len = 0;
	char buf[512] = {'\0'};
	int i = 0, len = 0;
	char buf[MISR_BUFF_SIZE + 1] = {'\0'};
	int rc;

	if (*ppos)
		return 0;

	drm_enc = file->private_data;
	sde_enc = to_sde_encoder_virt(drm_enc);
	if (!file || !file->private_data)
		return -EINVAL;

	sde_enc = file->private_data;

	rc = _sde_encoder_power_enable(sde_enc, true);
	if (rc)
		return rc;

	mutex_lock(&sde_enc->enc_lock);
	if (!sde_enc->misr_enable) {
		len += snprintf(buf + len, MISR_BUFF_SIZE - len,
			"disabled\n");
		goto buff_check;
	} else if (sde_enc->disp_info.capabilities &
						~MSM_DISPLAY_CAP_VID_MODE) {
		len += snprintf(buf + len, MISR_BUFF_SIZE - len,
			"unsupported\n");
		goto buff_check;
	}

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
		struct sde_misr_params *misr_map;

		if (!phys || !phys->misr_map)
		if (!phys || !phys->ops.collect_misr)
			continue;

		misr_map = phys->misr_map;

		len += snprintf(buf+len, sizeof(buf), "INTF%d\n", i);
		for (j = 0; j < SDE_CRC_BATCH_SIZE; j++)
			len += snprintf(buf+len, sizeof(buf), "%x\n",
						misr_map->crc_value[j]);
		len += snprintf(buf + len, MISR_BUFF_SIZE - len,
			"Intf idx:%d\n", phys->intf_idx - INTF_0);
		len += snprintf(buf + len, MISR_BUFF_SIZE - len, "0x%x\n",
					phys->ops.collect_misr(phys));
	}

	if (len < 0 || len >= sizeof(buf))
		return 0;
buff_check:
	if (count <= len) {
		len = 0;
		goto end;
	}

	if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
		return -EFAULT;
	if (copy_to_user(user_buff, buf, len)) {
		len = -EFAULT;
		goto end;
	}

	*ppos += len;   /* increase offset */
	mutex_unlock(&sde_enc->enc_lock);

end:
	mutex_unlock(&sde_enc->enc_lock);
	_sde_encoder_power_enable(sde_enc, false);
	return len;
}

@@ -1507,7 +1542,7 @@ static int _sde_encoder_init_debugfs(struct drm_encoder *drm_enc)
	static const struct file_operations debugfs_misr_fops = {
		.open = simple_open,
		.read = _sde_encoder_misr_read,
		.write = _sde_encoder_misr_set,
		.write = _sde_encoder_misr_setup,
	};

	char name[SDE_NAME_SIZE];
@@ -1534,7 +1569,7 @@ static int _sde_encoder_init_debugfs(struct drm_encoder *drm_enc)
		sde_enc->debugfs_root, sde_enc, &debugfs_status_fops);

	debugfs_create_file("misr_data", 0644,
		sde_enc->debugfs_root, drm_enc, &debugfs_misr_fops);
		sde_enc->debugfs_root, sde_enc, &debugfs_misr_fops);

	return 0;
}
@@ -1896,10 +1931,6 @@ int sde_encoder_wait_for_commit_done(struct drm_encoder *drm_enc)
			if (ret)
				return ret;
		}

		if (phys && phys->ops.collect_misr)
			if (phys->misr_map && phys->misr_map->enable)
				phys->ops.collect_misr(phys, phys->misr_map);
	}

	return ret;
+2 −5
Original line number Diff line number Diff line
@@ -147,9 +147,8 @@ struct sde_encoder_phys_ops {
	bool (*needs_single_flush)(struct sde_encoder_phys *phys_enc);

	void (*setup_misr)(struct sde_encoder_phys *phys_encs,
			struct sde_misr_params *misr_map);
	void (*collect_misr)(struct sde_encoder_phys *phys_enc,
			struct sde_misr_params *misr_map);
				bool enable, u32 frame_count);
	u32 (*collect_misr)(struct sde_encoder_phys *phys_enc);
	void (*hw_reset)(struct sde_encoder_phys *phys_enc);
};

@@ -183,7 +182,6 @@ enum sde_intr_idx {
 * @hw_pp:		Hardware interface to the ping pong registers
 * @sde_kms:		Pointer to the sde_kms top level
 * @cached_mode:	DRM mode cached at mode_set time, acted on in enable
 * @misr_map:		Interface for setting and collecting MISR data
 * @enabled:		Whether the encoder has enabled and running a mode
 * @split_role:		Role to play in a split-panel configuration
 * @intf_mode:		Interface mode
@@ -212,7 +210,6 @@ struct sde_encoder_phys {
	struct sde_hw_pingpong *hw_pp;
	struct sde_kms *sde_kms;
	struct drm_display_mode cached_mode;
	struct sde_misr_params *misr_map;
	enum sde_enc_split_role split_role;
	enum sde_intf_mode intf_mode;
	enum sde_intf intf_idx;
+17 −18
Original line number Diff line number Diff line
@@ -830,23 +830,29 @@ static void sde_encoder_phys_vid_handle_post_kickoff(
}

static void sde_encoder_phys_vid_setup_misr(struct sde_encoder_phys *phys_enc,
			struct sde_misr_params *misr_map)
						bool enable, u32 frame_count)
{
	struct sde_encoder_phys_vid *vid_enc =
		to_sde_encoder_phys_vid(phys_enc);
	struct sde_encoder_phys_vid *vid_enc;

	if (!phys_enc)
		return;
	vid_enc = to_sde_encoder_phys_vid(phys_enc);

	if (vid_enc && vid_enc->hw_intf && vid_enc->hw_intf->ops.setup_misr)
		vid_enc->hw_intf->ops.setup_misr(vid_enc->hw_intf, misr_map);
	if (vid_enc->hw_intf && vid_enc->hw_intf->ops.setup_misr)
		vid_enc->hw_intf->ops.setup_misr(vid_enc->hw_intf,
							enable, frame_count);
}

static void sde_encoder_phys_vid_collect_misr(struct sde_encoder_phys *phys_enc,
			struct sde_misr_params *misr_map)
static u32 sde_encoder_phys_vid_collect_misr(struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_phys_vid *vid_enc =
			to_sde_encoder_phys_vid(phys_enc);
	struct sde_encoder_phys_vid *vid_enc;

	if (!phys_enc)
		return 0;
	vid_enc = to_sde_encoder_phys_vid(phys_enc);

	if (vid_enc && vid_enc->hw_intf && vid_enc->hw_intf->ops.collect_misr)
		vid_enc->hw_intf->ops.collect_misr(vid_enc->hw_intf, misr_map);
	return vid_enc->hw_intf && vid_enc->hw_intf->ops.collect_misr ?
		vid_enc->hw_intf->ops.collect_misr(vid_enc->hw_intf) : 0;
}

static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops)
@@ -919,13 +925,6 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
		goto fail;
	}

	phys_enc->misr_map = kzalloc(sizeof(struct sde_misr_params),
						GFP_KERNEL);
	if (!phys_enc->misr_map) {
		ret = -ENOMEM;
		goto fail;
	}

	SDE_DEBUG_VIDENC(vid_enc, "\n");

	sde_encoder_phys_vid_init_ops(&phys_enc->ops);
Loading