Loading Documentation/devicetree/bindings/fb/mdss-mdp.txt +2 −0 Original line number Diff line number Diff line Loading @@ -350,6 +350,8 @@ Optional properties: used to reduce the pending writes limit dynamically and can be tuned to match performance requirements depending upon system state. - qcom,mdss-default-ot-limit: This integer value indicates the default number of pending reads that can be allowed for the real time clients. - qcom,mdss-clk-levels: This array indicates the mdp core clock level selection array. Core clock is calculated for each frame and hence depending upon calculated value, clock rate Loading drivers/video/msm/mdss/mdss.h +1 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ struct mdss_data_type { bool needs_hist_vote; u32 rotator_ot_limit; u32 default_ot_limit; u32 mdp_irq_mask; u32 mdp_hist_irq_mask; Loading drivers/video/msm/mdss/mdss_mdp.c +175 −0 Original line number Diff line number Diff line Loading @@ -2618,6 +2618,10 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev) "qcom,mdss-rotator-ot-limit", &data); mdata->rotator_ot_limit = (!rc ? data : 0); rc = of_property_read_u32(pdev->dev.of_node, "qcom,mdss-default-ot-limit", &data); mdata->default_ot_limit = (!rc ? data : 0); mdata->has_non_scalar_rgb = of_property_read_bool(pdev->dev.of_node, "qcom,mdss-has-non-scalar-rgb"); mdata->has_bwc = of_property_read_bool(pdev->dev.of_node, Loading Loading @@ -2946,6 +2950,177 @@ int mdss_panel_get_boot_cfg(void) return rc; } int mdss_mdp_wait_for_xin_halt(u32 xin_id, bool is_vbif_nrt) { void __iomem *vbif_base; u32 status; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 idle_mask = BIT(xin_id); int rc; vbif_base = is_vbif_nrt ? mdata->vbif_nrt_io.base : mdata->vbif_io.base; rc = readl_poll_timeout(vbif_base + MMSS_VBIF_XIN_HALT_CTRL1, status, (status & idle_mask), 1000, XIN_HALT_TIMEOUT_US); if (rc == -ETIMEDOUT) { pr_err("VBIF client %d not halting. TIMEDOUT.\n", xin_id); BUG(); } else { pr_debug("VBIF client %d is halted\n", xin_id); } return rc; } /** * force_on_xin_clk() - enable/disable the force-on for the pipe clock * @bit_off: offset of the bit to enable/disable the force-on. * @reg_off: register offset for the clock control. * @enable: boolean to indicate if the force-on of the clock needs to be * enabled or disabled. * * This function returns: * true - if the clock is forced-on by this function * false - if the clock was already forced on * It is the caller responsibility to check if this function is forcing * the clock on; if so, it will need to remove the force of the clock, * otherwise it should avoid to remove the force-on. * Clocks must be on when calling this function. */ bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable) { u32 val; u32 force_on_mask; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); bool clk_forced_on = false; force_on_mask = BIT(bit_off); val = readl_relaxed(mdata->mdp_base + clk_ctl_reg_off); clk_forced_on = !(force_on_mask & val); if (true == enable) val |= force_on_mask; else val &= ~force_on_mask; writel_relaxed(val, mdata->mdp_base + clk_ctl_reg_off); return clk_forced_on; } static bool limit_rotator_ot(bool is_yuv, u32 width, u32 height) { return (true == is_yuv) && (width * height <= 1080 * 1920); } static int limit_wb_ot(u32 width, u32 height) { return width * height <= 1080 * 1920; } static u32 get_ot_limit(u32 reg_off, u32 bit_off, bool is_rot, bool is_wb, bool is_yuv, u32 width, u32 height) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 ot_lim = mdata->default_ot_limit; u32 is_vbif_nrt, val; /* * If default ot limit is not set from dt, * then ot limiting is disabled. */ if (ot_lim == 0) goto exit; is_vbif_nrt = mdss_mdp_is_vbif_nrt(mdata->mdp_rev); if ((is_rot && limit_rotator_ot(is_yuv, width, height)) || (is_wb && limit_wb_ot(width, height))) { ot_lim = MDSS_OT_LIMIT; } val = MDSS_VBIF_READ(mdata, reg_off, is_vbif_nrt); val &= (0xFF << bit_off); val = val >> bit_off; if (val == ot_lim) ot_lim = 0; exit: return ot_lim; } void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params, bool is_rot, bool is_wb, bool is_yuv) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 ot_lim; u32 reg_off_vbif_lim_conf = (params->xin_id / 4) * 4 + params->reg_off_vbif_lim_conf; u32 bit_off_vbif_lim_conf = (params->xin_id % 4) * 8; bool is_vbif_nrt = mdss_mdp_is_vbif_nrt(mdata->mdp_rev); u32 reg_val; bool forced_on; if (!mdss_mdp_apply_ot_limit(mdata->mdp_rev)) goto exit; ot_lim = get_ot_limit( reg_off_vbif_lim_conf, bit_off_vbif_lim_conf, is_rot, is_wb, is_yuv, params->width, params->height) & 0xFF; if (ot_lim == 0) goto exit; trace_mdp_perf_set_ot(params->num, params->xin_id, ot_lim, is_vbif_nrt); mutex_lock(&mdata->reg_lock); forced_on = force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, true); reg_val = MDSS_VBIF_READ(mdata, reg_off_vbif_lim_conf, is_vbif_nrt); reg_val &= ~(0xFF << bit_off_vbif_lim_conf); reg_val |= (ot_lim) << bit_off_vbif_lim_conf; MDSS_VBIF_WRITE(mdata, reg_off_vbif_lim_conf, reg_val, is_vbif_nrt); reg_val = MDSS_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0, is_vbif_nrt); MDSS_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0, reg_val | BIT(params->xin_id), is_vbif_nrt); mutex_unlock(&mdata->reg_lock); mdss_mdp_wait_for_xin_halt(params->xin_id, is_vbif_nrt); mutex_lock(&mdata->reg_lock); reg_val = MDSS_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0, is_vbif_nrt); MDSS_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0, reg_val & ~BIT(params->xin_id), is_vbif_nrt); if (forced_on) force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, false); mutex_unlock(&mdata->reg_lock); exit: return; } static int mdss_mdp_cx_ctrl(struct mdss_data_type *mdata, int enable) { int rc = 0; Loading drivers/video/msm/mdss/mdss_mdp.h +35 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,14 @@ #define CURSOR_PIPE_LEFT 0 #define CURSOR_PIPE_RIGHT 1 /* * Recommendation is to have different ot depending on the fps * and resolution, but since current SW doesn't support different * fps for non-real time, we are hard-coding the ot limit to 2 for now */ #define MDSS_OT_LIMIT 2 #define XIN_HALT_TIMEOUT_US 0x4000 enum mdss_mdp_perf_state_type { PERF_SW_COMMIT_STATE = 0, PERF_HW_MDP_STATE, Loading Loading @@ -547,6 +555,16 @@ struct mdss_overlay_private { u32 cursor_ndx[2]; }; struct mdss_mdp_set_ot_params { u32 xin_id; u32 num; u32 width; u32 height; u32 reg_off_vbif_lim_conf; u32 reg_off_mdp_clk_ctrl; u32 bit_off_mdp_clk_ctrl; }; struct mdss_mdp_commit_cb { void *data; int (*commit_cb_fnc) (enum mdp_commit_stage_type commit_state, Loading Loading @@ -651,6 +669,19 @@ static inline int mdss_mdp_pipe_is_sw_reset_available( } } static inline bool mdss_mdp_is_vbif_nrt(u32 mdp_rev) { return IS_MDSS_MAJOR_MINOR_SAME(mdp_rev, MDSS_MDP_HW_REV_107); } static inline bool mdss_mdp_apply_ot_limit(u32 mdp_rev) { return mdp_rev == MDSS_MDP_HW_REV_105 || mdp_rev == MDSS_MDP_HW_REV_109 || mdp_rev == MDSS_MDP_HW_REV_110; } static inline int mdss_mdp_iommu_dyn_attach_supported( struct mdss_data_type *mdata) { Loading Loading @@ -1008,4 +1039,8 @@ int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable); int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enable); void mdss_mdp_ctl_restore(void); int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl); int mdss_mdp_wait_for_xin_halt(u32 xin_id, bool is_vbif_nrt); void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params, bool is_rot, bool is_wb, bool is_yuv); #endif /* MDSS_MDP_H */ drivers/video/msm/mdss/mdss_mdp_hwio.h +3 −0 Original line number Diff line number Diff line Loading @@ -627,6 +627,9 @@ enum mdss_mdp_pingpong_index { #define MDSS_MDP_INTF_MISR_SIGNATURE (MDSS_MDP_INTF_MISR_CTRL + 0x4) /* following offsets are with respect to MDP VBIF base */ #define MMSS_VBIF_RD_LIM_CONF 0x0B0 #define MMSS_VBIF_WR_LIM_CONF 0x0C0 #define MMSS_VBIF_XIN_HALT_CTRL0 0x200 #define MMSS_VBIF_XIN_HALT_CTRL1 0x204 #define MMSS_VBIF_AXI_HALT_CTRL0 0x208 Loading Loading
Documentation/devicetree/bindings/fb/mdss-mdp.txt +2 −0 Original line number Diff line number Diff line Loading @@ -350,6 +350,8 @@ Optional properties: used to reduce the pending writes limit dynamically and can be tuned to match performance requirements depending upon system state. - qcom,mdss-default-ot-limit: This integer value indicates the default number of pending reads that can be allowed for the real time clients. - qcom,mdss-clk-levels: This array indicates the mdp core clock level selection array. Core clock is calculated for each frame and hence depending upon calculated value, clock rate Loading
drivers/video/msm/mdss/mdss.h +1 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ struct mdss_data_type { bool needs_hist_vote; u32 rotator_ot_limit; u32 default_ot_limit; u32 mdp_irq_mask; u32 mdp_hist_irq_mask; Loading
drivers/video/msm/mdss/mdss_mdp.c +175 −0 Original line number Diff line number Diff line Loading @@ -2618,6 +2618,10 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev) "qcom,mdss-rotator-ot-limit", &data); mdata->rotator_ot_limit = (!rc ? data : 0); rc = of_property_read_u32(pdev->dev.of_node, "qcom,mdss-default-ot-limit", &data); mdata->default_ot_limit = (!rc ? data : 0); mdata->has_non_scalar_rgb = of_property_read_bool(pdev->dev.of_node, "qcom,mdss-has-non-scalar-rgb"); mdata->has_bwc = of_property_read_bool(pdev->dev.of_node, Loading Loading @@ -2946,6 +2950,177 @@ int mdss_panel_get_boot_cfg(void) return rc; } int mdss_mdp_wait_for_xin_halt(u32 xin_id, bool is_vbif_nrt) { void __iomem *vbif_base; u32 status; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 idle_mask = BIT(xin_id); int rc; vbif_base = is_vbif_nrt ? mdata->vbif_nrt_io.base : mdata->vbif_io.base; rc = readl_poll_timeout(vbif_base + MMSS_VBIF_XIN_HALT_CTRL1, status, (status & idle_mask), 1000, XIN_HALT_TIMEOUT_US); if (rc == -ETIMEDOUT) { pr_err("VBIF client %d not halting. TIMEDOUT.\n", xin_id); BUG(); } else { pr_debug("VBIF client %d is halted\n", xin_id); } return rc; } /** * force_on_xin_clk() - enable/disable the force-on for the pipe clock * @bit_off: offset of the bit to enable/disable the force-on. * @reg_off: register offset for the clock control. * @enable: boolean to indicate if the force-on of the clock needs to be * enabled or disabled. * * This function returns: * true - if the clock is forced-on by this function * false - if the clock was already forced on * It is the caller responsibility to check if this function is forcing * the clock on; if so, it will need to remove the force of the clock, * otherwise it should avoid to remove the force-on. * Clocks must be on when calling this function. */ bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable) { u32 val; u32 force_on_mask; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); bool clk_forced_on = false; force_on_mask = BIT(bit_off); val = readl_relaxed(mdata->mdp_base + clk_ctl_reg_off); clk_forced_on = !(force_on_mask & val); if (true == enable) val |= force_on_mask; else val &= ~force_on_mask; writel_relaxed(val, mdata->mdp_base + clk_ctl_reg_off); return clk_forced_on; } static bool limit_rotator_ot(bool is_yuv, u32 width, u32 height) { return (true == is_yuv) && (width * height <= 1080 * 1920); } static int limit_wb_ot(u32 width, u32 height) { return width * height <= 1080 * 1920; } static u32 get_ot_limit(u32 reg_off, u32 bit_off, bool is_rot, bool is_wb, bool is_yuv, u32 width, u32 height) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 ot_lim = mdata->default_ot_limit; u32 is_vbif_nrt, val; /* * If default ot limit is not set from dt, * then ot limiting is disabled. */ if (ot_lim == 0) goto exit; is_vbif_nrt = mdss_mdp_is_vbif_nrt(mdata->mdp_rev); if ((is_rot && limit_rotator_ot(is_yuv, width, height)) || (is_wb && limit_wb_ot(width, height))) { ot_lim = MDSS_OT_LIMIT; } val = MDSS_VBIF_READ(mdata, reg_off, is_vbif_nrt); val &= (0xFF << bit_off); val = val >> bit_off; if (val == ot_lim) ot_lim = 0; exit: return ot_lim; } void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params, bool is_rot, bool is_wb, bool is_yuv) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 ot_lim; u32 reg_off_vbif_lim_conf = (params->xin_id / 4) * 4 + params->reg_off_vbif_lim_conf; u32 bit_off_vbif_lim_conf = (params->xin_id % 4) * 8; bool is_vbif_nrt = mdss_mdp_is_vbif_nrt(mdata->mdp_rev); u32 reg_val; bool forced_on; if (!mdss_mdp_apply_ot_limit(mdata->mdp_rev)) goto exit; ot_lim = get_ot_limit( reg_off_vbif_lim_conf, bit_off_vbif_lim_conf, is_rot, is_wb, is_yuv, params->width, params->height) & 0xFF; if (ot_lim == 0) goto exit; trace_mdp_perf_set_ot(params->num, params->xin_id, ot_lim, is_vbif_nrt); mutex_lock(&mdata->reg_lock); forced_on = force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, true); reg_val = MDSS_VBIF_READ(mdata, reg_off_vbif_lim_conf, is_vbif_nrt); reg_val &= ~(0xFF << bit_off_vbif_lim_conf); reg_val |= (ot_lim) << bit_off_vbif_lim_conf; MDSS_VBIF_WRITE(mdata, reg_off_vbif_lim_conf, reg_val, is_vbif_nrt); reg_val = MDSS_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0, is_vbif_nrt); MDSS_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0, reg_val | BIT(params->xin_id), is_vbif_nrt); mutex_unlock(&mdata->reg_lock); mdss_mdp_wait_for_xin_halt(params->xin_id, is_vbif_nrt); mutex_lock(&mdata->reg_lock); reg_val = MDSS_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0, is_vbif_nrt); MDSS_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0, reg_val & ~BIT(params->xin_id), is_vbif_nrt); if (forced_on) force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, false); mutex_unlock(&mdata->reg_lock); exit: return; } static int mdss_mdp_cx_ctrl(struct mdss_data_type *mdata, int enable) { int rc = 0; Loading
drivers/video/msm/mdss/mdss_mdp.h +35 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,14 @@ #define CURSOR_PIPE_LEFT 0 #define CURSOR_PIPE_RIGHT 1 /* * Recommendation is to have different ot depending on the fps * and resolution, but since current SW doesn't support different * fps for non-real time, we are hard-coding the ot limit to 2 for now */ #define MDSS_OT_LIMIT 2 #define XIN_HALT_TIMEOUT_US 0x4000 enum mdss_mdp_perf_state_type { PERF_SW_COMMIT_STATE = 0, PERF_HW_MDP_STATE, Loading Loading @@ -547,6 +555,16 @@ struct mdss_overlay_private { u32 cursor_ndx[2]; }; struct mdss_mdp_set_ot_params { u32 xin_id; u32 num; u32 width; u32 height; u32 reg_off_vbif_lim_conf; u32 reg_off_mdp_clk_ctrl; u32 bit_off_mdp_clk_ctrl; }; struct mdss_mdp_commit_cb { void *data; int (*commit_cb_fnc) (enum mdp_commit_stage_type commit_state, Loading Loading @@ -651,6 +669,19 @@ static inline int mdss_mdp_pipe_is_sw_reset_available( } } static inline bool mdss_mdp_is_vbif_nrt(u32 mdp_rev) { return IS_MDSS_MAJOR_MINOR_SAME(mdp_rev, MDSS_MDP_HW_REV_107); } static inline bool mdss_mdp_apply_ot_limit(u32 mdp_rev) { return mdp_rev == MDSS_MDP_HW_REV_105 || mdp_rev == MDSS_MDP_HW_REV_109 || mdp_rev == MDSS_MDP_HW_REV_110; } static inline int mdss_mdp_iommu_dyn_attach_supported( struct mdss_data_type *mdata) { Loading Loading @@ -1008,4 +1039,8 @@ int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable); int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enable); void mdss_mdp_ctl_restore(void); int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl); int mdss_mdp_wait_for_xin_halt(u32 xin_id, bool is_vbif_nrt); void mdss_mdp_set_ot_limit(struct mdss_mdp_set_ot_params *params, bool is_rot, bool is_wb, bool is_yuv); #endif /* MDSS_MDP_H */
drivers/video/msm/mdss/mdss_mdp_hwio.h +3 −0 Original line number Diff line number Diff line Loading @@ -627,6 +627,9 @@ enum mdss_mdp_pingpong_index { #define MDSS_MDP_INTF_MISR_SIGNATURE (MDSS_MDP_INTF_MISR_CTRL + 0x4) /* following offsets are with respect to MDP VBIF base */ #define MMSS_VBIF_RD_LIM_CONF 0x0B0 #define MMSS_VBIF_WR_LIM_CONF 0x0C0 #define MMSS_VBIF_XIN_HALT_CTRL0 0x200 #define MMSS_VBIF_XIN_HALT_CTRL1 0x204 #define MMSS_VBIF_AXI_HALT_CTRL0 0x208 Loading