Loading arch/arm/boot/dts/qcom/dsi-panel-sharp-dualmipi-wqxga-video.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ qcom,mdss-dsi-min-refresh-rate = <53>; qcom,mdss-dsi-max-refresh-rate = <60>; qcom,mdss-dsi-pan-enable-dynamic-fps; qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; qcom,mdss-dsi-pan-fps-update = "dfps_immediate_clk_mode"; qcom,mdss-dsi-panel-status-check-mode = "bta_check"; qcom,mdss-dsi-tx-eot-append; qcom,esd-check-enabled; Loading arch/arm/boot/dts/qcom/msm8996-mdss.dtsi +18 −5 Original line number Diff line number Diff line Loading @@ -385,11 +385,17 @@ <&mdss_dsi0_pll clk_dsi0pll_byte_clk_mux>, <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_mux>, <&mdss_dsi0_pll clk_dsi0pll_byte_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>; <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_shadow_byte_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_shadow_pixel_clk_src>; clock-names = "byte_clk", "pixel_clk", "core_clk", "byte_clk_rcg", "pixel_clk_rcg", "pll_byte_clk_mux", "pll_pixel_clk_mux", "pll_byte_clk_src", "pll_pixel_clk_src"; "pll_byte_clk_src", "pll_pixel_clk_src", "pll_shadow_byte_clk_src", "pll_shadow_pixel_clk_src"; qcom,null-insertion-enabled; qcom,platform-strength-ctrl = [ff 06 Loading Loading @@ -429,12 +435,19 @@ <&clock_mmss clk_pclk1_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_byte_clk_mux>, <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_mux>, <&mdss_dsi0_pll clk_dsi0pll_byte_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>; <&mdss_dsi1_pll clk_dsi1pll_byte_clk_src>, <&mdss_dsi1_pll clk_dsi1pll_pixel_clk_src>, <&mdss_dsi1_pll clk_dsi1pll_shadow_byte_clk_src>, <&mdss_dsi1_pll clk_dsi1pll_shadow_pixel_clk_src>; clock-names = "byte_clk", "pixel_clk", "core_clk", "byte_clk_rcg", "pixel_clk_rcg", "pll_byte_clk_mux", "pll_pixel_clk_mux", "pll_byte_clk_src", "pll_pixel_clk_src"; "pll_byte_clk_src", "pll_pixel_clk_src", "pll_byte_clk_src", "pll_pixel_clk_src", "pll_shadow_byte_clk_src", "pll_shadow_pixel_clk_src"; qcom,null-insertion-enabled; qcom,platform-strength-ctrl = [ff 06 Loading drivers/video/msm/mdss/mdss_dsi.c +292 −127 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include "mdss_panel.h" #include "mdss_dsi.h" #include "mdss_debug.h" #include "mdss_dsi_phy.h" #define XO_CLK_RATE 19200000 #define CMDLINE_DSI_CTL_NUM_STRING_LEN 2 Loading Loading @@ -1247,6 +1248,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) * sent to panel */ mdss_dsi_read_hw_revision(ctrl_pdata); mdss_dsi_read_phy_revision(ctrl_pdata); mdss_dsi_restore_intr_mask(ctrl_pdata); pr_debug("%s: panel already on\n", __func__); goto end; Loading Loading @@ -1295,6 +1297,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) MDSS_DSI_LINK_CLK, MDSS_DSI_CLK_ON); mdss_dsi_sw_reset(ctrl_pdata, true); mdss_dsi_read_hw_revision(ctrl_pdata); mdss_dsi_read_phy_revision(ctrl_pdata); /* * Issue hardware reset line after enabling the DSI clocks and data Loading Loading @@ -1642,13 +1645,33 @@ static void __mdss_dsi_update_video_mode_total(struct mdss_panel_data *pdata, static void __mdss_dsi_dyn_refresh_config( struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int reg_data; int reg_data = 0; u32 phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata); reg_data = MIPI_INP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL); /* configure only for master control in split display */ if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) return; switch (phy_rev) { case DSI_PHY_REV_10: reg_data = MIPI_INP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL); reg_data &= ~BIT(12); MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, reg_data); break; case DSI_PHY_REV_20: reg_data = BIT(13); MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, reg_data); break; default: pr_err("Phy rev %d unsupported\n", phy_rev); break; } pr_debug("Dynamic fps ctrl = 0x%x\n", reg_data); MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, reg_data); } static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata) Loading @@ -1668,6 +1691,14 @@ static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata) ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (ctrl_pdata == NULL) { pr_err("%s Invalid ctrl_pdata\n", __func__); return; } if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) return; pinfo = &pdata->panel_info; pd = &(pinfo->mipi.dsi_phy_db); Loading Loading @@ -1706,13 +1737,14 @@ static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata) pll_delay); } static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; u32 data; u64 clk_rate; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *pinfo; u32 phy_rev; if (pdata == NULL) { pr_err("%s Invalid pdata\n", __func__); Loading @@ -1726,6 +1758,9 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, return -EINVAL; } pinfo = &pdata->panel_info; phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata); rc = mdss_dsi_clk_div_config (&ctrl_pdata->panel_data.panel_info, new_fps); if (rc) { Loading @@ -1734,42 +1769,116 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, return rc; } if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { __mdss_dsi_dyn_refresh_config(ctrl_pdata); if (phy_rev == DSI_PHY_REV_20) mdss_dsi_dfps_config_8996(ctrl_pdata); __mdss_dsi_calc_dfps_delay(pdata); ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; clk_rate = pdata->panel_info.clk_rate; /* take a backup of current clk rates */ ctrl_pdata->pclk_rate_bkp = ctrl_pdata->pclk_rate; ctrl_pdata->byte_clk_rate_bkp = ctrl_pdata->byte_clk_rate; ctrl_pdata->pclk_rate = pinfo->mipi.dsi_pclk_rate; clk_rate = pinfo->clk_rate; do_div(clk_rate, 8U); ctrl_pdata->byte_clk_rate = (u32) clk_rate; pr_debug("byte_rate=%i\n", ctrl_pdata->byte_clk_rate); pr_debug("pclk_rate=%i\n", ctrl_pdata->pclk_rate); if (mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) { pr_debug("%s DFPS already updated.\n", __func__); ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; return rc; } /* add an extra reference to main clks */ clk_prepare_enable(ctrl_pdata->pll_byte_clk); clk_prepare_enable(ctrl_pdata->pll_pixel_clk); static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, int new_fps) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL; struct mdss_panel_info *pinfo, *spinfo; int rc = 0; u32 data; if (pdata == NULL) { pr_err("%s Invalid pdata\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (IS_ERR_OR_NULL(ctrl_pdata)) { pr_err("Invalid sctrl_pdata = %lu\n", PTR_ERR(ctrl_pdata)); return PTR_ERR(ctrl_pdata); } pinfo = &ctrl_pdata->panel_data.panel_info; /* * In split display case, configure and enable dynamic refresh * register only after both the ctrl data is programmed. So, * ignore enabling dynamic refresh for the master control and * configure only when it is slave control. */ if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_master(ctrl_pdata)) return 0; if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) { sctrl_pdata = ctrl_pdata; spinfo = pinfo; ctrl_pdata = mdss_dsi_get_ctrl_clk_master(); if (IS_ERR_OR_NULL(ctrl_pdata)) { pr_err("Invalid ctrl_pdata = %lu\n", PTR_ERR(ctrl_pdata)); return PTR_ERR(ctrl_pdata); } pinfo = &ctrl_pdata->panel_data.panel_info; } /* * For programming dynamic refresh registers, we need to change * the parent to shadow clocks for the software byte and pixel mux. * After switching to shadow clocks, if there is no ref count on * main byte and pixel clocks, clock driver may shutdown those * unreferenced byte and pixel clocks. Hence add an extra reference * count to avoid shutting down the main byte and pixel clocks. */ rc = clk_prepare_enable(ctrl_pdata->pll_byte_clk); if (rc) { pr_err("Unable to add extra refcnt for byte clock\n"); goto error_byte; } rc = clk_prepare_enable(ctrl_pdata->pll_pixel_clk); if (rc) { pr_err("Unable to add extra refcnt for pixel clock\n"); goto error_pixel; } /* change the parent to shadow clocks*/ clk_set_parent(ctrl_pdata->mux_byte_clk, rc = clk_set_parent(ctrl_pdata->mux_byte_clk, ctrl_pdata->shadow_byte_clk); clk_set_parent(ctrl_pdata->mux_pixel_clk, if (rc) { pr_err("Unable to set parent to shadow byte clock\n"); goto error_shadow_byte; } rc = clk_set_parent(ctrl_pdata->mux_pixel_clk, ctrl_pdata->shadow_pixel_clk); if (rc) { pr_err("Unable to set parent to shadow pixel clock\n"); goto error_shadow_pixel; } rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate, 0); if (rc) { pr_err("%s: dsi_byte_clk - clk_set_rate failed\n", __func__); return rc; goto error_byte_link; } rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, Loading @@ -1777,55 +1886,93 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, if (rc) { pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n", __func__); return rc; goto error_pixel_link; } if (sctrl_pdata) { rc = mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, sctrl_pdata->byte_clk_rate, 0); if (rc) { pr_err("%s: slv dsi_byte_clk - clk_set_rate failed\n", __func__); goto error_sbyte_link; } rc = mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, sctrl_pdata->pclk_rate, 0); if (rc) { pr_err("%s: slv dsi_pixel_clk - clk_set_rate failed\n", __func__); goto error_spixel_link; } } rc = mdss_dsi_en_wait4dynamic_done(ctrl_pdata); MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, if (rc) { pr_err("Unsuccessful dynamic fps change"); goto dfps_timeout; } MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, 0x00); if (sctrl_pdata) MIPI_OUTP((sctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, 0x00); data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0120); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x120, data); pr_debug("pll unlock: 0x%x\n", data); clk_set_parent(ctrl_pdata->mux_byte_clk, if (data & BIT(16)) { pr_debug("pll unlocked: 0x%x\n", data); /* clear PLL unlock bit */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x120, BIT(16)); } /* Move the mux clocks to main byte and pixel clocks */ rc = clk_set_parent(ctrl_pdata->mux_byte_clk, ctrl_pdata->pll_byte_clk); clk_set_parent(ctrl_pdata->mux_pixel_clk, if (rc) pr_err("Unable to set parent back to main byte clock\n"); rc = clk_set_parent(ctrl_pdata->mux_pixel_clk, ctrl_pdata->pll_pixel_clk); if (rc) pr_err("Unable to set parent back to main pixel clock\n"); /* Remove extra ref count on parent clocks */ clk_disable_unprepare(ctrl_pdata->pll_byte_clk); clk_disable_unprepare(ctrl_pdata->pll_pixel_clk); if (!rc) { ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; /* we are using current_fps to compare if dfps needed */ ctrl_pdata->panel_data.panel_info.current_fps = new_fps; } } else { ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; clk_rate = pdata->panel_info.clk_rate; do_div(clk_rate, 8U); ctrl_pdata->byte_clk_rate = (u32) clk_rate; rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate, MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); if (rc) { pr_err("%s: dsi_byte_clk - clk_set_rate failed\n", __func__); return rc; /* update new fps that at this point is already updated in hw */ pinfo->current_fps = new_fps; if (sctrl_pdata) { spinfo->current_fps = new_fps; } rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate, MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); if (rc) { pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n", __func__); return rc; } } dfps_timeout: if (sctrl_pdata) mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, sctrl_pdata->pclk_rate_bkp, 0); error_spixel_link: if (sctrl_pdata) mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, sctrl_pdata->byte_clk_rate_bkp, 0); error_sbyte_link: mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate_bkp, 0); error_pixel_link: mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate_bkp, 0); error_byte_link: clk_set_parent(ctrl_pdata->mux_pixel_clk, ctrl_pdata->pll_pixel_clk); error_shadow_pixel: clk_set_parent(ctrl_pdata->mux_byte_clk, ctrl_pdata->pll_byte_clk); error_shadow_byte: clk_disable_unprepare(ctrl_pdata->pll_pixel_clk); error_pixel: clk_disable_unprepare(ctrl_pdata->pll_byte_clk); error_byte: return rc; } Loading @@ -1833,8 +1980,9 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL; struct mdss_panel_info *pinfo; u32 phy_rev; u32 frame_rate_bkp; pr_debug("%s+:\n", __func__); Loading @@ -1847,56 +1995,62 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) panel_data); if (!ctrl_pdata->panel_data.panel_info.dynamic_fps) { pr_err("%s: Dynamic fps not enabled for this panel\n", __func__); pr_err("Dynamic fps not enabled for this panel\n"); return -EINVAL; } phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata); pinfo = &pdata->panel_info; /* get the fps configured in HW */ frame_rate_bkp = pinfo->current_fps; if (new_fps == pinfo->current_fps) { /* * at split display case, DFPS registers were already programmed * while programming the left ctrl(DSI0). Ignore right ctrl (DSI1) * reguest. * This is unlikely as mdss driver checks for previously * configured frame rate. */ pinfo = &pdata->panel_info; if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { if (mdss_dsi_is_right_ctrl(ctrl_pdata)) { pr_debug("%s DFPS already updated.\n", __func__); return rc; pr_debug("Panel is already at this FPS\n"); goto end_update; } /* left ctrl to get right ctrl */ sctrl_pdata = mdss_dsi_get_other_ctrl(ctrl_pdata); } if (new_fps != ctrl_pdata->panel_data.panel_info.current_fps) { if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) { if (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) { /* Porch method */ __mdss_dsi_update_video_mode_total(pdata, new_fps); if (sctrl_pdata) { pr_debug("%s Updating slave ctrl DFPS\n", __func__); __mdss_dsi_update_video_mode_total( &sctrl_pdata->panel_data, } else if (pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { /* Clock update method */ if (phy_rev == DSI_PHY_REV_20) { rc = mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, new_fps); if (rc) { pr_err("PHY calculations failed-%d\n", new_fps); goto end_update; } } } else { rc = __mdss_dsi_dfps_update_clks(pdata, new_fps); if (!rc && sctrl_pdata) { pr_debug("%s Updating slave ctrl DFPS\n", __func__); rc = __mdss_dsi_dfps_update_clks( &sctrl_pdata->panel_data, new_fps); rc = __mdss_dsi_dfps_calc_clks(pdata, new_fps); if (rc) { pr_err("error calculating clocks for %d\n", new_fps); goto error_clks; } rc = __mdss_dsi_dfps_update_clks(pdata, new_fps); if (rc) { pr_err("Dynamic refresh failed-%d\n", new_fps); goto error_dfps; } } else { pr_debug("%s: Panel is already at this FPS\n", __func__); } return rc; error_dfps: if (__mdss_dsi_dfps_calc_clks(pdata, frame_rate_bkp)) pr_err("error reverting clock calculations for %d\n", frame_rate_bkp); error_clks: if (mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, frame_rate_bkp)) pr_err("Unable to revert phy timing-%d\n", frame_rate_bkp); end_update: return rc; } Loading Loading @@ -2135,8 +2289,12 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, if (arg != NULL) { rc = mdss_dsi_dfps_config(pdata, (int) (unsigned long) arg); pr_debug("%s:update fps to = %d\n", __func__, (int) (unsigned long) arg); if (rc) pr_err("unable to change fps-%d, error-%d\n", (int) (unsigned long) arg, rc); else pr_debug("panel frame rate changed to %d\n", (int) (unsigned long) arg); } break; case MDSS_EVENT_CONT_SPLASH_BEGIN: Loading Loading @@ -2651,10 +2809,17 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) } pinfo = &(ctrl_pdata->panel_data.panel_info); if (pinfo->dynamic_fps) if (mdss_dsi_shadow_clk_init(pdev, ctrl_pdata)) if (!(mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) && pinfo->dynamic_fps) { rc = mdss_dsi_shadow_clk_init(pdev, ctrl_pdata); if (rc) { pr_err("%s: unable to initialize shadow ctrl clks\n", __func__); rc = -EPERM; } } rc = mdss_dsi_set_clk_rates(ctrl_pdata); if (rc) { Loading drivers/video/msm/mdss/mdss_dsi.h +10 −0 Original line number Diff line number Diff line Loading @@ -234,6 +234,7 @@ struct dsi_shared_data { u32 hw_config; /* DSI setup configuration i.e. single/dual/split */ u32 pll_src_config; /* PLL source selection for DSI link clocks */ u32 hw_rev; /* DSI h/w revision */ u32 phy_rev; /* DSI PHY revision*/ /* DSI ULPS clamp register offsets */ u32 ulps_clamp_ctrl_off; Loading Loading @@ -440,6 +441,8 @@ struct mdss_dsi_ctrl_pdata { struct pwm_device *pwm_bl; u32 pclk_rate; u32 byte_clk_rate; u32 pclk_rate_bkp; u32 byte_clk_rate_bkp; bool refresh_clk_rate; /* flag to recalculate clk_rate */ struct dss_module_power panel_power_data; struct dss_module_power power_data[DSI_MAX_PM]; /* for 8x10 */ Loading Loading @@ -620,6 +623,7 @@ void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_dln0_phy_err(struct mdss_dsi_ctrl_pdata *ctrl, bool print_en); void mdss_dsi_lp_cd_rx(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_read_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl); u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0, char cmd1, void (*fxn)(int), char *rbuf, int len); int mdss_dsi_panel_init(struct device_node *node, Loading @@ -640,6 +644,7 @@ void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl, struct mdss_panel_info *pinfo); void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, struct dsc_desc *dsc); void mdss_dsi_dfps_config_8996(struct mdss_dsi_ctrl_pdata *ctrl); static inline const char *__mdss_dsi_pm_name(enum dsi_pm_type module) { Loading Loading @@ -736,6 +741,11 @@ static inline bool mdss_dsi_is_dsi1_active(struct dsi_shared_data *sdata) return sdata->dsi1_active; } static inline u32 mdss_dsi_get_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl) { return ctrl->shared_data->phy_rev; } static inline bool mdss_dsi_sync_wait_enable(struct mdss_dsi_ctrl_pdata *ctrl) { return ctrl->cmd_sync_wait_broadcast; Loading drivers/video/msm/mdss/mdss_dsi_host.c +40 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "mdss_panel.h" #include "mdss_debug.h" #include "mdss_smmu.h" #include "mdss_dsi_phy.h" #define VSYNC_PERIOD 17 #define DMA_TX_TIMEOUT 200 Loading Loading @@ -290,6 +291,23 @@ void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl) ctrl->ndx, ctrl->shared_data->hw_rev); } void mdss_dsi_read_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl) { u32 reg_val; if (ctrl->shared_data->phy_rev > DSI_PHY_REV_UNKNOWN) return; reg_val = MIPI_INP(ctrl->phy_io.base); if (reg_val == DSI_PHY_REV_20) ctrl->shared_data->phy_rev = DSI_PHY_REV_20; else if (reg_val == DSI_PHY_REV_10) ctrl->shared_data->phy_rev = DSI_PHY_REV_10; else ctrl->shared_data->phy_rev = DSI_PHY_REV_UNKNOWN; } void mdss_dsi_host_init(struct mdss_panel_data *pdata) { u32 dsi_ctrl, intr_ctrl; Loading Loading @@ -2119,6 +2137,7 @@ int mdss_dsi_en_wait4dynamic_done(struct mdss_dsi_ctrl_pdata *ctrl) unsigned long flag; u32 data; int rc = 0; struct mdss_dsi_ctrl_pdata *sctrl_pdata; /* DSI_INTL_CTRL */ data = MIPI_INP((ctrl->ctrl_base) + 0x0110); Loading @@ -2130,8 +2149,21 @@ int mdss_dsi_en_wait4dynamic_done(struct mdss_dsi_ctrl_pdata *ctrl) reinit_completion(&ctrl->dynamic_comp); mdss_dsi_enable_irq(ctrl, DSI_DYNAMIC_TERM); spin_unlock_irqrestore(&ctrl->mdp_lock, flag); /* * Ensure that registers are updated before triggering * dynamic refresh */ wmb(); MIPI_OUTP((ctrl->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, (BIT(8) | BIT(0))); (BIT(13) | BIT(8) | BIT(0))); sctrl_pdata = mdss_dsi_get_ctrl_clk_slave(); if (sctrl_pdata) MIPI_OUTP((sctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, (BIT(13) | BIT(8) | BIT(0))); if (!wait_for_completion_timeout(&ctrl->dynamic_comp, msecs_to_jiffies(VSYNC_PERIOD * 4))) { Loading Loading @@ -2814,6 +2846,7 @@ void mdss_dsi_error(struct mdss_dsi_ctrl_pdata *ctrl) irqreturn_t mdss_dsi_isr(int irq, void *ptr) { u32 isr; u32 intr; struct mdss_dsi_ctrl_pdata *ctrl = (struct mdss_dsi_ctrl_pdata *)ptr; Loading Loading @@ -2890,6 +2923,12 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr) if (isr & DSI_INTR_DYNAMIC_REFRESH_DONE) { spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_DYNAMIC_TERM); /* clear dfps interrupt */ intr = MIPI_INP(ctrl->ctrl_base + 0x0110); intr |= DSI_INTR_DYNAMIC_REFRESH_DONE; MIPI_OUTP(ctrl->ctrl_base + 0x0110, intr); complete(&ctrl->dynamic_comp); spin_unlock(&ctrl->mdp_lock); } Loading Loading
arch/arm/boot/dts/qcom/dsi-panel-sharp-dualmipi-wqxga-video.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ qcom,mdss-dsi-min-refresh-rate = <53>; qcom,mdss-dsi-max-refresh-rate = <60>; qcom,mdss-dsi-pan-enable-dynamic-fps; qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; qcom,mdss-dsi-pan-fps-update = "dfps_immediate_clk_mode"; qcom,mdss-dsi-panel-status-check-mode = "bta_check"; qcom,mdss-dsi-tx-eot-append; qcom,esd-check-enabled; Loading
arch/arm/boot/dts/qcom/msm8996-mdss.dtsi +18 −5 Original line number Diff line number Diff line Loading @@ -385,11 +385,17 @@ <&mdss_dsi0_pll clk_dsi0pll_byte_clk_mux>, <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_mux>, <&mdss_dsi0_pll clk_dsi0pll_byte_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>; <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_shadow_byte_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_shadow_pixel_clk_src>; clock-names = "byte_clk", "pixel_clk", "core_clk", "byte_clk_rcg", "pixel_clk_rcg", "pll_byte_clk_mux", "pll_pixel_clk_mux", "pll_byte_clk_src", "pll_pixel_clk_src"; "pll_byte_clk_src", "pll_pixel_clk_src", "pll_shadow_byte_clk_src", "pll_shadow_pixel_clk_src"; qcom,null-insertion-enabled; qcom,platform-strength-ctrl = [ff 06 Loading Loading @@ -429,12 +435,19 @@ <&clock_mmss clk_pclk1_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_byte_clk_mux>, <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_mux>, <&mdss_dsi0_pll clk_dsi0pll_byte_clk_src>, <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>; <&mdss_dsi1_pll clk_dsi1pll_byte_clk_src>, <&mdss_dsi1_pll clk_dsi1pll_pixel_clk_src>, <&mdss_dsi1_pll clk_dsi1pll_shadow_byte_clk_src>, <&mdss_dsi1_pll clk_dsi1pll_shadow_pixel_clk_src>; clock-names = "byte_clk", "pixel_clk", "core_clk", "byte_clk_rcg", "pixel_clk_rcg", "pll_byte_clk_mux", "pll_pixel_clk_mux", "pll_byte_clk_src", "pll_pixel_clk_src"; "pll_byte_clk_src", "pll_pixel_clk_src", "pll_byte_clk_src", "pll_pixel_clk_src", "pll_shadow_byte_clk_src", "pll_shadow_pixel_clk_src"; qcom,null-insertion-enabled; qcom,platform-strength-ctrl = [ff 06 Loading
drivers/video/msm/mdss/mdss_dsi.c +292 −127 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include "mdss_panel.h" #include "mdss_dsi.h" #include "mdss_debug.h" #include "mdss_dsi_phy.h" #define XO_CLK_RATE 19200000 #define CMDLINE_DSI_CTL_NUM_STRING_LEN 2 Loading Loading @@ -1247,6 +1248,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) * sent to panel */ mdss_dsi_read_hw_revision(ctrl_pdata); mdss_dsi_read_phy_revision(ctrl_pdata); mdss_dsi_restore_intr_mask(ctrl_pdata); pr_debug("%s: panel already on\n", __func__); goto end; Loading Loading @@ -1295,6 +1297,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) MDSS_DSI_LINK_CLK, MDSS_DSI_CLK_ON); mdss_dsi_sw_reset(ctrl_pdata, true); mdss_dsi_read_hw_revision(ctrl_pdata); mdss_dsi_read_phy_revision(ctrl_pdata); /* * Issue hardware reset line after enabling the DSI clocks and data Loading Loading @@ -1642,13 +1645,33 @@ static void __mdss_dsi_update_video_mode_total(struct mdss_panel_data *pdata, static void __mdss_dsi_dyn_refresh_config( struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int reg_data; int reg_data = 0; u32 phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata); reg_data = MIPI_INP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL); /* configure only for master control in split display */ if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) return; switch (phy_rev) { case DSI_PHY_REV_10: reg_data = MIPI_INP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL); reg_data &= ~BIT(12); MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, reg_data); break; case DSI_PHY_REV_20: reg_data = BIT(13); MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, reg_data); break; default: pr_err("Phy rev %d unsupported\n", phy_rev); break; } pr_debug("Dynamic fps ctrl = 0x%x\n", reg_data); MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, reg_data); } static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata) Loading @@ -1668,6 +1691,14 @@ static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata) ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (ctrl_pdata == NULL) { pr_err("%s Invalid ctrl_pdata\n", __func__); return; } if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) return; pinfo = &pdata->panel_info; pd = &(pinfo->mipi.dsi_phy_db); Loading Loading @@ -1706,13 +1737,14 @@ static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata) pll_delay); } static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; u32 data; u64 clk_rate; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_panel_info *pinfo; u32 phy_rev; if (pdata == NULL) { pr_err("%s Invalid pdata\n", __func__); Loading @@ -1726,6 +1758,9 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, return -EINVAL; } pinfo = &pdata->panel_info; phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata); rc = mdss_dsi_clk_div_config (&ctrl_pdata->panel_data.panel_info, new_fps); if (rc) { Loading @@ -1734,42 +1769,116 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, return rc; } if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { __mdss_dsi_dyn_refresh_config(ctrl_pdata); if (phy_rev == DSI_PHY_REV_20) mdss_dsi_dfps_config_8996(ctrl_pdata); __mdss_dsi_calc_dfps_delay(pdata); ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; clk_rate = pdata->panel_info.clk_rate; /* take a backup of current clk rates */ ctrl_pdata->pclk_rate_bkp = ctrl_pdata->pclk_rate; ctrl_pdata->byte_clk_rate_bkp = ctrl_pdata->byte_clk_rate; ctrl_pdata->pclk_rate = pinfo->mipi.dsi_pclk_rate; clk_rate = pinfo->clk_rate; do_div(clk_rate, 8U); ctrl_pdata->byte_clk_rate = (u32) clk_rate; pr_debug("byte_rate=%i\n", ctrl_pdata->byte_clk_rate); pr_debug("pclk_rate=%i\n", ctrl_pdata->pclk_rate); if (mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) { pr_debug("%s DFPS already updated.\n", __func__); ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; return rc; } /* add an extra reference to main clks */ clk_prepare_enable(ctrl_pdata->pll_byte_clk); clk_prepare_enable(ctrl_pdata->pll_pixel_clk); static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, int new_fps) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL; struct mdss_panel_info *pinfo, *spinfo; int rc = 0; u32 data; if (pdata == NULL) { pr_err("%s Invalid pdata\n", __func__); return -EINVAL; } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); if (IS_ERR_OR_NULL(ctrl_pdata)) { pr_err("Invalid sctrl_pdata = %lu\n", PTR_ERR(ctrl_pdata)); return PTR_ERR(ctrl_pdata); } pinfo = &ctrl_pdata->panel_data.panel_info; /* * In split display case, configure and enable dynamic refresh * register only after both the ctrl data is programmed. So, * ignore enabling dynamic refresh for the master control and * configure only when it is slave control. */ if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_master(ctrl_pdata)) return 0; if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) { sctrl_pdata = ctrl_pdata; spinfo = pinfo; ctrl_pdata = mdss_dsi_get_ctrl_clk_master(); if (IS_ERR_OR_NULL(ctrl_pdata)) { pr_err("Invalid ctrl_pdata = %lu\n", PTR_ERR(ctrl_pdata)); return PTR_ERR(ctrl_pdata); } pinfo = &ctrl_pdata->panel_data.panel_info; } /* * For programming dynamic refresh registers, we need to change * the parent to shadow clocks for the software byte and pixel mux. * After switching to shadow clocks, if there is no ref count on * main byte and pixel clocks, clock driver may shutdown those * unreferenced byte and pixel clocks. Hence add an extra reference * count to avoid shutting down the main byte and pixel clocks. */ rc = clk_prepare_enable(ctrl_pdata->pll_byte_clk); if (rc) { pr_err("Unable to add extra refcnt for byte clock\n"); goto error_byte; } rc = clk_prepare_enable(ctrl_pdata->pll_pixel_clk); if (rc) { pr_err("Unable to add extra refcnt for pixel clock\n"); goto error_pixel; } /* change the parent to shadow clocks*/ clk_set_parent(ctrl_pdata->mux_byte_clk, rc = clk_set_parent(ctrl_pdata->mux_byte_clk, ctrl_pdata->shadow_byte_clk); clk_set_parent(ctrl_pdata->mux_pixel_clk, if (rc) { pr_err("Unable to set parent to shadow byte clock\n"); goto error_shadow_byte; } rc = clk_set_parent(ctrl_pdata->mux_pixel_clk, ctrl_pdata->shadow_pixel_clk); if (rc) { pr_err("Unable to set parent to shadow pixel clock\n"); goto error_shadow_pixel; } rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate, 0); if (rc) { pr_err("%s: dsi_byte_clk - clk_set_rate failed\n", __func__); return rc; goto error_byte_link; } rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, Loading @@ -1777,55 +1886,93 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata, if (rc) { pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n", __func__); return rc; goto error_pixel_link; } if (sctrl_pdata) { rc = mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, sctrl_pdata->byte_clk_rate, 0); if (rc) { pr_err("%s: slv dsi_byte_clk - clk_set_rate failed\n", __func__); goto error_sbyte_link; } rc = mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, sctrl_pdata->pclk_rate, 0); if (rc) { pr_err("%s: slv dsi_pixel_clk - clk_set_rate failed\n", __func__); goto error_spixel_link; } } rc = mdss_dsi_en_wait4dynamic_done(ctrl_pdata); MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, if (rc) { pr_err("Unsuccessful dynamic fps change"); goto dfps_timeout; } MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, 0x00); if (sctrl_pdata) MIPI_OUTP((sctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, 0x00); data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0120); MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x120, data); pr_debug("pll unlock: 0x%x\n", data); clk_set_parent(ctrl_pdata->mux_byte_clk, if (data & BIT(16)) { pr_debug("pll unlocked: 0x%x\n", data); /* clear PLL unlock bit */ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x120, BIT(16)); } /* Move the mux clocks to main byte and pixel clocks */ rc = clk_set_parent(ctrl_pdata->mux_byte_clk, ctrl_pdata->pll_byte_clk); clk_set_parent(ctrl_pdata->mux_pixel_clk, if (rc) pr_err("Unable to set parent back to main byte clock\n"); rc = clk_set_parent(ctrl_pdata->mux_pixel_clk, ctrl_pdata->pll_pixel_clk); if (rc) pr_err("Unable to set parent back to main pixel clock\n"); /* Remove extra ref count on parent clocks */ clk_disable_unprepare(ctrl_pdata->pll_byte_clk); clk_disable_unprepare(ctrl_pdata->pll_pixel_clk); if (!rc) { ctrl_pdata->panel_data.panel_info.mipi.frame_rate = new_fps; /* we are using current_fps to compare if dfps needed */ ctrl_pdata->panel_data.panel_info.current_fps = new_fps; } } else { ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate; clk_rate = pdata->panel_info.clk_rate; do_div(clk_rate, 8U); ctrl_pdata->byte_clk_rate = (u32) clk_rate; rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate, MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); if (rc) { pr_err("%s: dsi_byte_clk - clk_set_rate failed\n", __func__); return rc; /* update new fps that at this point is already updated in hw */ pinfo->current_fps = new_fps; if (sctrl_pdata) { spinfo->current_fps = new_fps; } rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate, MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON); if (rc) { pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n", __func__); return rc; } } dfps_timeout: if (sctrl_pdata) mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, sctrl_pdata->pclk_rate_bkp, 0); error_spixel_link: if (sctrl_pdata) mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, sctrl_pdata->byte_clk_rate_bkp, 0); error_sbyte_link: mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate_bkp, 0); error_pixel_link: mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle, MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate_bkp, 0); error_byte_link: clk_set_parent(ctrl_pdata->mux_pixel_clk, ctrl_pdata->pll_pixel_clk); error_shadow_pixel: clk_set_parent(ctrl_pdata->mux_byte_clk, ctrl_pdata->pll_byte_clk); error_shadow_byte: clk_disable_unprepare(ctrl_pdata->pll_pixel_clk); error_pixel: clk_disable_unprepare(ctrl_pdata->pll_byte_clk); error_byte: return rc; } Loading @@ -1833,8 +1980,9 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL; struct mdss_panel_info *pinfo; u32 phy_rev; u32 frame_rate_bkp; pr_debug("%s+:\n", __func__); Loading @@ -1847,56 +1995,62 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) panel_data); if (!ctrl_pdata->panel_data.panel_info.dynamic_fps) { pr_err("%s: Dynamic fps not enabled for this panel\n", __func__); pr_err("Dynamic fps not enabled for this panel\n"); return -EINVAL; } phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata); pinfo = &pdata->panel_info; /* get the fps configured in HW */ frame_rate_bkp = pinfo->current_fps; if (new_fps == pinfo->current_fps) { /* * at split display case, DFPS registers were already programmed * while programming the left ctrl(DSI0). Ignore right ctrl (DSI1) * reguest. * This is unlikely as mdss driver checks for previously * configured frame rate. */ pinfo = &pdata->panel_info; if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) { if (mdss_dsi_is_right_ctrl(ctrl_pdata)) { pr_debug("%s DFPS already updated.\n", __func__); return rc; pr_debug("Panel is already at this FPS\n"); goto end_update; } /* left ctrl to get right ctrl */ sctrl_pdata = mdss_dsi_get_other_ctrl(ctrl_pdata); } if (new_fps != ctrl_pdata->panel_data.panel_info.current_fps) { if (pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || pdata->panel_info.dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) { if (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP || pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) { /* Porch method */ __mdss_dsi_update_video_mode_total(pdata, new_fps); if (sctrl_pdata) { pr_debug("%s Updating slave ctrl DFPS\n", __func__); __mdss_dsi_update_video_mode_total( &sctrl_pdata->panel_data, } else if (pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) { /* Clock update method */ if (phy_rev == DSI_PHY_REV_20) { rc = mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, new_fps); if (rc) { pr_err("PHY calculations failed-%d\n", new_fps); goto end_update; } } } else { rc = __mdss_dsi_dfps_update_clks(pdata, new_fps); if (!rc && sctrl_pdata) { pr_debug("%s Updating slave ctrl DFPS\n", __func__); rc = __mdss_dsi_dfps_update_clks( &sctrl_pdata->panel_data, new_fps); rc = __mdss_dsi_dfps_calc_clks(pdata, new_fps); if (rc) { pr_err("error calculating clocks for %d\n", new_fps); goto error_clks; } rc = __mdss_dsi_dfps_update_clks(pdata, new_fps); if (rc) { pr_err("Dynamic refresh failed-%d\n", new_fps); goto error_dfps; } } else { pr_debug("%s: Panel is already at this FPS\n", __func__); } return rc; error_dfps: if (__mdss_dsi_dfps_calc_clks(pdata, frame_rate_bkp)) pr_err("error reverting clock calculations for %d\n", frame_rate_bkp); error_clks: if (mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, frame_rate_bkp)) pr_err("Unable to revert phy timing-%d\n", frame_rate_bkp); end_update: return rc; } Loading Loading @@ -2135,8 +2289,12 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, if (arg != NULL) { rc = mdss_dsi_dfps_config(pdata, (int) (unsigned long) arg); pr_debug("%s:update fps to = %d\n", __func__, (int) (unsigned long) arg); if (rc) pr_err("unable to change fps-%d, error-%d\n", (int) (unsigned long) arg, rc); else pr_debug("panel frame rate changed to %d\n", (int) (unsigned long) arg); } break; case MDSS_EVENT_CONT_SPLASH_BEGIN: Loading Loading @@ -2651,10 +2809,17 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) } pinfo = &(ctrl_pdata->panel_data.panel_info); if (pinfo->dynamic_fps) if (mdss_dsi_shadow_clk_init(pdev, ctrl_pdata)) if (!(mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) && mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) && pinfo->dynamic_fps) { rc = mdss_dsi_shadow_clk_init(pdev, ctrl_pdata); if (rc) { pr_err("%s: unable to initialize shadow ctrl clks\n", __func__); rc = -EPERM; } } rc = mdss_dsi_set_clk_rates(ctrl_pdata); if (rc) { Loading
drivers/video/msm/mdss/mdss_dsi.h +10 −0 Original line number Diff line number Diff line Loading @@ -234,6 +234,7 @@ struct dsi_shared_data { u32 hw_config; /* DSI setup configuration i.e. single/dual/split */ u32 pll_src_config; /* PLL source selection for DSI link clocks */ u32 hw_rev; /* DSI h/w revision */ u32 phy_rev; /* DSI PHY revision*/ /* DSI ULPS clamp register offsets */ u32 ulps_clamp_ctrl_off; Loading Loading @@ -440,6 +441,8 @@ struct mdss_dsi_ctrl_pdata { struct pwm_device *pwm_bl; u32 pclk_rate; u32 byte_clk_rate; u32 pclk_rate_bkp; u32 byte_clk_rate_bkp; bool refresh_clk_rate; /* flag to recalculate clk_rate */ struct dss_module_power panel_power_data; struct dss_module_power power_data[DSI_MAX_PM]; /* for 8x10 */ Loading Loading @@ -620,6 +623,7 @@ void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_dln0_phy_err(struct mdss_dsi_ctrl_pdata *ctrl, bool print_en); void mdss_dsi_lp_cd_rx(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl); void mdss_dsi_read_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl); u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0, char cmd1, void (*fxn)(int), char *rbuf, int len); int mdss_dsi_panel_init(struct device_node *node, Loading @@ -640,6 +644,7 @@ void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl, struct mdss_panel_info *pinfo); void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, struct dsc_desc *dsc); void mdss_dsi_dfps_config_8996(struct mdss_dsi_ctrl_pdata *ctrl); static inline const char *__mdss_dsi_pm_name(enum dsi_pm_type module) { Loading Loading @@ -736,6 +741,11 @@ static inline bool mdss_dsi_is_dsi1_active(struct dsi_shared_data *sdata) return sdata->dsi1_active; } static inline u32 mdss_dsi_get_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl) { return ctrl->shared_data->phy_rev; } static inline bool mdss_dsi_sync_wait_enable(struct mdss_dsi_ctrl_pdata *ctrl) { return ctrl->cmd_sync_wait_broadcast; Loading
drivers/video/msm/mdss/mdss_dsi_host.c +40 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "mdss_panel.h" #include "mdss_debug.h" #include "mdss_smmu.h" #include "mdss_dsi_phy.h" #define VSYNC_PERIOD 17 #define DMA_TX_TIMEOUT 200 Loading Loading @@ -290,6 +291,23 @@ void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl) ctrl->ndx, ctrl->shared_data->hw_rev); } void mdss_dsi_read_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl) { u32 reg_val; if (ctrl->shared_data->phy_rev > DSI_PHY_REV_UNKNOWN) return; reg_val = MIPI_INP(ctrl->phy_io.base); if (reg_val == DSI_PHY_REV_20) ctrl->shared_data->phy_rev = DSI_PHY_REV_20; else if (reg_val == DSI_PHY_REV_10) ctrl->shared_data->phy_rev = DSI_PHY_REV_10; else ctrl->shared_data->phy_rev = DSI_PHY_REV_UNKNOWN; } void mdss_dsi_host_init(struct mdss_panel_data *pdata) { u32 dsi_ctrl, intr_ctrl; Loading Loading @@ -2119,6 +2137,7 @@ int mdss_dsi_en_wait4dynamic_done(struct mdss_dsi_ctrl_pdata *ctrl) unsigned long flag; u32 data; int rc = 0; struct mdss_dsi_ctrl_pdata *sctrl_pdata; /* DSI_INTL_CTRL */ data = MIPI_INP((ctrl->ctrl_base) + 0x0110); Loading @@ -2130,8 +2149,21 @@ int mdss_dsi_en_wait4dynamic_done(struct mdss_dsi_ctrl_pdata *ctrl) reinit_completion(&ctrl->dynamic_comp); mdss_dsi_enable_irq(ctrl, DSI_DYNAMIC_TERM); spin_unlock_irqrestore(&ctrl->mdp_lock, flag); /* * Ensure that registers are updated before triggering * dynamic refresh */ wmb(); MIPI_OUTP((ctrl->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, (BIT(8) | BIT(0))); (BIT(13) | BIT(8) | BIT(0))); sctrl_pdata = mdss_dsi_get_ctrl_clk_slave(); if (sctrl_pdata) MIPI_OUTP((sctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, (BIT(13) | BIT(8) | BIT(0))); if (!wait_for_completion_timeout(&ctrl->dynamic_comp, msecs_to_jiffies(VSYNC_PERIOD * 4))) { Loading Loading @@ -2814,6 +2846,7 @@ void mdss_dsi_error(struct mdss_dsi_ctrl_pdata *ctrl) irqreturn_t mdss_dsi_isr(int irq, void *ptr) { u32 isr; u32 intr; struct mdss_dsi_ctrl_pdata *ctrl = (struct mdss_dsi_ctrl_pdata *)ptr; Loading Loading @@ -2890,6 +2923,12 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr) if (isr & DSI_INTR_DYNAMIC_REFRESH_DONE) { spin_lock(&ctrl->mdp_lock); mdss_dsi_disable_irq_nosync(ctrl, DSI_DYNAMIC_TERM); /* clear dfps interrupt */ intr = MIPI_INP(ctrl->ctrl_base + 0x0110); intr |= DSI_INTR_DYNAMIC_REFRESH_DONE; MIPI_OUTP(ctrl->ctrl_base + 0x0110, intr); complete(&ctrl->dynamic_comp); spin_unlock(&ctrl->mdp_lock); } Loading