Loading Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +4 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ Required properties: timing settings for the panel. - qcom,mdss-dsi-panel-timings-phy-v2: An array of length 40 char that specifies the PHY version 2 lane timing settings for the panel. - qcom,mdss-dsi-panel-timings-phy-12nm: An array of length 8 char that specifies the 12nm DSI PHY lane timing settings for the panel. - qcom,mdss-dsi-on-command: A byte stream formed by multiple dcs packets base on qcom dsi controller protocol. byte 0: dcs data type Loading Loading @@ -631,6 +633,8 @@ Example: 23 20 06 09 05 03 04 a0 23 20 06 09 05 03 04 a0 23 2e 06 08 05 03 04 a0]; qcom,mdss-dsi-panel-timings-phy-12nm = [a9 4e 56 0b 8a 4d 0b d6]; qcom,mdss-dsi-on-command = [32 01 00 00 00 00 02 00 00 29 01 00 00 10 00 02 FF 99]; qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; Loading drivers/video/fbdev/msm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o mdss_dsi_cmd.o mdss_dsi_status.o mdss-dsi-objs += mdss_dsi_panel.o mdss-dsi-objs += msm_mdss_io_8974.o mdss-dsi-objs += mdss_dsi_phy.o mdss-dsi-objs += mdss_dsi_phy_12nm.o mdss-dsi-objs += mdss_dsi_clk.o obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o obj-$(CONFIG_FB_MSM_MDSS) += mdss_panel.o Loading drivers/video/fbdev/msm/mdss_dsi.c +15 −18 Original line number Diff line number Diff line Loading @@ -2989,9 +2989,9 @@ static int mdss_dsi_ctrl_clock_init(struct platform_device *ctrl_pdev, info.core_clks.mmss_misc_ahb_clk = ctrl_pdata->shared_data->mmss_misc_ahb_clk; info.link_clks.esc_clk = ctrl_pdata->esc_clk; info.link_clks.byte_clk = ctrl_pdata->byte_clk; info.link_clks.pixel_clk = ctrl_pdata->pixel_clk; info.link_lp_clks.esc_clk = ctrl_pdata->esc_clk; info.link_hs_clks.byte_clk = ctrl_pdata->byte_clk; info.link_hs_clks.pixel_clk = ctrl_pdata->pixel_clk; info.pre_clkoff_cb = mdss_dsi_pre_clkoff_cb; info.post_clkon_cb = mdss_dsi_post_clkon_cb; Loading Loading @@ -3976,12 +3976,11 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, if (!data) { pr_err("%s:%d, Unable to read Phy Strength ctrl settings\n", __func__, __LINE__); return -EINVAL; } } else { pinfo->mipi.dsi_phy_db.strength_len = len; for (i = 0; i < len; i++) pinfo->mipi.dsi_phy_db.strength[i] = data[i]; } pinfo->mipi.dsi_phy_db.reg_ldo_mode = of_property_read_bool( ctrl_pdev->dev.of_node, "qcom,regulator-ldo-mode"); Loading @@ -3991,12 +3990,11 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, if (!data) { pr_err("%s:%d, Unable to read Phy regulator settings\n", __func__, __LINE__); return -EINVAL; } } else { pinfo->mipi.dsi_phy_db.regulator_len = len; for (i = 0; i < len; i++) pinfo->mipi.dsi_phy_db.regulator[i] = data[i]; } data = of_get_property(ctrl_pdev->dev.of_node, "qcom,platform-bist-ctrl", &len); Loading @@ -4012,12 +4010,11 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, if (!data) { pr_err("%s:%d, Unable to read Phy lane configure settings\n", __func__, __LINE__); return -EINVAL; } } else { pinfo->mipi.dsi_phy_db.lanecfg_len = len; for (i = 0; i < len; i++) pinfo->mipi.dsi_phy_db.lanecfg[i] = data[i]; } ctrl_pdata->timing_db_mode = of_property_read_bool( ctrl_pdev->dev.of_node, "qcom,timing-db-mode"); Loading drivers/video/fbdev/msm/mdss_dsi.h +5 −0 Original line number Diff line number Diff line Loading @@ -337,6 +337,7 @@ struct dsi_panel_timing { struct mdss_panel_timing timing; uint32_t phy_timing[12]; uint32_t phy_timing_8996[40]; uint32_t phy_timing_12nm[8]; /* DSI_CLKOUT_TIMING_CTRL */ char t_clk_post; char t_clk_pre; Loading Loading @@ -616,15 +617,19 @@ void mdss_dsi_shadow_clk_deinit(struct device *dev, struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_dsi_pre_clkoff_cb(void *priv, enum mdss_dsi_clk_type clk_type, enum mdss_dsi_lclk_type l_type, enum mdss_dsi_clk_state new_state); int mdss_dsi_post_clkoff_cb(void *priv, enum mdss_dsi_clk_type clk_type, enum mdss_dsi_lclk_type l_type, enum mdss_dsi_clk_state curr_state); int mdss_dsi_post_clkon_cb(void *priv, enum mdss_dsi_clk_type clk_type, enum mdss_dsi_lclk_type l_type, enum mdss_dsi_clk_state curr_state); int mdss_dsi_pre_clkon_cb(void *priv, enum mdss_dsi_clk_type clk_type, enum mdss_dsi_lclk_type l_type, enum mdss_dsi_clk_state new_state); int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable); void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl); Loading drivers/video/fbdev/msm/mdss_dsi_clk.c +240 −106 Original line number Diff line number Diff line Loading @@ -27,11 +27,9 @@ struct dsi_core_clks { }; struct dsi_link_clks { struct mdss_dsi_link_clk_info clks; struct mdss_dsi_link_hs_clk_info hs_clks; struct mdss_dsi_link_lp_clk_info lp_clks; u32 current_clk_state; u32 byte_clk_rate; u32 pix_clk_rate; u32 esc_clk_rate; }; struct mdss_dsi_clk_mngr { Loading Loading @@ -73,28 +71,27 @@ static int dsi_core_clk_start(struct dsi_core_clks *c_clks) rc = clk_prepare_enable(c_clks->clks.mdp_core_clk); if (rc) { pr_err("%s: failed to enable mdp_core_clock. rc=%d\n", __func__, rc); pr_err("failed to enable mdp_core_clock. rc=%d\n", rc); goto error; } rc = clk_prepare_enable(c_clks->clks.ahb_clk); if (rc) { pr_err("%s: failed to enable ahb clock. rc=%d\n", __func__, rc); pr_err("failed to enable ahb clock. rc=%d\n", rc); goto disable_core_clk; } rc = clk_prepare_enable(c_clks->clks.axi_clk); if (rc) { pr_err("%s: failed to enable ahb clock. rc=%d\n", __func__, rc); pr_err("failed to enable ahb clock. rc=%d\n", rc); goto disable_ahb_clk; } if (c_clks->clks.mmss_misc_ahb_clk) { rc = clk_prepare_enable(c_clks->clks.mmss_misc_ahb_clk); if (rc) { pr_err("%s: failed to enable mmss misc ahb clk.rc=%d\n", __func__, rc); pr_err("failed to enable mmss misc ahb clk.rc=%d\n", rc); goto disable_axi_clk; } } Loading Loading @@ -140,12 +137,15 @@ static int dsi_core_clk_stop(struct dsi_core_clks *c_clks) return rc; } static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_set_rate( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; struct mdss_dsi_clk_mngr *mngr; struct dsi_link_clks *l_clks; struct mdss_dsi_ctrl_pdata *ctrl; l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); /* Loading @@ -160,19 +160,13 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks) if (ctrl->panel_data.panel_info.cont_splash_enabled) return 0; rc = clk_set_rate(l_clks->clks.esc_clk, l_clks->esc_clk_rate); if (rc) { pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); goto error; } rc = clk_set_rate(l_clks->clks.byte_clk, l_clks->byte_clk_rate); rc = clk_set_rate(link_hs_clks->byte_clk, link_hs_clks->byte_clk_rate); if (rc) { pr_err("clk_set_rate failed for byte_clk rc = %d\n", rc); goto error; } rc = clk_set_rate(l_clks->clks.pixel_clk, l_clks->pix_clk_rate); rc = clk_set_rate(link_hs_clks->pixel_clk, link_hs_clks->pix_clk_rate); if (rc) { pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc); goto error; Loading @@ -182,141 +176,203 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks) return rc; } static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_prepare( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; rc = clk_prepare(l_clks->clks.esc_clk); if (rc) { pr_err("%s: Failed to prepare dsi esc clk\n", __func__); goto esc_clk_err; } rc = clk_prepare(l_clks->clks.byte_clk); rc = clk_prepare(link_hs_clks->byte_clk); if (rc) { pr_err("%s: Failed to prepare dsi byte clk\n", __func__); pr_err("Failed to prepare dsi byte clk\n"); goto byte_clk_err; } rc = clk_prepare(l_clks->clks.pixel_clk); rc = clk_prepare(link_hs_clks->pixel_clk); if (rc) { pr_err("%s: Failed to prepare dsi pixel clk\n", __func__); pr_err("Failed to prepare dsi pixel_clk\n"); goto pixel_clk_err; } return rc; pixel_clk_err: clk_unprepare(l_clks->clks.byte_clk); clk_unprepare(link_hs_clks->byte_clk); byte_clk_err: clk_unprepare(l_clks->clks.esc_clk); esc_clk_err: return rc; } static int dsi_link_clk_unprepare(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_unprepare( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; clk_unprepare(l_clks->clks.pixel_clk); clk_unprepare(l_clks->clks.byte_clk); clk_unprepare(l_clks->clks.esc_clk); clk_unprepare(link_hs_clks->pixel_clk); clk_unprepare(link_hs_clks->byte_clk); return rc; } static int dsi_link_clk_enable(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_enable( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; rc = clk_enable(l_clks->clks.esc_clk); rc = clk_enable(link_hs_clks->byte_clk); if (rc) { pr_err("%s: Failed to enable dsi esc clk\n", __func__); goto esc_clk_err; } rc = clk_enable(l_clks->clks.byte_clk); if (rc) { pr_err("%s: Failed to enable dsi byte clk\n", __func__); pr_err("Failed to enable dsi byte clk\n"); goto byte_clk_err; } rc = clk_enable(l_clks->clks.pixel_clk); rc = clk_enable(link_hs_clks->pixel_clk); if (rc) { pr_err("%s: Failed to enable dsi pixel clk\n", __func__); pr_err("Failed to enable dsi pixel_clk\n"); goto pixel_clk_err; } return rc; pixel_clk_err: clk_disable(l_clks->clks.byte_clk); clk_disable(link_hs_clks->byte_clk); byte_clk_err: clk_disable(l_clks->clks.esc_clk); esc_clk_err: return rc; } static int dsi_link_clk_disable(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_disable( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; clk_disable(l_clks->clks.esc_clk); clk_disable(l_clks->clks.pixel_clk); clk_disable(l_clks->clks.byte_clk); clk_disable(link_hs_clks->pixel_clk); clk_disable(link_hs_clks->byte_clk); return rc; } static int dsi_link_clk_start(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_start( struct mdss_dsi_link_hs_clk_info *link_hs_clks, enum mdss_dsi_link_clk_op_type op_type) { int rc = 0; struct dsi_link_clks *l_clks; struct mdss_dsi_clk_mngr *mngr; l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); rc = dsi_link_clk_set_rate(l_clks); if (op_type & MDSS_DSI_LINK_CLK_SET_RATE) { rc = dsi_link_hs_clk_set_rate(link_hs_clks); if (rc) { pr_err("failed to set clk rates, rc = %d\n", rc); pr_err("failed to set HS clk rates, rc = %d\n", rc); goto error; } } rc = dsi_link_clk_prepare(l_clks); if (op_type & MDSS_DSI_LINK_CLK_PREPARE) { rc = dsi_link_hs_clk_prepare(link_hs_clks); if (rc) { pr_err("failed to prepare link clks, rc = %d\n", rc); pr_err("failed to prepare link HS clks, rc = %d\n", rc); goto error; } } rc = dsi_link_clk_enable(l_clks); if (op_type & MDSS_DSI_LINK_CLK_ENABLE) { rc = dsi_link_hs_clk_enable(link_hs_clks); if (rc) { pr_err("failed to enable link clks, rc = %d\n", rc); pr_err("failed to enable link HS clks, rc = %d\n", rc); goto error_unprepare; } } pr_debug("%s: LINK CLOCK IS ON\n", mngr->name); pr_debug("%s: LINK HS CLOCK IS ON\n", mngr->name); return rc; error_unprepare: dsi_link_clk_unprepare(l_clks); dsi_link_hs_clk_unprepare(link_hs_clks); error: return rc; } static int dsi_link_clk_stop(struct dsi_link_clks *l_clks) static int dsi_link_lp_clk_start( struct mdss_dsi_link_lp_clk_info *link_lp_clks) { int rc = 0; struct mdss_dsi_clk_mngr *mngr; struct dsi_link_clks *l_clks; struct mdss_dsi_ctrl_pdata *ctrl; l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); /* * In an ideal world, cont_splash_enabled should not be required inside * the clock manager. But, in the current driver cont_splash_enabled * flag is set inside mdp driver and there is no interface event * associated with this flag setting. Also, set rate for clock need not * be called for every enable call. It should be done only once when * coming out of suspend. */ ctrl = mngr->priv_data; if (ctrl->panel_data.panel_info.cont_splash_enabled) goto prepare; (void)dsi_link_clk_disable(l_clks); rc = clk_set_rate(link_lp_clks->esc_clk, link_lp_clks->esc_clk_rate); if (rc) { pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); goto error; } prepare: rc = clk_prepare(link_lp_clks->esc_clk); if (rc) { pr_err("Failed to prepare dsi esc clk\n"); goto error; } rc = clk_enable(link_lp_clks->esc_clk); if (rc) { pr_err("Failed to enable dsi esc clk\n"); clk_unprepare(l_clks->lp_clks.esc_clk); goto error; } error: pr_debug("%s: LINK LP CLOCK IS ON\n", mngr->name); return rc; } static int dsi_link_hs_clk_stop( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; struct dsi_link_clks *l_clks; struct mdss_dsi_clk_mngr *mngr; l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); (void)dsi_link_clk_unprepare(l_clks); pr_debug("%s: LINK CLOCK IS OFF\n", mngr->name); (void)dsi_link_hs_clk_disable(link_hs_clks); (void)dsi_link_hs_clk_unprepare(link_hs_clks); pr_debug("%s: LINK HS CLOCK IS OFF\n", mngr->name); return rc; } static int dsi_link_lp_clk_stop( struct mdss_dsi_link_lp_clk_info *link_lp_clks) { struct dsi_link_clks *l_clks; struct mdss_dsi_clk_mngr *mngr; l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); clk_disable(l_clks->lp_clks.esc_clk); clk_unprepare(l_clks->lp_clks.esc_clk); pr_debug("%s: LINK LP CLOCK IS OFF\n", mngr->name); return 0; } static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, struct dsi_link_clks *l_clks, u32 l_state) { Loading Loading @@ -347,7 +403,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (c_clks && (c_state == MDSS_DSI_CLK_ON)) { if (c_clks->current_clk_state == MDSS_DSI_CLK_OFF) { rc = mngr->pre_clkon_cb(mngr->priv_data, MDSS_DSI_CORE_CLK, MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE, MDSS_DSI_CLK_ON); if (rc) { pr_err("failed to turn on MDP FS rc= %d\n", rc); Loading @@ -362,7 +418,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, MDSS_DSI_CORE_CLK, MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE, MDSS_DSI_CLK_ON); if (rc) pr_err("post clk on cb failed, rc = %d\n", rc); Loading @@ -375,21 +431,50 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (l_state == MDSS_DSI_CLK_ON) { if (mngr->pre_clkon_cb) { rc = mngr->pre_clkon_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, l_state); MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK, l_state); if (rc) pr_err("pre link clk on cb failed\n"); pr_err("pre link LP clk on cb failed\n"); } rc = dsi_link_clk_start(l_clks); rc = dsi_link_lp_clk_start(&l_clks->lp_clks); if (rc) { pr_err("failed to start link clk rc= %d\n", rc); pr_err("failed to start LP link clk clk\n"); goto error; } if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK, l_state); if (rc) pr_err("post LP clk on cb failed\n"); } if (mngr->pre_clkon_cb) { rc = mngr->pre_clkon_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK, l_state); if (rc) pr_err("post link clk on cb failed\n"); pr_err("pre HS clk on cb failed\n"); } rc = dsi_link_hs_clk_start(&l_clks->hs_clks, (MDSS_DSI_LINK_CLK_SET_RATE | MDSS_DSI_LINK_CLK_PREPARE)); if (rc) { pr_err("failed to prepare HS clk rc= %d\n", rc); goto error; } if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK, l_state); if (rc) pr_err("post HS clk on cb failed\n"); } rc = dsi_link_hs_clk_start(&l_clks->hs_clks, MDSS_DSI_LINK_CLK_ENABLE); if (rc) { pr_err("failed to enable HS clk rc= %d\n", rc); goto error; } } else { /* Loading Loading @@ -418,9 +503,16 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, goto error; } rc = dsi_link_clk_start(l_clks); rc = dsi_link_lp_clk_start(&l_clks->lp_clks); if (rc) { pr_err("LP Link clks did not start\n"); goto error; } rc = dsi_link_hs_clk_start(&l_clks->hs_clks, MDSS_DSI_LINK_CLK_START); if (rc) { pr_err("Link clks did not start\n"); pr_err("HS Link clks did not start\n"); goto error; } l_c_on = true; Loading @@ -429,24 +521,50 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, l_state); MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK, l_state); if (rc) pr_err("pre HS clk off cb failed\n"); } rc = dsi_link_hs_clk_stop(&l_clks->hs_clks); if (rc) { pr_err("failed to stop HS clk, rc = %d\n", rc); goto error; } if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK, l_state); if (rc) pr_err("post HS clk off cb failed\n"); } if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK, l_state); if (rc) pr_err("pre link clk off cb failed\n"); pr_err("pre LP clk off cb failed\n"); } rc = dsi_link_clk_stop(l_clks); rc = dsi_link_lp_clk_stop(&l_clks->lp_clks); if (rc) { pr_err("failed to stop link clk, rc = %d\n", pr_err("failed to stop LP link clk, rc = %d\n", rc); goto error; } if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, l_state); MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK, l_state); if (rc) pr_err("post link clk off cb failed\n"); pr_err("post LP clk off cb failed\n"); } /* * This check is to save unnecessary clock state * change when going from EARLY_GATE to OFF. In the Loading Loading @@ -502,7 +620,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, MDSS_DSI_CORE_CLK, MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE, c_state); if (rc) pr_err("pre core clk off cb failed\n"); Loading @@ -517,7 +635,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (c_state == MDSS_DSI_CLK_OFF) { if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, MDSS_DSI_CORE_CLK, MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE, MDSS_DSI_CLK_OFF); if (rc) pr_err("post clkoff cb fail, rc = %d\n", Loading Loading @@ -610,27 +728,30 @@ static int dsi_set_clk_rate(struct mdss_dsi_clk_mngr *mngr, int clk, u32 rate, MDSS_XLOG(clk, rate, flags); switch (clk) { case MDSS_DSI_LINK_ESC_CLK: mngr->link_clks.esc_clk_rate = rate; mngr->link_clks.lp_clks.esc_clk_rate = rate; if (!flags) { rc = clk_set_rate(mngr->link_clks.clks.esc_clk, rate); rc = clk_set_rate(mngr->link_clks.lp_clks.esc_clk, rate); if (rc) pr_err("set rate failed for esc clk rc=%d\n", rc); } break; case MDSS_DSI_LINK_BYTE_CLK: mngr->link_clks.byte_clk_rate = rate; mngr->link_clks.hs_clks.byte_clk_rate = rate; if (!flags) { rc = clk_set_rate(mngr->link_clks.clks.byte_clk, rate); rc = clk_set_rate(mngr->link_clks.hs_clks.byte_clk, rate); if (rc) pr_err("set rate failed for byte clk rc=%d\n", rc); } break; case MDSS_DSI_LINK_PIX_CLK: mngr->link_clks.pix_clk_rate = rate; mngr->link_clks.hs_clks.pix_clk_rate = rate; if (!flags) { rc = clk_set_rate(mngr->link_clks.clks.pixel_clk, rate); rc = clk_set_rate(mngr->link_clks.hs_clks.pixel_clk, rate); if (rc) pr_err("failed to set rate for pix clk rc=%d\n", rc); Loading Loading @@ -888,8 +1009,10 @@ void *mdss_dsi_clk_init(struct mdss_dsi_clk_info *info) mutex_init(&mngr->clk_mutex); memcpy(&mngr->core_clks.clks, &info->core_clks, sizeof(struct mdss_dsi_core_clk_info)); memcpy(&mngr->link_clks.clks, &info->link_clks, sizeof(struct mdss_dsi_link_clk_info)); memcpy(&mngr->link_clks.hs_clks, &info->link_hs_clks, sizeof(struct mdss_dsi_link_hs_clk_info)); memcpy(&mngr->link_clks.lp_clks, &info->link_lp_clks, sizeof(struct mdss_dsi_link_lp_clk_info)); INIT_LIST_HEAD(&mngr->client_list); mngr->pre_clkon_cb = info->pre_clkon_cb; Loading Loading @@ -981,15 +1104,26 @@ int mdss_dsi_clk_force_toggle(void *client, u32 clk) if ((clk & MDSS_DSI_LINK_CLK) && (mngr->link_clks.current_clk_state == MDSS_DSI_CLK_ON)) { rc = dsi_link_clk_stop(&mngr->link_clks); rc = dsi_link_hs_clk_stop(&mngr->link_clks.hs_clks); if (rc) { pr_err("failed to stop link clks\n"); pr_err("failed to stop HS link clks\n"); goto error; } rc = dsi_link_clk_start(&mngr->link_clks); rc = dsi_link_lp_clk_stop(&mngr->link_clks.lp_clks); if (rc) { pr_err("failed to stop LP link clks\n"); goto error; } rc = dsi_link_lp_clk_start(&mngr->link_clks.lp_clks); if (rc) pr_err("failed to start LP link clks\n"); rc = dsi_link_hs_clk_start(&mngr->link_clks.hs_clks, MDSS_DSI_LINK_CLK_START); if (rc) pr_err("failed to start link clks\n"); pr_err("failed to start HS link clks\n"); } else if (clk & MDSS_DSI_LINK_CLK) { pr_err("cannot reset, link clock is off\n"); Loading Loading
Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt +4 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ Required properties: timing settings for the panel. - qcom,mdss-dsi-panel-timings-phy-v2: An array of length 40 char that specifies the PHY version 2 lane timing settings for the panel. - qcom,mdss-dsi-panel-timings-phy-12nm: An array of length 8 char that specifies the 12nm DSI PHY lane timing settings for the panel. - qcom,mdss-dsi-on-command: A byte stream formed by multiple dcs packets base on qcom dsi controller protocol. byte 0: dcs data type Loading Loading @@ -631,6 +633,8 @@ Example: 23 20 06 09 05 03 04 a0 23 20 06 09 05 03 04 a0 23 2e 06 08 05 03 04 a0]; qcom,mdss-dsi-panel-timings-phy-12nm = [a9 4e 56 0b 8a 4d 0b d6]; qcom,mdss-dsi-on-command = [32 01 00 00 00 00 02 00 00 29 01 00 00 10 00 02 FF 99]; qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; Loading
drivers/video/fbdev/msm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o mdss_dsi_cmd.o mdss_dsi_status.o mdss-dsi-objs += mdss_dsi_panel.o mdss-dsi-objs += msm_mdss_io_8974.o mdss-dsi-objs += mdss_dsi_phy.o mdss-dsi-objs += mdss_dsi_phy_12nm.o mdss-dsi-objs += mdss_dsi_clk.o obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o obj-$(CONFIG_FB_MSM_MDSS) += mdss_panel.o Loading
drivers/video/fbdev/msm/mdss_dsi.c +15 −18 Original line number Diff line number Diff line Loading @@ -2989,9 +2989,9 @@ static int mdss_dsi_ctrl_clock_init(struct platform_device *ctrl_pdev, info.core_clks.mmss_misc_ahb_clk = ctrl_pdata->shared_data->mmss_misc_ahb_clk; info.link_clks.esc_clk = ctrl_pdata->esc_clk; info.link_clks.byte_clk = ctrl_pdata->byte_clk; info.link_clks.pixel_clk = ctrl_pdata->pixel_clk; info.link_lp_clks.esc_clk = ctrl_pdata->esc_clk; info.link_hs_clks.byte_clk = ctrl_pdata->byte_clk; info.link_hs_clks.pixel_clk = ctrl_pdata->pixel_clk; info.pre_clkoff_cb = mdss_dsi_pre_clkoff_cb; info.post_clkon_cb = mdss_dsi_post_clkon_cb; Loading Loading @@ -3976,12 +3976,11 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, if (!data) { pr_err("%s:%d, Unable to read Phy Strength ctrl settings\n", __func__, __LINE__); return -EINVAL; } } else { pinfo->mipi.dsi_phy_db.strength_len = len; for (i = 0; i < len; i++) pinfo->mipi.dsi_phy_db.strength[i] = data[i]; } pinfo->mipi.dsi_phy_db.reg_ldo_mode = of_property_read_bool( ctrl_pdev->dev.of_node, "qcom,regulator-ldo-mode"); Loading @@ -3991,12 +3990,11 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, if (!data) { pr_err("%s:%d, Unable to read Phy regulator settings\n", __func__, __LINE__); return -EINVAL; } } else { pinfo->mipi.dsi_phy_db.regulator_len = len; for (i = 0; i < len; i++) pinfo->mipi.dsi_phy_db.regulator[i] = data[i]; } data = of_get_property(ctrl_pdev->dev.of_node, "qcom,platform-bist-ctrl", &len); Loading @@ -4012,12 +4010,11 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, if (!data) { pr_err("%s:%d, Unable to read Phy lane configure settings\n", __func__, __LINE__); return -EINVAL; } } else { pinfo->mipi.dsi_phy_db.lanecfg_len = len; for (i = 0; i < len; i++) pinfo->mipi.dsi_phy_db.lanecfg[i] = data[i]; } ctrl_pdata->timing_db_mode = of_property_read_bool( ctrl_pdev->dev.of_node, "qcom,timing-db-mode"); Loading
drivers/video/fbdev/msm/mdss_dsi.h +5 −0 Original line number Diff line number Diff line Loading @@ -337,6 +337,7 @@ struct dsi_panel_timing { struct mdss_panel_timing timing; uint32_t phy_timing[12]; uint32_t phy_timing_8996[40]; uint32_t phy_timing_12nm[8]; /* DSI_CLKOUT_TIMING_CTRL */ char t_clk_post; char t_clk_pre; Loading Loading @@ -616,15 +617,19 @@ void mdss_dsi_shadow_clk_deinit(struct device *dev, struct mdss_dsi_ctrl_pdata *ctrl_pdata); int mdss_dsi_pre_clkoff_cb(void *priv, enum mdss_dsi_clk_type clk_type, enum mdss_dsi_lclk_type l_type, enum mdss_dsi_clk_state new_state); int mdss_dsi_post_clkoff_cb(void *priv, enum mdss_dsi_clk_type clk_type, enum mdss_dsi_lclk_type l_type, enum mdss_dsi_clk_state curr_state); int mdss_dsi_post_clkon_cb(void *priv, enum mdss_dsi_clk_type clk_type, enum mdss_dsi_lclk_type l_type, enum mdss_dsi_clk_state curr_state); int mdss_dsi_pre_clkon_cb(void *priv, enum mdss_dsi_clk_type clk_type, enum mdss_dsi_lclk_type l_type, enum mdss_dsi_clk_state new_state); int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable); void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl); Loading
drivers/video/fbdev/msm/mdss_dsi_clk.c +240 −106 Original line number Diff line number Diff line Loading @@ -27,11 +27,9 @@ struct dsi_core_clks { }; struct dsi_link_clks { struct mdss_dsi_link_clk_info clks; struct mdss_dsi_link_hs_clk_info hs_clks; struct mdss_dsi_link_lp_clk_info lp_clks; u32 current_clk_state; u32 byte_clk_rate; u32 pix_clk_rate; u32 esc_clk_rate; }; struct mdss_dsi_clk_mngr { Loading Loading @@ -73,28 +71,27 @@ static int dsi_core_clk_start(struct dsi_core_clks *c_clks) rc = clk_prepare_enable(c_clks->clks.mdp_core_clk); if (rc) { pr_err("%s: failed to enable mdp_core_clock. rc=%d\n", __func__, rc); pr_err("failed to enable mdp_core_clock. rc=%d\n", rc); goto error; } rc = clk_prepare_enable(c_clks->clks.ahb_clk); if (rc) { pr_err("%s: failed to enable ahb clock. rc=%d\n", __func__, rc); pr_err("failed to enable ahb clock. rc=%d\n", rc); goto disable_core_clk; } rc = clk_prepare_enable(c_clks->clks.axi_clk); if (rc) { pr_err("%s: failed to enable ahb clock. rc=%d\n", __func__, rc); pr_err("failed to enable ahb clock. rc=%d\n", rc); goto disable_ahb_clk; } if (c_clks->clks.mmss_misc_ahb_clk) { rc = clk_prepare_enable(c_clks->clks.mmss_misc_ahb_clk); if (rc) { pr_err("%s: failed to enable mmss misc ahb clk.rc=%d\n", __func__, rc); pr_err("failed to enable mmss misc ahb clk.rc=%d\n", rc); goto disable_axi_clk; } } Loading Loading @@ -140,12 +137,15 @@ static int dsi_core_clk_stop(struct dsi_core_clks *c_clks) return rc; } static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_set_rate( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; struct mdss_dsi_clk_mngr *mngr; struct dsi_link_clks *l_clks; struct mdss_dsi_ctrl_pdata *ctrl; l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); /* Loading @@ -160,19 +160,13 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks) if (ctrl->panel_data.panel_info.cont_splash_enabled) return 0; rc = clk_set_rate(l_clks->clks.esc_clk, l_clks->esc_clk_rate); if (rc) { pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); goto error; } rc = clk_set_rate(l_clks->clks.byte_clk, l_clks->byte_clk_rate); rc = clk_set_rate(link_hs_clks->byte_clk, link_hs_clks->byte_clk_rate); if (rc) { pr_err("clk_set_rate failed for byte_clk rc = %d\n", rc); goto error; } rc = clk_set_rate(l_clks->clks.pixel_clk, l_clks->pix_clk_rate); rc = clk_set_rate(link_hs_clks->pixel_clk, link_hs_clks->pix_clk_rate); if (rc) { pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc); goto error; Loading @@ -182,141 +176,203 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks) return rc; } static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_prepare( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; rc = clk_prepare(l_clks->clks.esc_clk); if (rc) { pr_err("%s: Failed to prepare dsi esc clk\n", __func__); goto esc_clk_err; } rc = clk_prepare(l_clks->clks.byte_clk); rc = clk_prepare(link_hs_clks->byte_clk); if (rc) { pr_err("%s: Failed to prepare dsi byte clk\n", __func__); pr_err("Failed to prepare dsi byte clk\n"); goto byte_clk_err; } rc = clk_prepare(l_clks->clks.pixel_clk); rc = clk_prepare(link_hs_clks->pixel_clk); if (rc) { pr_err("%s: Failed to prepare dsi pixel clk\n", __func__); pr_err("Failed to prepare dsi pixel_clk\n"); goto pixel_clk_err; } return rc; pixel_clk_err: clk_unprepare(l_clks->clks.byte_clk); clk_unprepare(link_hs_clks->byte_clk); byte_clk_err: clk_unprepare(l_clks->clks.esc_clk); esc_clk_err: return rc; } static int dsi_link_clk_unprepare(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_unprepare( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; clk_unprepare(l_clks->clks.pixel_clk); clk_unprepare(l_clks->clks.byte_clk); clk_unprepare(l_clks->clks.esc_clk); clk_unprepare(link_hs_clks->pixel_clk); clk_unprepare(link_hs_clks->byte_clk); return rc; } static int dsi_link_clk_enable(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_enable( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; rc = clk_enable(l_clks->clks.esc_clk); rc = clk_enable(link_hs_clks->byte_clk); if (rc) { pr_err("%s: Failed to enable dsi esc clk\n", __func__); goto esc_clk_err; } rc = clk_enable(l_clks->clks.byte_clk); if (rc) { pr_err("%s: Failed to enable dsi byte clk\n", __func__); pr_err("Failed to enable dsi byte clk\n"); goto byte_clk_err; } rc = clk_enable(l_clks->clks.pixel_clk); rc = clk_enable(link_hs_clks->pixel_clk); if (rc) { pr_err("%s: Failed to enable dsi pixel clk\n", __func__); pr_err("Failed to enable dsi pixel_clk\n"); goto pixel_clk_err; } return rc; pixel_clk_err: clk_disable(l_clks->clks.byte_clk); clk_disable(link_hs_clks->byte_clk); byte_clk_err: clk_disable(l_clks->clks.esc_clk); esc_clk_err: return rc; } static int dsi_link_clk_disable(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_disable( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; clk_disable(l_clks->clks.esc_clk); clk_disable(l_clks->clks.pixel_clk); clk_disable(l_clks->clks.byte_clk); clk_disable(link_hs_clks->pixel_clk); clk_disable(link_hs_clks->byte_clk); return rc; } static int dsi_link_clk_start(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_start( struct mdss_dsi_link_hs_clk_info *link_hs_clks, enum mdss_dsi_link_clk_op_type op_type) { int rc = 0; struct dsi_link_clks *l_clks; struct mdss_dsi_clk_mngr *mngr; l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); rc = dsi_link_clk_set_rate(l_clks); if (op_type & MDSS_DSI_LINK_CLK_SET_RATE) { rc = dsi_link_hs_clk_set_rate(link_hs_clks); if (rc) { pr_err("failed to set clk rates, rc = %d\n", rc); pr_err("failed to set HS clk rates, rc = %d\n", rc); goto error; } } rc = dsi_link_clk_prepare(l_clks); if (op_type & MDSS_DSI_LINK_CLK_PREPARE) { rc = dsi_link_hs_clk_prepare(link_hs_clks); if (rc) { pr_err("failed to prepare link clks, rc = %d\n", rc); pr_err("failed to prepare link HS clks, rc = %d\n", rc); goto error; } } rc = dsi_link_clk_enable(l_clks); if (op_type & MDSS_DSI_LINK_CLK_ENABLE) { rc = dsi_link_hs_clk_enable(link_hs_clks); if (rc) { pr_err("failed to enable link clks, rc = %d\n", rc); pr_err("failed to enable link HS clks, rc = %d\n", rc); goto error_unprepare; } } pr_debug("%s: LINK CLOCK IS ON\n", mngr->name); pr_debug("%s: LINK HS CLOCK IS ON\n", mngr->name); return rc; error_unprepare: dsi_link_clk_unprepare(l_clks); dsi_link_hs_clk_unprepare(link_hs_clks); error: return rc; } static int dsi_link_clk_stop(struct dsi_link_clks *l_clks) static int dsi_link_lp_clk_start( struct mdss_dsi_link_lp_clk_info *link_lp_clks) { int rc = 0; struct mdss_dsi_clk_mngr *mngr; struct dsi_link_clks *l_clks; struct mdss_dsi_ctrl_pdata *ctrl; l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); /* * In an ideal world, cont_splash_enabled should not be required inside * the clock manager. But, in the current driver cont_splash_enabled * flag is set inside mdp driver and there is no interface event * associated with this flag setting. Also, set rate for clock need not * be called for every enable call. It should be done only once when * coming out of suspend. */ ctrl = mngr->priv_data; if (ctrl->panel_data.panel_info.cont_splash_enabled) goto prepare; (void)dsi_link_clk_disable(l_clks); rc = clk_set_rate(link_lp_clks->esc_clk, link_lp_clks->esc_clk_rate); if (rc) { pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); goto error; } prepare: rc = clk_prepare(link_lp_clks->esc_clk); if (rc) { pr_err("Failed to prepare dsi esc clk\n"); goto error; } rc = clk_enable(link_lp_clks->esc_clk); if (rc) { pr_err("Failed to enable dsi esc clk\n"); clk_unprepare(l_clks->lp_clks.esc_clk); goto error; } error: pr_debug("%s: LINK LP CLOCK IS ON\n", mngr->name); return rc; } static int dsi_link_hs_clk_stop( struct mdss_dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; struct dsi_link_clks *l_clks; struct mdss_dsi_clk_mngr *mngr; l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); (void)dsi_link_clk_unprepare(l_clks); pr_debug("%s: LINK CLOCK IS OFF\n", mngr->name); (void)dsi_link_hs_clk_disable(link_hs_clks); (void)dsi_link_hs_clk_unprepare(link_hs_clks); pr_debug("%s: LINK HS CLOCK IS OFF\n", mngr->name); return rc; } static int dsi_link_lp_clk_stop( struct mdss_dsi_link_lp_clk_info *link_lp_clks) { struct dsi_link_clks *l_clks; struct mdss_dsi_clk_mngr *mngr; l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks); clk_disable(l_clks->lp_clks.esc_clk); clk_unprepare(l_clks->lp_clks.esc_clk); pr_debug("%s: LINK LP CLOCK IS OFF\n", mngr->name); return 0; } static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, struct dsi_link_clks *l_clks, u32 l_state) { Loading Loading @@ -347,7 +403,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (c_clks && (c_state == MDSS_DSI_CLK_ON)) { if (c_clks->current_clk_state == MDSS_DSI_CLK_OFF) { rc = mngr->pre_clkon_cb(mngr->priv_data, MDSS_DSI_CORE_CLK, MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE, MDSS_DSI_CLK_ON); if (rc) { pr_err("failed to turn on MDP FS rc= %d\n", rc); Loading @@ -362,7 +418,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, MDSS_DSI_CORE_CLK, MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE, MDSS_DSI_CLK_ON); if (rc) pr_err("post clk on cb failed, rc = %d\n", rc); Loading @@ -375,21 +431,50 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (l_state == MDSS_DSI_CLK_ON) { if (mngr->pre_clkon_cb) { rc = mngr->pre_clkon_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, l_state); MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK, l_state); if (rc) pr_err("pre link clk on cb failed\n"); pr_err("pre link LP clk on cb failed\n"); } rc = dsi_link_clk_start(l_clks); rc = dsi_link_lp_clk_start(&l_clks->lp_clks); if (rc) { pr_err("failed to start link clk rc= %d\n", rc); pr_err("failed to start LP link clk clk\n"); goto error; } if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK, l_state); if (rc) pr_err("post LP clk on cb failed\n"); } if (mngr->pre_clkon_cb) { rc = mngr->pre_clkon_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK, l_state); if (rc) pr_err("post link clk on cb failed\n"); pr_err("pre HS clk on cb failed\n"); } rc = dsi_link_hs_clk_start(&l_clks->hs_clks, (MDSS_DSI_LINK_CLK_SET_RATE | MDSS_DSI_LINK_CLK_PREPARE)); if (rc) { pr_err("failed to prepare HS clk rc= %d\n", rc); goto error; } if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK, l_state); if (rc) pr_err("post HS clk on cb failed\n"); } rc = dsi_link_hs_clk_start(&l_clks->hs_clks, MDSS_DSI_LINK_CLK_ENABLE); if (rc) { pr_err("failed to enable HS clk rc= %d\n", rc); goto error; } } else { /* Loading Loading @@ -418,9 +503,16 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, goto error; } rc = dsi_link_clk_start(l_clks); rc = dsi_link_lp_clk_start(&l_clks->lp_clks); if (rc) { pr_err("LP Link clks did not start\n"); goto error; } rc = dsi_link_hs_clk_start(&l_clks->hs_clks, MDSS_DSI_LINK_CLK_START); if (rc) { pr_err("Link clks did not start\n"); pr_err("HS Link clks did not start\n"); goto error; } l_c_on = true; Loading @@ -429,24 +521,50 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, l_state); MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK, l_state); if (rc) pr_err("pre HS clk off cb failed\n"); } rc = dsi_link_hs_clk_stop(&l_clks->hs_clks); if (rc) { pr_err("failed to stop HS clk, rc = %d\n", rc); goto error; } if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK, l_state); if (rc) pr_err("post HS clk off cb failed\n"); } if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK, l_state); if (rc) pr_err("pre link clk off cb failed\n"); pr_err("pre LP clk off cb failed\n"); } rc = dsi_link_clk_stop(l_clks); rc = dsi_link_lp_clk_stop(&l_clks->lp_clks); if (rc) { pr_err("failed to stop link clk, rc = %d\n", pr_err("failed to stop LP link clk, rc = %d\n", rc); goto error; } if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, MDSS_DSI_LINK_CLK, l_state); MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK, l_state); if (rc) pr_err("post link clk off cb failed\n"); pr_err("post LP clk off cb failed\n"); } /* * This check is to save unnecessary clock state * change when going from EARLY_GATE to OFF. In the Loading Loading @@ -502,7 +620,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, MDSS_DSI_CORE_CLK, MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE, c_state); if (rc) pr_err("pre core clk off cb failed\n"); Loading @@ -517,7 +635,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (c_state == MDSS_DSI_CLK_OFF) { if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, MDSS_DSI_CORE_CLK, MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE, MDSS_DSI_CLK_OFF); if (rc) pr_err("post clkoff cb fail, rc = %d\n", Loading Loading @@ -610,27 +728,30 @@ static int dsi_set_clk_rate(struct mdss_dsi_clk_mngr *mngr, int clk, u32 rate, MDSS_XLOG(clk, rate, flags); switch (clk) { case MDSS_DSI_LINK_ESC_CLK: mngr->link_clks.esc_clk_rate = rate; mngr->link_clks.lp_clks.esc_clk_rate = rate; if (!flags) { rc = clk_set_rate(mngr->link_clks.clks.esc_clk, rate); rc = clk_set_rate(mngr->link_clks.lp_clks.esc_clk, rate); if (rc) pr_err("set rate failed for esc clk rc=%d\n", rc); } break; case MDSS_DSI_LINK_BYTE_CLK: mngr->link_clks.byte_clk_rate = rate; mngr->link_clks.hs_clks.byte_clk_rate = rate; if (!flags) { rc = clk_set_rate(mngr->link_clks.clks.byte_clk, rate); rc = clk_set_rate(mngr->link_clks.hs_clks.byte_clk, rate); if (rc) pr_err("set rate failed for byte clk rc=%d\n", rc); } break; case MDSS_DSI_LINK_PIX_CLK: mngr->link_clks.pix_clk_rate = rate; mngr->link_clks.hs_clks.pix_clk_rate = rate; if (!flags) { rc = clk_set_rate(mngr->link_clks.clks.pixel_clk, rate); rc = clk_set_rate(mngr->link_clks.hs_clks.pixel_clk, rate); if (rc) pr_err("failed to set rate for pix clk rc=%d\n", rc); Loading Loading @@ -888,8 +1009,10 @@ void *mdss_dsi_clk_init(struct mdss_dsi_clk_info *info) mutex_init(&mngr->clk_mutex); memcpy(&mngr->core_clks.clks, &info->core_clks, sizeof(struct mdss_dsi_core_clk_info)); memcpy(&mngr->link_clks.clks, &info->link_clks, sizeof(struct mdss_dsi_link_clk_info)); memcpy(&mngr->link_clks.hs_clks, &info->link_hs_clks, sizeof(struct mdss_dsi_link_hs_clk_info)); memcpy(&mngr->link_clks.lp_clks, &info->link_lp_clks, sizeof(struct mdss_dsi_link_lp_clk_info)); INIT_LIST_HEAD(&mngr->client_list); mngr->pre_clkon_cb = info->pre_clkon_cb; Loading Loading @@ -981,15 +1104,26 @@ int mdss_dsi_clk_force_toggle(void *client, u32 clk) if ((clk & MDSS_DSI_LINK_CLK) && (mngr->link_clks.current_clk_state == MDSS_DSI_CLK_ON)) { rc = dsi_link_clk_stop(&mngr->link_clks); rc = dsi_link_hs_clk_stop(&mngr->link_clks.hs_clks); if (rc) { pr_err("failed to stop link clks\n"); pr_err("failed to stop HS link clks\n"); goto error; } rc = dsi_link_clk_start(&mngr->link_clks); rc = dsi_link_lp_clk_stop(&mngr->link_clks.lp_clks); if (rc) { pr_err("failed to stop LP link clks\n"); goto error; } rc = dsi_link_lp_clk_start(&mngr->link_clks.lp_clks); if (rc) pr_err("failed to start LP link clks\n"); rc = dsi_link_hs_clk_start(&mngr->link_clks.hs_clks, MDSS_DSI_LINK_CLK_START); if (rc) pr_err("failed to start link clks\n"); pr_err("failed to start HS link clks\n"); } else if (clk & MDSS_DSI_LINK_CLK) { pr_err("cannot reset, link clock is off\n"); Loading