diff options
| author | Alan Kwong <akwong@codeaurora.org> | 2016-10-24 21:39:26 -0400 |
|---|---|---|
| committer | Alan Kwong <akwong@codeaurora.org> | 2016-12-14 09:59:56 -0500 |
| commit | 40b9c0ee802c5a963aa448008177dc31b040cb49 (patch) | |
| tree | 0c6b070dec66faae32a62021270af9b0aae0c0f4 /drivers/gpu | |
| parent | ed93daaea77966c21d6b3807a8e3f94bcd07f11b (diff) | |
drm/msm/sde: add debugfs entry for danger and safe status
Add debugfs entry for current danger and safe status of each pipe
and current overall status for debugging purposes.
Change-Id: I3e784d0218df40c184a431409c864a3208a90b45
Signed-off-by: Alan Kwong <akwong@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_top.c | 62 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_top.h | 28 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_kms.c | 110 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_kms.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_plane.c | 147 |
5 files changed, 350 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c index 045d4c24bb29..1a5d469e6e7e 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_top.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c @@ -22,6 +22,9 @@ #define FLD_INTF_2_SW_TRG_MUX BIT(8) #define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF +#define DANGER_STATUS 0x360 +#define SAFE_STATUS 0x364 + #define TE_LINE_INTERVAL 0x3F4 #define TRAFFIC_SHAPER_EN BIT(31) @@ -139,6 +142,63 @@ static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp, return clk_forced_on; } + +static void sde_hw_get_danger_status(struct sde_hw_mdp *mdp, + struct sde_danger_safe_status *status) +{ + struct sde_hw_blk_reg_map *c = &mdp->hw; + u32 value; + + value = SDE_REG_READ(c, DANGER_STATUS); + status->mdp = (value >> 0) & 0x3; + status->sspp[SSPP_VIG0] = (value >> 4) & 0x3; + status->sspp[SSPP_VIG1] = (value >> 6) & 0x3; + status->sspp[SSPP_VIG2] = (value >> 8) & 0x3; + status->sspp[SSPP_VIG3] = (value >> 10) & 0x3; + status->sspp[SSPP_RGB0] = (value >> 12) & 0x3; + status->sspp[SSPP_RGB1] = (value >> 14) & 0x3; + status->sspp[SSPP_RGB2] = (value >> 16) & 0x3; + status->sspp[SSPP_RGB3] = (value >> 18) & 0x3; + status->sspp[SSPP_DMA0] = (value >> 20) & 0x3; + status->sspp[SSPP_DMA1] = (value >> 22) & 0x3; + status->sspp[SSPP_DMA2] = (value >> 28) & 0x3; + status->sspp[SSPP_DMA3] = (value >> 30) & 0x3; + status->sspp[SSPP_CURSOR0] = (value >> 24) & 0x3; + status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x3; + status->wb[WB_0] = 0; + status->wb[WB_1] = 0; + status->wb[WB_2] = (value >> 2) & 0x3; + status->wb[WB_3] = 0; +} + +static void sde_hw_get_safe_status(struct sde_hw_mdp *mdp, + struct sde_danger_safe_status *status) +{ + struct sde_hw_blk_reg_map *c = &mdp->hw; + u32 value; + + value = SDE_REG_READ(c, SAFE_STATUS); + status->mdp = (value >> 0) & 0x1; + status->sspp[SSPP_VIG0] = (value >> 4) & 0x1; + status->sspp[SSPP_VIG1] = (value >> 6) & 0x1; + status->sspp[SSPP_VIG2] = (value >> 8) & 0x1; + status->sspp[SSPP_VIG3] = (value >> 10) & 0x1; + status->sspp[SSPP_RGB0] = (value >> 12) & 0x1; + status->sspp[SSPP_RGB1] = (value >> 14) & 0x1; + status->sspp[SSPP_RGB2] = (value >> 16) & 0x1; + status->sspp[SSPP_RGB3] = (value >> 18) & 0x1; + status->sspp[SSPP_DMA0] = (value >> 20) & 0x1; + status->sspp[SSPP_DMA1] = (value >> 22) & 0x1; + status->sspp[SSPP_DMA2] = (value >> 28) & 0x1; + status->sspp[SSPP_DMA3] = (value >> 30) & 0x1; + status->sspp[SSPP_CURSOR0] = (value >> 24) & 0x1; + status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x1; + status->wb[WB_0] = 0; + status->wb[WB_1] = 0; + status->wb[WB_2] = (value >> 2) & 0x1; + status->wb[WB_3] = 0; +} + static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops, unsigned long cap) { @@ -146,6 +206,8 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops, ops->setup_pp_split = sde_hw_setup_pp_split; ops->setup_cdm_output = sde_hw_setup_cdm_output; ops->setup_clk_force_ctrl = sde_hw_setup_clk_force_ctrl; + ops->get_danger_status = sde_hw_get_danger_status; + ops->get_safe_status = sde_hw_get_safe_status; } static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp, diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.h b/drivers/gpu/drm/msm/sde/sde_hw_top.h index eb8ff8685908..780d051e7408 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_top.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_top.h @@ -65,6 +65,18 @@ struct cdm_output_cfg { }; /** + * struct sde_danger_safe_status: danger and safe status signals + * @mdp: top level status + * @sspp: source pipe status + * @wb: writebck output status + */ +struct sde_danger_safe_status { + u8 mdp; + u8 sspp[SSPP_MAX]; + u8 wb[WB_MAX]; +}; + +/** * struct sde_hw_mdp_ops - interface to the MDP TOP Hw driver functions * Assumption is these functions will be called after clocks are enabled. * @setup_split_pipe : Programs the pipe control registers @@ -113,6 +125,22 @@ struct sde_hw_mdp_ops { */ bool (*setup_clk_force_ctrl)(struct sde_hw_mdp *mdp, enum sde_clk_ctrl_type clk_ctrl, bool enable); + + /** + * get_danger_status - get danger status + * @mdp: mdp top context driver + * @status: Pointer to danger safe status + */ + void (*get_danger_status)(struct sde_hw_mdp *mdp, + struct sde_danger_safe_status *status); + + /** + * get_safe_status - get safe status + * @mdp: mdp top context driver + * @status: Pointer to danger safe status + */ + void (*get_safe_status)(struct sde_hw_mdp *mdp, + struct sde_danger_safe_status *status); }; struct sde_hw_mdp { diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 1b523767f523..7d67404caef4 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -78,6 +78,101 @@ bool sde_is_custom_client(void) return sdecustom; } +#ifdef CONFIG_DEBUG_FS +static int _sde_danger_signal_status(struct seq_file *s, + bool danger_status) +{ + struct sde_kms *kms = (struct sde_kms *)s->private; + struct msm_drm_private *priv; + struct sde_danger_safe_status status; + int i; + + if (!kms || !kms->dev || !kms->dev->dev_private || !kms->hw_mdp) { + SDE_ERROR("invalid arg(s)\n"); + return 0; + } + + priv = kms->dev->dev_private; + memset(&status, 0, sizeof(struct sde_danger_safe_status)); + + sde_power_resource_enable(&priv->phandle, kms->core_client, true); + if (danger_status) { + seq_puts(s, "\nDanger signal status:\n"); + if (kms->hw_mdp->ops.get_danger_status) + kms->hw_mdp->ops.get_danger_status(kms->hw_mdp, + &status); + } else { + seq_puts(s, "\nSafe signal status:\n"); + if (kms->hw_mdp->ops.get_danger_status) + kms->hw_mdp->ops.get_danger_status(kms->hw_mdp, + &status); + } + sde_power_resource_enable(&priv->phandle, kms->core_client, false); + + seq_printf(s, "MDP : 0x%x\n", status.mdp); + + for (i = SSPP_VIG0; i < SSPP_MAX; i++) + seq_printf(s, "SSPP%d : 0x%x \t", i - SSPP_VIG0, + status.sspp[i]); + seq_puts(s, "\n"); + + for (i = WB_0; i < WB_MAX; i++) + seq_printf(s, "WB%d : 0x%x \t", i - WB_0, + status.wb[i]); + seq_puts(s, "\n"); + + return 0; +} + +#define DEFINE_SDE_DEBUGFS_SEQ_FOPS(__prefix) \ +static int __prefix ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __prefix ## _show, inode->i_private); \ +} \ +static const struct file_operations __prefix ## _fops = { \ + .owner = THIS_MODULE, \ + .open = __prefix ## _open, \ + .release = single_release, \ + .read = seq_read, \ + .llseek = seq_lseek, \ +} + +static int sde_debugfs_danger_stats_show(struct seq_file *s, void *v) +{ + return _sde_danger_signal_status(s, true); +} +DEFINE_SDE_DEBUGFS_SEQ_FOPS(sde_debugfs_danger_stats); + +static int sde_debugfs_safe_stats_show(struct seq_file *s, void *v) +{ + return _sde_danger_signal_status(s, false); +} +DEFINE_SDE_DEBUGFS_SEQ_FOPS(sde_debugfs_safe_stats); + +static void sde_debugfs_danger_destroy(struct sde_kms *sde_kms) +{ + debugfs_remove_recursive(sde_kms->debugfs_danger); + sde_kms->debugfs_danger = NULL; +} + +static int sde_debugfs_danger_init(struct sde_kms *sde_kms, + struct dentry *parent) +{ + sde_kms->debugfs_danger = debugfs_create_dir("danger", + parent); + if (!sde_kms->debugfs_danger) { + SDE_ERROR("failed to create danger debugfs\n"); + return -EINVAL; + } + + debugfs_create_file("danger_status", 0644, sde_kms->debugfs_danger, + sde_kms, &sde_debugfs_danger_stats_fops); + debugfs_create_file("safe_status", 0644, sde_kms->debugfs_danger, + sde_kms, &sde_debugfs_safe_stats_fops); + + return 0; +} + static int _sde_debugfs_show_regset32(struct seq_file *s, void *data) { struct sde_debugfs_regset32 *regset; @@ -197,6 +292,8 @@ static int _sde_debugfs_init(struct sde_kms *sde_kms) if (!sde_kms->debugfs_debug) SDE_ERROR("failed to create debugfs debug directory\n"); + sde_debugfs_danger_init(sde_kms, sde_kms->debugfs_debug); + return 0; } @@ -204,12 +301,25 @@ static void _sde_debugfs_destroy(struct sde_kms *sde_kms) { /* don't need to NULL check debugfs_root */ if (sde_kms) { + sde_debugfs_danger_destroy(sde_kms); debugfs_remove_recursive(sde_kms->debugfs_debug); sde_kms->debugfs_debug = 0; debugfs_remove_recursive(sde_kms->debugfs_root); sde_kms->debugfs_root = 0; } } +#else +static void sde_debugfs_danger_destroy(struct sde_kms *sde_kms, + struct dentry *parent) +{ +} + +static int sde_debugfs_danger_init(struct sde_kms *sde_kms, + struct dentry *parent) +{ + return 0; +} +#endif static int sde_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc) { diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h index ea2d6841d11c..572409bcc218 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.h +++ b/drivers/gpu/drm/msm/sde/sde_kms.h @@ -121,6 +121,7 @@ struct sde_kms { /* directory entry for debugfs */ void *debugfs_root; struct dentry *debugfs_debug; + struct dentry *debugfs_danger; /* io/register spaces: */ void __iomem *mmio, *vbif[VBIF_MAX]; @@ -143,6 +144,8 @@ struct sde_kms { void **dsi_displays; int wb_display_count; void **wb_displays; + + bool has_danger_ctrl; }; struct vsync_info { diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index 63e19b3f0bea..08d746fb32d6 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -406,6 +406,39 @@ static void _sde_plane_set_qos_ctrl(struct drm_plane *plane, &psde->pipe_qos_cfg); } +int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) +{ + struct sde_plane *psde; + struct msm_drm_private *priv; + struct sde_kms *sde_kms; + + if (!plane || !plane->dev) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + priv = plane->dev->dev_private; + if (!priv || !priv->kms) { + SDE_ERROR("invalid KMS reference\n"); + return -EINVAL; + } + + sde_kms = to_sde_kms(priv->kms); + psde = to_sde_plane(plane); + + if (!psde->is_rt_pipe) + goto end; + + sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true); + + _sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL); + + sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false); + +end: + return 0; +} + /** * _sde_plane_set_ot_limit - set OT limit for the given plane * @plane: Pointer to drm plane @@ -2069,6 +2102,98 @@ enum sde_sspp sde_plane_pipe(struct drm_plane *plane) return plane ? to_sde_plane(plane)->pipe : SSPP_NONE; } +static ssize_t _sde_plane_danger_read(struct file *file, + char __user *buff, size_t count, loff_t *ppos) +{ + struct sde_kms *kms = file->private_data; + struct sde_mdss_cfg *cfg = kms->catalog; + int len = 0; + char buf[40] = {'\0'}; + + if (!cfg) + return -ENODEV; + + if (*ppos) + return 0; /* the end */ + + len = snprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl); + if (len < 0 || len >= sizeof(buf)) + return 0; + + if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + return -EFAULT; + + *ppos += len; /* increase offset */ + + return len; +} + +static void _sde_plane_set_danger_state(struct sde_kms *kms, bool enable) +{ + struct drm_plane *plane; + + drm_for_each_plane(plane, kms->dev) { + if (plane->fb && plane->state) { + sde_plane_danger_signal_ctrl(plane, enable); + SDE_DEBUG("plane:%d img:%dx%d ", + plane->base.id, plane->fb->width, + plane->fb->height); + SDE_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n", + plane->state->src_x >> 16, + plane->state->src_y >> 16, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + plane->state->crtc_x, plane->state->crtc_y, + plane->state->crtc_w, plane->state->crtc_h); + } else { + SDE_DEBUG("Inactive plane:%d\n", plane->base.id); + } + } +} + +static ssize_t _sde_plane_danger_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct sde_kms *kms = file->private_data; + struct sde_mdss_cfg *cfg = kms->catalog; + int disable_panic; + char buf[10]; + + if (!cfg) + return -EFAULT; + + if (count >= sizeof(buf)) + return -EFAULT; + + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + + buf[count] = 0; /* end of string */ + + if (kstrtoint(buf, 0, &disable_panic)) + return -EFAULT; + + if (disable_panic) { + /* Disable panic signal for all active pipes */ + SDE_DEBUG("Disabling danger:\n"); + _sde_plane_set_danger_state(kms, false); + kms->has_danger_ctrl = false; + } else { + /* Enable panic signal for all active pipes */ + SDE_DEBUG("Enabling danger:\n"); + kms->has_danger_ctrl = true; + _sde_plane_set_danger_state(kms, true); + } + + return count; +} + +static const struct file_operations sde_plane_danger_enable = { + .open = simple_open, + .read = _sde_plane_danger_read, + .write = _sde_plane_danger_write, +}; + static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms) { const struct sde_sspp_sub_blks *sblk = 0; @@ -2111,6 +2236,28 @@ static void _sde_plane_init_debugfs(struct sde_plane *psde, struct sde_kms *kms) kms); sde_debugfs_create_regset32("csc_blk", S_IRUGO, psde->debugfs_root, &psde->debugfs_csc); + + debugfs_create_u32("xin_id", + S_IRUGO, + psde->debugfs_root, + (u32 *) &cfg->xin_id); + debugfs_create_u32("clk_ctrl", + S_IRUGO, + psde->debugfs_root, + (u32 *) &cfg->clk_ctrl); + debugfs_create_x32("creq_vblank", + S_IRUGO | S_IWUSR, + psde->debugfs_root, + (u32 *) &sblk->creq_vblank); + debugfs_create_x32("danger_vblank", + S_IRUGO | S_IWUSR, + psde->debugfs_root, + (u32 *) &sblk->danger_vblank); + + debugfs_create_file("disable_danger", + S_IRUGO | S_IWUSR, + psde->debugfs_root, + kms, &sde_plane_danger_enable); } } } |
