Loading drivers/gpu/drm/msm/sde/sde_crtc.c +144 −14 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) Loading Loading @@ -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"); Loading @@ -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; Loading @@ -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); } } Loading Loading @@ -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) \ { \ Loading Loading @@ -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; Loading @@ -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; } Loading drivers/gpu/drm/msm/sde/sde_crtc.h +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) Loading drivers/gpu/drm/msm/sde/sde_encoder.c +104 −73 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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) Loading @@ -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) Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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; } Loading @@ -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]; Loading @@ -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; } Loading Loading @@ -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; Loading drivers/gpu/drm/msm/sde/sde_encoder_phys.h +2 −5 Original line number Diff line number Diff line Loading @@ -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); }; Loading Loading @@ -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 Loading Loading @@ -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; Loading drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +17 −18 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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 Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +144 −14 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) Loading Loading @@ -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"); Loading @@ -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; Loading @@ -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); } } Loading Loading @@ -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) \ { \ Loading Loading @@ -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; Loading @@ -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; } Loading
drivers/gpu/drm/msm/sde/sde_crtc.h +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +104 −73 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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) Loading @@ -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) Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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; } Loading @@ -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]; Loading @@ -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; } Loading Loading @@ -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; Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys.h +2 −5 Original line number Diff line number Diff line Loading @@ -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); }; Loading Loading @@ -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 Loading Loading @@ -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; Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +17 −18 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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