Loading drivers/gpu/drm/msm/sde/sde_hw_top.c +62 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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) { Loading @@ -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, Loading drivers/gpu/drm/msm/sde/sde_hw_top.h +28 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,18 @@ struct cdm_output_cfg { bool intf_en; }; /** * 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. Loading Loading @@ -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 { Loading drivers/gpu/drm/msm/sde/sde_kms.c +110 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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) { Loading drivers/gpu/drm/msm/sde/sde_kms.h +3 −0 Original line number Diff line number Diff line Loading @@ -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]; Loading @@ -143,6 +144,8 @@ struct sde_kms { void **dsi_displays; int wb_display_count; void **wb_displays; bool has_danger_ctrl; }; struct vsync_info { Loading drivers/gpu/drm/msm/sde/sde_plane.c +147 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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", 0444, psde->debugfs_root, &psde->debugfs_csc); debugfs_create_u32("xin_id", 0444, psde->debugfs_root, (u32 *) &cfg->xin_id); debugfs_create_u32("clk_ctrl", 0444, psde->debugfs_root, (u32 *) &cfg->clk_ctrl); debugfs_create_x32("creq_vblank", 0644, psde->debugfs_root, (u32 *) &sblk->creq_vblank); debugfs_create_x32("danger_vblank", 0644, psde->debugfs_root, (u32 *) &sblk->danger_vblank); debugfs_create_file("disable_danger", 0644, psde->debugfs_root, kms, &sde_plane_danger_enable); } } } Loading Loading
drivers/gpu/drm/msm/sde/sde_hw_top.c +62 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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) { Loading @@ -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, Loading
drivers/gpu/drm/msm/sde/sde_hw_top.h +28 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,18 @@ struct cdm_output_cfg { bool intf_en; }; /** * 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. Loading Loading @@ -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 { Loading
drivers/gpu/drm/msm/sde/sde_kms.c +110 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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) { Loading
drivers/gpu/drm/msm/sde/sde_kms.h +3 −0 Original line number Diff line number Diff line Loading @@ -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]; Loading @@ -143,6 +144,8 @@ struct sde_kms { void **dsi_displays; int wb_display_count; void **wb_displays; bool has_danger_ctrl; }; struct vsync_info { Loading
drivers/gpu/drm/msm/sde/sde_plane.c +147 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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", 0444, psde->debugfs_root, &psde->debugfs_csc); debugfs_create_u32("xin_id", 0444, psde->debugfs_root, (u32 *) &cfg->xin_id); debugfs_create_u32("clk_ctrl", 0444, psde->debugfs_root, (u32 *) &cfg->clk_ctrl); debugfs_create_x32("creq_vblank", 0644, psde->debugfs_root, (u32 *) &sblk->creq_vblank); debugfs_create_x32("danger_vblank", 0644, psde->debugfs_root, (u32 *) &sblk->danger_vblank); debugfs_create_file("disable_danger", 0644, psde->debugfs_root, kms, &sde_plane_danger_enable); } } } Loading