Loading drivers/gpu/drm/msm/sde/sde_crtc.c +66 −48 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 */ Loading @@ -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) { Loading Loading @@ -5236,10 +5214,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; Loading @@ -5248,6 +5225,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) { Loading Loading @@ -5427,20 +5438,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; Loading @@ -5454,7 +5463,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'}; Loading @@ -5474,30 +5482,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: Loading @@ -5514,7 +5533,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; } Loading drivers/gpu/drm/msm/sde/sde_crtc.h +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> * Loading Loading @@ -185,6 +185,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 */ Loading Loading @@ -235,7 +245,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 Loading Loading @@ -305,10 +318,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; Loading Loading @@ -752,4 +764,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_ */ drivers/gpu/drm/msm/sde/sde_encoder.c +100 −26 Original line number Diff line number Diff line Loading @@ -2157,6 +2157,28 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc, return 0; } static void sde_encoder_misr_configure(struct drm_encoder *drm_enc, bool enable, u32 frame_count) { struct sde_encoder_virt *sde_enc; int i; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return; } sde_enc = to_sde_encoder_virt(drm_enc); for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; if (!phys || !phys->ops.setup_misr) continue; phys->ops.setup_misr(phys, enable, frame_count); } } static void sde_encoder_input_event_handler(struct input_handle *handle, unsigned int type, unsigned int code, int value) { Loading Loading @@ -3884,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"); Loading Loading @@ -3949,6 +3972,15 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc) } } if (sde_enc->misr_enable) 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) { Loading Loading @@ -4790,6 +4822,28 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc) } } void sde_encoder_helper_setup_misr(struct sde_encoder_phys *phys_enc, bool enable, u32 frame_count) { if (!phys_enc) return; if (phys_enc->hw_intf && phys_enc->hw_intf->ops.setup_misr) phys_enc->hw_intf->ops.setup_misr(phys_enc->hw_intf, enable, frame_count); } int sde_encoder_helper_collect_misr(struct sde_encoder_phys *phys_enc, bool nonblock, u32 *misr_value) { if (!phys_enc) return -EINVAL; return phys_enc->hw_intf && phys_enc->hw_intf->ops.collect_misr ? phys_enc->hw_intf->ops.collect_misr(phys_enc->hw_intf, nonblock, misr_value) : -ENOTSUPP; } #ifdef CONFIG_DEBUG_FS static int _sde_encoder_status_show(struct seq_file *s, void *data) { Loading Loading @@ -4846,15 +4900,27 @@ 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; int i = 0, rc; int rc; char buf[MISR_BUFF_SIZE + 1]; size_t buff_copy; u32 frame_count, enable; struct msm_drm_private *priv = NULL; struct sde_kms *sde_kms = NULL; if (!file || !file->private_data) return -EINVAL; sde_enc = file->private_data; priv = sde_enc->base.dev->dev_private; if (!sde_enc || !priv || !priv->kms) return -EINVAL; sde_kms = to_sde_kms(priv->kms); if (sde_kms_is_secure_session_inprogress(sde_kms)) { SDE_DEBUG_ENC(sde_enc, "misr enable/disable not allowed\n"); return -ENOTSUPP; } buff_copy = min_t(size_t, count, MISR_BUFF_SIZE); if (copy_from_user(buf, user_buf, buff_copy)) Loading @@ -4869,20 +4935,10 @@ static ssize_t _sde_encoder_misr_setup(struct file *file, if (rc) return rc; 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]; if (!phys || !phys->ops.setup_misr) continue; phys->ops.setup_misr(phys, enable, frame_count); } mutex_unlock(&sde_enc->enc_lock); sde_encoder_misr_configure(&sde_enc->base, enable, frame_count); _sde_encoder_power_enable(sde_enc, false); return count; } Loading @@ -4890,6 +4946,8 @@ 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 msm_drm_private *priv = NULL; struct sde_kms *sde_kms = NULL; int i = 0, len = 0; char buf[MISR_BUFF_SIZE + 1] = {'\0'}; int rc; Loading @@ -4901,33 +4959,50 @@ static ssize_t _sde_encoder_misr_read(struct file *file, return -EINVAL; sde_enc = file->private_data; priv = sde_enc->base.dev->dev_private; if (priv != NULL) sde_kms = to_sde_kms(priv->kms); if (sde_kms_is_secure_session_inprogress(sde_kms)) { SDE_DEBUG_ENC(sde_enc, "misr read not allowed\n"); return -ENOTSUPP; } 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, len += scnprintf(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]; u32 misr_value = 0; if (!phys || !phys->ops.collect_misr) if (!phys || !phys->ops.collect_misr) { len += scnprintf(buf + len, MISR_BUFF_SIZE - len, "invalid\n"); SDE_ERROR_ENC(sde_enc, "invalid misr ops\n"); continue; } 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)); rc = phys->ops.collect_misr(phys, false, &misr_value); if (rc) { len += scnprintf(buf + len, MISR_BUFF_SIZE - len, "invalid\n"); SDE_ERROR_ENC(sde_enc, "failed to collect misr %d\n", rc); continue; } else { len += scnprintf(buf + len, MISR_BUFF_SIZE - len, "Intf idx:%d\n", phys->intf_idx - INTF_0); len += scnprintf(buf + len, MISR_BUFF_SIZE - len, "0x%x\n", misr_value); } } buff_check: Loading @@ -4944,7 +5019,6 @@ static ssize_t _sde_encoder_misr_read(struct file *file, *ppos += len; /* increase offset */ end: mutex_unlock(&sde_enc->enc_lock); _sde_encoder_power_enable(sde_enc, false); return len; } Loading drivers/gpu/drm/msm/sde/sde_encoder_phys.h +20 −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_ENCODER_PHYS_H__ Loading Loading @@ -169,7 +169,8 @@ struct sde_encoder_phys_ops { void (*setup_misr)(struct sde_encoder_phys *phys_encs, bool enable, u32 frame_count); u32 (*collect_misr)(struct sde_encoder_phys *phys_enc); int (*collect_misr)(struct sde_encoder_phys *phys_enc, bool nonblock, u32 *misr_value); void (*hw_reset)(struct sde_encoder_phys *phys_enc); void (*irq_control)(struct sde_encoder_phys *phys, bool enable); void (*update_split_role)(struct sde_encoder_phys *phys_enc, Loading Loading @@ -702,4 +703,21 @@ static inline bool sde_encoder_phys_needs_single_flush( void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc, struct sde_encoder_phys_wb *wb_enc); /** * sde_encoder_helper_setup_misr - helper function to setup misr * @enable: enable/disable flag * @frame_count: frame count for misr */ void sde_encoder_helper_setup_misr(struct sde_encoder_phys *phys_enc, bool enable, u32 frame_count); /** * sde_encoder_helper_collect_misr - helper function to collect misr * @nonblock: blocking/non-blocking flag * @misr_value: pointer to misr value * @Return: zero on success */ int sde_encoder_helper_collect_misr(struct sde_encoder_phys *phys_enc, bool nonblock, u32 *misr_value); #endif /* __sde_encoder_phys_H__ */ drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +3 −1 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. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ Loading Loading @@ -1663,6 +1663,8 @@ static void sde_encoder_phys_cmd_init_ops(struct sde_encoder_phys_ops *ops) ops->get_wr_line_count = sde_encoder_phys_cmd_get_write_line_count; ops->wait_for_active = NULL; ops->setup_vsync_source = sde_encoder_phys_cmd_setup_vsync_source; ops->setup_misr = sde_encoder_helper_setup_misr; ops->collect_misr = sde_encoder_helper_collect_misr; } struct sde_encoder_phys *sde_encoder_phys_cmd_init( Loading Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +66 −48 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 */ Loading @@ -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) { Loading Loading @@ -5236,10 +5214,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; Loading @@ -5248,6 +5225,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) { Loading Loading @@ -5427,20 +5438,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; Loading @@ -5454,7 +5463,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'}; Loading @@ -5474,30 +5482,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: Loading @@ -5514,7 +5533,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; } Loading
drivers/gpu/drm/msm/sde/sde_crtc.h +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> * Loading Loading @@ -185,6 +185,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 */ Loading Loading @@ -235,7 +245,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 Loading Loading @@ -305,10 +318,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; Loading Loading @@ -752,4 +764,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_ */
drivers/gpu/drm/msm/sde/sde_encoder.c +100 −26 Original line number Diff line number Diff line Loading @@ -2157,6 +2157,28 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc, return 0; } static void sde_encoder_misr_configure(struct drm_encoder *drm_enc, bool enable, u32 frame_count) { struct sde_encoder_virt *sde_enc; int i; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return; } sde_enc = to_sde_encoder_virt(drm_enc); for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; if (!phys || !phys->ops.setup_misr) continue; phys->ops.setup_misr(phys, enable, frame_count); } } static void sde_encoder_input_event_handler(struct input_handle *handle, unsigned int type, unsigned int code, int value) { Loading Loading @@ -3884,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"); Loading Loading @@ -3949,6 +3972,15 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc) } } if (sde_enc->misr_enable) 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) { Loading Loading @@ -4790,6 +4822,28 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc) } } void sde_encoder_helper_setup_misr(struct sde_encoder_phys *phys_enc, bool enable, u32 frame_count) { if (!phys_enc) return; if (phys_enc->hw_intf && phys_enc->hw_intf->ops.setup_misr) phys_enc->hw_intf->ops.setup_misr(phys_enc->hw_intf, enable, frame_count); } int sde_encoder_helper_collect_misr(struct sde_encoder_phys *phys_enc, bool nonblock, u32 *misr_value) { if (!phys_enc) return -EINVAL; return phys_enc->hw_intf && phys_enc->hw_intf->ops.collect_misr ? phys_enc->hw_intf->ops.collect_misr(phys_enc->hw_intf, nonblock, misr_value) : -ENOTSUPP; } #ifdef CONFIG_DEBUG_FS static int _sde_encoder_status_show(struct seq_file *s, void *data) { Loading Loading @@ -4846,15 +4900,27 @@ 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; int i = 0, rc; int rc; char buf[MISR_BUFF_SIZE + 1]; size_t buff_copy; u32 frame_count, enable; struct msm_drm_private *priv = NULL; struct sde_kms *sde_kms = NULL; if (!file || !file->private_data) return -EINVAL; sde_enc = file->private_data; priv = sde_enc->base.dev->dev_private; if (!sde_enc || !priv || !priv->kms) return -EINVAL; sde_kms = to_sde_kms(priv->kms); if (sde_kms_is_secure_session_inprogress(sde_kms)) { SDE_DEBUG_ENC(sde_enc, "misr enable/disable not allowed\n"); return -ENOTSUPP; } buff_copy = min_t(size_t, count, MISR_BUFF_SIZE); if (copy_from_user(buf, user_buf, buff_copy)) Loading @@ -4869,20 +4935,10 @@ static ssize_t _sde_encoder_misr_setup(struct file *file, if (rc) return rc; 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]; if (!phys || !phys->ops.setup_misr) continue; phys->ops.setup_misr(phys, enable, frame_count); } mutex_unlock(&sde_enc->enc_lock); sde_encoder_misr_configure(&sde_enc->base, enable, frame_count); _sde_encoder_power_enable(sde_enc, false); return count; } Loading @@ -4890,6 +4946,8 @@ 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 msm_drm_private *priv = NULL; struct sde_kms *sde_kms = NULL; int i = 0, len = 0; char buf[MISR_BUFF_SIZE + 1] = {'\0'}; int rc; Loading @@ -4901,33 +4959,50 @@ static ssize_t _sde_encoder_misr_read(struct file *file, return -EINVAL; sde_enc = file->private_data; priv = sde_enc->base.dev->dev_private; if (priv != NULL) sde_kms = to_sde_kms(priv->kms); if (sde_kms_is_secure_session_inprogress(sde_kms)) { SDE_DEBUG_ENC(sde_enc, "misr read not allowed\n"); return -ENOTSUPP; } 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, len += scnprintf(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]; u32 misr_value = 0; if (!phys || !phys->ops.collect_misr) if (!phys || !phys->ops.collect_misr) { len += scnprintf(buf + len, MISR_BUFF_SIZE - len, "invalid\n"); SDE_ERROR_ENC(sde_enc, "invalid misr ops\n"); continue; } 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)); rc = phys->ops.collect_misr(phys, false, &misr_value); if (rc) { len += scnprintf(buf + len, MISR_BUFF_SIZE - len, "invalid\n"); SDE_ERROR_ENC(sde_enc, "failed to collect misr %d\n", rc); continue; } else { len += scnprintf(buf + len, MISR_BUFF_SIZE - len, "Intf idx:%d\n", phys->intf_idx - INTF_0); len += scnprintf(buf + len, MISR_BUFF_SIZE - len, "0x%x\n", misr_value); } } buff_check: Loading @@ -4944,7 +5019,6 @@ static ssize_t _sde_encoder_misr_read(struct file *file, *ppos += len; /* increase offset */ end: mutex_unlock(&sde_enc->enc_lock); _sde_encoder_power_enable(sde_enc, false); return len; } Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys.h +20 −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_ENCODER_PHYS_H__ Loading Loading @@ -169,7 +169,8 @@ struct sde_encoder_phys_ops { void (*setup_misr)(struct sde_encoder_phys *phys_encs, bool enable, u32 frame_count); u32 (*collect_misr)(struct sde_encoder_phys *phys_enc); int (*collect_misr)(struct sde_encoder_phys *phys_enc, bool nonblock, u32 *misr_value); void (*hw_reset)(struct sde_encoder_phys *phys_enc); void (*irq_control)(struct sde_encoder_phys *phys, bool enable); void (*update_split_role)(struct sde_encoder_phys *phys_enc, Loading Loading @@ -702,4 +703,21 @@ static inline bool sde_encoder_phys_needs_single_flush( void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc, struct sde_encoder_phys_wb *wb_enc); /** * sde_encoder_helper_setup_misr - helper function to setup misr * @enable: enable/disable flag * @frame_count: frame count for misr */ void sde_encoder_helper_setup_misr(struct sde_encoder_phys *phys_enc, bool enable, u32 frame_count); /** * sde_encoder_helper_collect_misr - helper function to collect misr * @nonblock: blocking/non-blocking flag * @misr_value: pointer to misr value * @Return: zero on success */ int sde_encoder_helper_collect_misr(struct sde_encoder_phys *phys_enc, bool nonblock, u32 *misr_value); #endif /* __sde_encoder_phys_H__ */
drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c +3 −1 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. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ Loading Loading @@ -1663,6 +1663,8 @@ static void sde_encoder_phys_cmd_init_ops(struct sde_encoder_phys_ops *ops) ops->get_wr_line_count = sde_encoder_phys_cmd_get_write_line_count; ops->wait_for_active = NULL; ops->setup_vsync_source = sde_encoder_phys_cmd_setup_vsync_source; ops->setup_misr = sde_encoder_helper_setup_misr; ops->collect_misr = sde_encoder_helper_collect_misr; } struct sde_encoder_phys *sde_encoder_phys_cmd_init( Loading