Loading drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c +1 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,7 @@ static void dsi_catalog_phy_3_0_init(struct dsi_phy_hw *phy) phy->ops.ulps_ops.is_lanes_in_ulps = dsi_phy_hw_v3_0_is_lanes_in_ulps; phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0; phy->ops.clamp_ctrl = dsi_phy_hw_v3_0_clamp_ctrl; phy->ops.phy_lane_reset = dsi_phy_hw_v3_0_lane_reset; phy->ops.toggle_resync_fifo = dsi_phy_hw_v3_0_toggle_resync_fifo; } Loading drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h +1 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,7 @@ u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy); bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes); int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg, u32 *timing_val, u32 size); void dsi_phy_hw_v3_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable); int dsi_phy_hw_v3_0_lane_reset(struct dsi_phy_hw *phy); void dsi_phy_hw_v3_0_toggle_resync_fifo(struct dsi_phy_hw *phy); Loading drivers/gpu/drm/msm/dsi-staging/dsi_clk.h +44 −15 Original line number Diff line number Diff line Loading @@ -43,6 +43,13 @@ enum dsi_link_clk_type { DSI_LINK_CLK_MAX, }; enum dsi_link_clk_op_type { DSI_LINK_CLK_SET_RATE = BIT(0), DSI_LINK_CLK_PREPARE = BIT(1), DSI_LINK_CLK_ENABLE = BIT(2), DSI_LINK_CLK_START = BIT(0) | BIT(1) | BIT(2), }; enum dsi_clk_type { DSI_CORE_CLK = BIT(0), DSI_LINK_CLK = BIT(1), Loading @@ -50,6 +57,12 @@ enum dsi_clk_type { DSI_CLKS_MAX = BIT(2), }; enum dsi_lclk_type { DSI_LINK_NONE = 0, DSI_LINK_LP_CLK = BIT(0), DSI_LINK_HS_CLK = BIT(1), }; struct dsi_clk_ctrl_info { enum dsi_clk_type clk_type; enum dsi_clk_state clk_state; Loading Loading @@ -82,23 +95,29 @@ struct dsi_core_clk_info { }; /** * struct dsi_link_clk_info - Link clock information for DSI hardware. * @byte_clk: Handle to DSI byte clock. * @pixel_clk: Handle to DSI pixel clock. * @esc_clk: Handle to DSI escape clock. * struct dsi_link_hs_clk_info - Set of high speed link clocks for DSI HW * @byte_clk: Handle to DSI byte_clk. * @pixel_clk: Handle to DSI pixel_clk. * @byte_intf_clk: Handle to DSI byte intf. clock. */ struct dsi_link_clk_info { struct dsi_link_hs_clk_info { struct clk *byte_clk; struct clk *pixel_clk; struct clk *esc_clk; struct clk *byte_intf_clk; }; /** * struct dsi_link_lp_clk_info - Set of low power link clocks for DSI HW. * @esc_clk: Handle to DSI escape clock. */ struct dsi_link_lp_clk_info { struct clk *esc_clk; }; /** * struct link_clk_freq - Clock frequency information for Link clocks * @byte_clk_rate: Frequency of DSI byte clock in KHz. * @pixel_clk_rate: Frequency of DSI pixel clock in KHz. * @byte_clk_rate: Frequency of DSI byte_clk in KHz. * @pixel_clk_rate: Frequency of DSI pixel_clk in KHz. * @esc_clk_rate: Frequency of DSI escape clock in KHz. */ struct link_clk_freq { Loading @@ -111,48 +130,56 @@ struct link_clk_freq { * typedef *pre_clockoff_cb() - Callback before clock is turned off * @priv: private data pointer. * @clk_type: clock which is being turned off. * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. * @new_state: next state for the clock. * * @return: error code. */ typedef int (*pre_clockoff_cb)(void *priv, enum dsi_clk_type clk_type, enum dsi_lclk_type l_type, enum dsi_clk_state new_state); /** * typedef *post_clockoff_cb() - Callback after clock is turned off * @priv: private data pointer. * @clk_type: clock which was turned off. * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. * @curr_state: current state for the clock. * * @return: error code. */ typedef int (*post_clockoff_cb)(void *priv, enum dsi_clk_type clk_type, enum dsi_lclk_type l_type, enum dsi_clk_state curr_state); /** * typedef *post_clockon_cb() - Callback after clock is turned on * @priv: private data pointer. * @clk_type: clock which was turned on. * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. * @curr_state: current state for the clock. * * @return: error code. */ typedef int (*post_clockon_cb)(void *priv, enum dsi_clk_type clk_type, enum dsi_lclk_type l_type, enum dsi_clk_state curr_state); /** * typedef *pre_clockon_cb() - Callback before clock is turned on * @priv: private data pointer. * @clk_type: clock which is being turned on. * @l_type: specifies if the clock is HS or LP type.Valid only for link clocks. * @new_state: next state for the clock. * * @return: error code. */ typedef int (*pre_clockon_cb)(void *priv, enum dsi_clk_type clk_type, enum dsi_lclk_type l_type, enum dsi_clk_state new_state); Loading @@ -160,7 +187,8 @@ typedef int (*pre_clockon_cb)(void *priv, * struct dsi_clk_info - clock information for DSI hardware. * @name: client name. * @c_clks[MAX_DSI_CTRL] array of core clock configurations * @l_clks[MAX_DSI_CTRL] array of link clock configurations * @l_lp_clks[MAX_DSI_CTRL] array of low power(esc) clock configurations * @l_hs_clks[MAX_DSI_CTRL] array of high speed clock configurations * @bus_handle[MAX_DSI_CTRL] array of bus handles * @ctrl_index[MAX_DSI_CTRL] array of DSI controller indexes mapped * to core and link clock configurations Loading @@ -175,7 +203,8 @@ typedef int (*pre_clockon_cb)(void *priv, struct dsi_clk_info { char name[MAX_STRING_LEN]; struct dsi_core_clk_info c_clks[MAX_DSI_CTRL]; struct dsi_link_clk_info l_clks[MAX_DSI_CTRL]; struct dsi_link_lp_clk_info l_lp_clks[MAX_DSI_CTRL]; struct dsi_link_hs_clk_info l_hs_clks[MAX_DSI_CTRL]; u32 bus_handle[MAX_DSI_CTRL]; u32 ctrl_index[MAX_DSI_CTRL]; pre_clockoff_cb pre_clkoff_cb; Loading @@ -189,8 +218,8 @@ struct dsi_clk_info { /** * struct dsi_clk_link_set - Pair of clock handles to describe link clocks * @byte_clk: Handle to DSi byte clock. * @pixel_clk: Handle to DSI pixel clock. * @byte_clk: Handle to DSi byte_clk. * @pixel_clk: Handle to DSI pixel_clk. */ struct dsi_clk_link_set { struct clk *byte_clk; Loading Loading @@ -263,9 +292,9 @@ int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, /** * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock * dsi_clk_set_pixel_clk_rate() - set frequency for pixel_clk * @client: DSI clock client pointer. * @pixel_clk: Pixel clock rate in Hz. * @pixel_clk: Pixel_clk rate in Hz. * @index: Index of the DSI controller. * return: error code in case of failure or 0 for success. */ Loading drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c +283 −134 Original line number Diff line number Diff line Loading @@ -24,7 +24,8 @@ struct dsi_core_clks { }; struct dsi_link_clks { struct dsi_link_clk_info clks; struct dsi_link_hs_clk_info hs_clks; struct dsi_link_lp_clk_info lp_clks; struct link_clk_freq freq; }; Loading Loading @@ -124,7 +125,7 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index) struct dsi_clk_mngr *mngr; mngr = c->mngr; rc = clk_set_rate(mngr->link_clks[index].clks.pixel_clk, pixel_clk); rc = clk_set_rate(mngr->link_clks[index].hs_clks.pixel_clk, pixel_clk); if (rc) pr_err("failed to set clk rate for pixel clk, rc=%d\n", rc); else Loading @@ -147,7 +148,7 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index) struct dsi_clk_mngr *mngr; mngr = c->mngr; rc = clk_set_rate(mngr->link_clks[index].clks.byte_clk, byte_clk); rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk); if (rc) pr_err("failed to set clk rate for byte clk, rc=%d\n", rc); else Loading Loading @@ -285,38 +286,39 @@ 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, int index) static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks, int index) { int rc = 0; struct dsi_clk_mngr *mngr; struct dsi_link_clks *l_clks; if (index >= MAX_DSI_CTRL) { pr_err("Invalid DSI ctrl index\n"); return -EINVAL; } l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[index]); if (mngr->is_cont_splash_enabled) return 0; /* * 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. */ rc = clk_set_rate(l_clks->clks.esc_clk, l_clks->freq.esc_clk_rate); if (rc) { pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); goto error; } if (mngr->is_cont_splash_enabled) return 0; rc = clk_set_rate(l_clks->clks.byte_clk, l_clks->freq.byte_clk_rate); rc = clk_set_rate(link_hs_clks->byte_clk, l_clks->freq.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->freq.pix_clk_rate); rc = clk_set_rate(link_hs_clks->pixel_clk, l_clks->freq.pix_clk_rate); if (rc) { pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc); goto error; Loading @@ -327,8 +329,8 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks, int index) * For DPHY: byte_intf_clk_rate = byte_clk_rate / 2 * todo: this needs to be revisited when support for CPHY is added */ if (l_clks->clks.byte_intf_clk) { rc = clk_set_rate(l_clks->clks.byte_intf_clk, if (link_hs_clks->byte_intf_clk) { rc = clk_set_rate(link_hs_clks->byte_intf_clk, (l_clks->freq.byte_clk_rate / 2)); if (rc) { pr_err("set_rate failed for byte_intf_clk rc = %d\n", Loading @@ -340,30 +342,24 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks, int index) return rc; } static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_prepare(struct dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; rc = clk_prepare(l_clks->clks.esc_clk); if (rc) { pr_err("Failed to prepare dsi esc clk, rc=%d\n", rc); goto esc_clk_err; } rc = clk_prepare(l_clks->clks.byte_clk); rc = clk_prepare(link_hs_clks->byte_clk); if (rc) { pr_err("Failed to prepare dsi byte clk, rc=%d\n", rc); goto byte_clk_err; } rc = clk_prepare(l_clks->clks.pixel_clk); rc = clk_prepare(link_hs_clks->pixel_clk); if (rc) { pr_err("Failed to prepare dsi pixel clk, rc=%d\n", rc); goto pixel_clk_err; } if (l_clks->clks.byte_intf_clk) { rc = clk_prepare(l_clks->clks.byte_intf_clk); if (link_hs_clks->byte_intf_clk) { rc = clk_prepare(link_hs_clks->byte_intf_clk); if (rc) { pr_err("Failed to prepare dsi byte intf clk, rc=%d\n", rc); Loading @@ -374,48 +370,39 @@ static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks) return rc; byte_intf_clk_err: clk_unprepare(l_clks->clks.pixel_clk); clk_unprepare(link_hs_clks->pixel_clk); 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 void dsi_link_clk_unprepare(struct dsi_link_clks *l_clks) static void dsi_link_hs_clk_unprepare(struct dsi_link_hs_clk_info *link_hs_clks) { if (l_clks->clks.byte_intf_clk) clk_unprepare(l_clks->clks.byte_intf_clk); clk_unprepare(l_clks->clks.pixel_clk); clk_unprepare(l_clks->clks.byte_clk); clk_unprepare(l_clks->clks.esc_clk); if (link_hs_clks->byte_intf_clk) clk_unprepare(link_hs_clks->byte_intf_clk); clk_unprepare(link_hs_clks->pixel_clk); clk_unprepare(link_hs_clks->byte_clk); } static int dsi_link_clk_enable(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_enable(struct dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; rc = clk_enable(l_clks->clks.esc_clk); if (rc) { pr_err("Failed to enable dsi esc clk, rc=%d\n", rc); goto esc_clk_err; } rc = clk_enable(l_clks->clks.byte_clk); rc = clk_enable(link_hs_clks->byte_clk); if (rc) { pr_err("Failed to enable dsi byte clk, rc=%d\n", rc); goto byte_clk_err; } rc = clk_enable(l_clks->clks.pixel_clk); rc = clk_enable(link_hs_clks->pixel_clk); if (rc) { pr_err("Failed to enable dsi pixel clk, rc=%d\n", rc); goto pixel_clk_err; } if (l_clks->clks.byte_intf_clk) { rc = clk_enable(l_clks->clks.byte_intf_clk); if (link_hs_clks->byte_intf_clk) { rc = clk_enable(link_hs_clks->byte_intf_clk); if (rc) { pr_err("Failed to enable dsi byte intf clk, rc=%d\n", rc); Loading @@ -426,28 +413,26 @@ static int dsi_link_clk_enable(struct dsi_link_clks *l_clks) return rc; byte_intf_clk_err: clk_disable(l_clks->clks.pixel_clk); clk_disable(link_hs_clks->pixel_clk); 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 void dsi_link_clk_disable(struct dsi_link_clks *l_clks) static void dsi_link_hs_clk_disable(struct dsi_link_hs_clk_info *link_hs_clks) { if (l_clks->clks.byte_intf_clk) clk_disable(l_clks->clks.byte_intf_clk); clk_disable(l_clks->clks.esc_clk); clk_disable(l_clks->clks.pixel_clk); clk_disable(l_clks->clks.byte_clk); if (link_hs_clks->byte_intf_clk) clk_disable(link_hs_clks->byte_intf_clk); clk_disable(link_hs_clks->pixel_clk); clk_disable(link_hs_clks->byte_clk); } /** * dsi_link_clk_start() - enable dsi link clocks */ static int dsi_link_clk_start(struct dsi_link_clks *clks, int index) static int dsi_link_hs_clk_start(struct dsi_link_hs_clk_info *link_hs_clks, enum dsi_link_clk_op_type op_type, int index) { int rc = 0; Loading @@ -456,28 +441,34 @@ static int dsi_link_clk_start(struct dsi_link_clks *clks, int index) return -EINVAL; } rc = dsi_link_clk_set_rate(clks, index); if (op_type & DSI_LINK_CLK_SET_RATE) { rc = dsi_link_hs_clk_set_rate(link_hs_clks, index); 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(clks); if (op_type & 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(clks); if (op_type & 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("Link clocks are enabled\n"); pr_debug("HS Link clocks are enabled\n"); return rc; error_unprepare: dsi_link_clk_unprepare(clks); dsi_link_hs_clk_unprepare(link_hs_clks); error: return rc; } Loading @@ -485,13 +476,69 @@ static int dsi_link_clk_start(struct dsi_link_clks *clks, int index) /** * dsi_link_clk_stop() - Stop DSI link clocks. */ int dsi_link_clk_stop(struct dsi_link_clks *clks) static int dsi_link_hs_clk_stop(struct dsi_link_hs_clk_info *link_hs_clks) { struct dsi_link_clks *l_clks; l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); dsi_link_hs_clk_disable(link_hs_clks); dsi_link_hs_clk_unprepare(link_hs_clks); pr_debug("HS Link clocks disabled\n"); return 0; } static int dsi_link_lp_clk_start(struct dsi_link_lp_clk_info *link_lp_clks) { int rc = 0; struct dsi_clk_mngr *mngr; struct dsi_link_clks *l_clks; l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[0]); if (!mngr) return -EINVAL; /* * 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. */ if (mngr->is_cont_splash_enabled) goto prepare; rc = clk_set_rate(link_lp_clks->esc_clk, l_clks->freq.esc_clk_rate); if (rc) { pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); goto error; } prepare: rc = clk_prepare_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); } error: pr_debug("LP Link clocks are enabled\n"); return rc; } static int dsi_link_lp_clk_stop( struct dsi_link_lp_clk_info *link_lp_clks) { dsi_link_clk_disable(clks); dsi_link_clk_unprepare(clks); struct dsi_link_clks *l_clks; pr_debug("Link clocks disabled\n"); l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); clk_disable_unprepare(l_clks->lp_clks.esc_clk); pr_debug("LP Link clocks are disabled\n"); return 0; } Loading Loading @@ -556,7 +603,7 @@ static int dsi_display_core_clk_enable(struct dsi_core_clks *clks, } static int dsi_display_link_clk_enable(struct dsi_link_clks *clks, u32 ctrl_count, u32 master_ndx) enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx) { int rc = 0; int i; Loading @@ -570,27 +617,56 @@ static int dsi_display_link_clk_enable(struct dsi_link_clks *clks, m_clks = &clks[master_ndx]; rc = dsi_link_clk_start(m_clks, master_ndx); if (l_type & DSI_LINK_LP_CLK) { rc = dsi_link_lp_clk_start(&m_clks->lp_clks); if (rc) { pr_err("failed to turn on master clocks, rc=%d\n", rc); pr_err("failed to turn on master lp link clocks, rc=%d\n", rc); goto error; } } if (l_type & DSI_LINK_HS_CLK) { rc = dsi_link_hs_clk_start(&m_clks->hs_clks, DSI_LINK_CLK_START, master_ndx); if (rc) { pr_err("failed to turn on master hs link clocks, rc=%d\n", rc); goto error; } } /* Turn on rest of the core clocks */ for (i = 0; i < ctrl_count; i++) { clk = &clks[i]; if (!clk || (clk == m_clks)) continue; rc = dsi_link_clk_start(clk, i); if (l_type & DSI_LINK_LP_CLK) { rc = dsi_link_lp_clk_start(&clk->lp_clks); if (rc) { pr_err("failed to turn on clocks, rc=%d\n", rc); pr_err("failed to turn on lp link clocks, rc=%d\n", rc); goto error_disable_master; } } if (l_type & DSI_LINK_HS_CLK) { rc = dsi_link_hs_clk_start(&clk->hs_clks, DSI_LINK_CLK_START, i); if (rc) { pr_err("failed to turn on hs link clocks, rc=%d\n", rc); goto error_disable_master; } } } return rc; error_disable_master: (void)dsi_link_clk_stop(m_clks); if (l_type == DSI_LINK_LP_CLK) (void)dsi_link_lp_clk_stop(&m_clks->lp_clks); else if (l_type == DSI_LINK_HS_CLK) (void)dsi_link_hs_clk_stop(&m_clks->hs_clks); error: return rc; } Loading Loading @@ -646,7 +722,7 @@ static int dsi_display_core_clk_disable(struct dsi_core_clks *clks, } static int dsi_display_link_clk_disable(struct dsi_link_clks *clks, u32 ctrl_count, u32 master_ndx) enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx) { int rc = 0; int i; Loading @@ -667,15 +743,100 @@ static int dsi_display_link_clk_disable(struct dsi_link_clks *clks, if (!clk || (clk == m_clks)) continue; rc = dsi_link_clk_stop(clk); if (l_type & DSI_LINK_LP_CLK) { rc = dsi_link_lp_clk_stop(&clk->lp_clks); if (rc) pr_err("failed to turn off clocks, rc=%d\n", rc); pr_err("failed to turn off lp link clocks, rc=%d\n", rc); } rc = dsi_link_clk_stop(m_clks); if (l_type & DSI_LINK_HS_CLK) { rc = dsi_link_hs_clk_stop(&clk->hs_clks); if (rc) pr_err("failed to turn off master clocks, rc=%d\n", rc); pr_err("failed to turn off hs link clocks, rc=%d\n", rc); } } if (l_type & DSI_LINK_LP_CLK) { rc = dsi_link_lp_clk_stop(&m_clks->lp_clks); if (rc) pr_err("failed to turn off master lp link clocks, rc=%d\n", rc); } if (l_type & DSI_LINK_HS_CLK) { rc = dsi_link_hs_clk_stop(&m_clks->hs_clks); if (rc) pr_err("failed to turn off master hs link clocks, rc=%d\n", rc); } return rc; } static int dsi_clk_update_link_clk_state(struct dsi_link_clks *l_clks, enum dsi_lclk_type l_type, u32 l_state, bool enable) { int rc = 0; struct dsi_clk_mngr *mngr; mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[0]); if (!mngr) return -EINVAL; if (enable) { if (mngr->pre_clkon_cb) { rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_LINK_CLK, l_type, l_state); if (rc) { pr_err("pre link clk on cb failed for type %d\n", l_type); goto error; } } rc = dsi_display_link_clk_enable(l_clks, l_type, mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("failed to start link clk type %d rc=%d\n", l_type, rc); goto error; } if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, DSI_LINK_CLK, l_type, l_state); if (rc) { pr_err("post link clk on cb failed for type %d\n", l_type); goto error; } } } else { if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, DSI_LINK_CLK, l_type, l_state); if (rc) pr_err("pre link clk off cb failed\n"); } rc = dsi_display_link_clk_disable(l_clks, l_type, mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("failed to stop link clk type %d, rc = %d\n", l_type, rc); goto error; } if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, DSI_LINK_CLK, l_type, l_state); if (rc) pr_err("post link clk off cb failed\n"); } } error: return rc; } Loading Loading @@ -710,6 +871,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->core_clk_state == DSI_CLK_OFF) { rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_CORE_CLK, DSI_LINK_NONE, DSI_CLK_ON); if (rc) { pr_err("failed to turn on MDP FS rc= %d\n", rc); Loading @@ -726,6 +888,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, DSI_CORE_CLK, DSI_LINK_NONE, DSI_CLK_ON); if (rc) pr_err("post clk on cb failed, rc = %d\n", rc); Loading @@ -735,25 +898,15 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (l_clks) { if (l_state == DSI_CLK_ON) { if (mngr->pre_clkon_cb) { rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_LINK_CLK, l_state); rc = dsi_clk_update_link_clk_state(l_clks, DSI_LINK_LP_CLK, l_state, true); if (rc) pr_err("pre link clk on cb failed\n"); } rc = dsi_display_link_clk_enable(l_clks, mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("failed to start link clk rc= %d\n", rc); goto error; } if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, DSI_LINK_CLK, l_state); rc = dsi_clk_update_link_clk_state(l_clks, DSI_LINK_HS_CLK, l_state, true); if (rc) pr_err("post link clk on cb failed\n"); } goto error; } else { /* * Two conditions that need to be checked for Link Loading Loading @@ -784,36 +937,26 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, } rc = dsi_display_link_clk_enable(l_clks, (DSI_LINK_LP_CLK & DSI_LINK_HS_CLK), mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("Link clks did not start\n"); pr_err("LP Link clks did not start\n"); goto error; } l_c_on = true; pr_debug("ECG: core and Link_on\n"); } if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, DSI_LINK_CLK, l_state); rc = dsi_clk_update_link_clk_state(l_clks, DSI_LINK_HS_CLK, l_state, false); if (rc) pr_err("pre link clk off cb failed\n"); } rc = dsi_display_link_clk_disable(l_clks, mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("failed to stop link clk, rc = %d\n", rc); goto error; } if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, DSI_LINK_CLK, l_state); rc = dsi_clk_update_link_clk_state(l_clks, DSI_LINK_LP_CLK, l_state, false); if (rc) pr_err("post link clk off cb failed\n"); } goto error; /* * This check is to save unnecessary clock state * change when going from EARLY_GATE to OFF. In the Loading Loading @@ -872,6 +1015,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, DSI_CORE_CLK, DSI_LINK_NONE, c_state); if (rc) pr_err("pre core clk off cb failed\n"); Loading @@ -888,6 +1032,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, DSI_CORE_CLK, DSI_LINK_NONE, DSI_CLK_OFF); if (rc) pr_err("post clkoff cb fail, rc = %d\n", Loading Loading @@ -1095,6 +1240,7 @@ static int dsi_display_link_clk_force_update(void *client) } rc = dsi_display_link_clk_disable(l_clks, (DSI_LINK_LP_CLK | DSI_LINK_HS_CLK), mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("%s, failed to stop link clk, rc = %d\n", Loading @@ -1103,6 +1249,7 @@ static int dsi_display_link_clk_force_update(void *client) } rc = dsi_display_link_clk_enable(l_clks, (DSI_LINK_LP_CLK | DSI_LINK_HS_CLK), mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("%s, failed to start link clk rc= %d\n", Loading Loading @@ -1267,8 +1414,10 @@ void *dsi_display_clk_mngr_register(struct dsi_clk_info *info) for (i = 0; i < mngr->dsi_ctrl_count; i++) { memcpy(&mngr->core_clks[i].clks, &info->c_clks[i], sizeof(struct dsi_core_clk_info)); memcpy(&mngr->link_clks[i].clks, &info->l_clks[i], sizeof(struct dsi_link_clk_info)); memcpy(&mngr->link_clks[i].hs_clks, &info->l_hs_clks[i], sizeof(struct dsi_link_hs_clk_info)); memcpy(&mngr->link_clks[i].lp_clks, &info->l_lp_clks[i], sizeof(struct dsi_link_lp_clk_info)); mngr->core_clks[i].bus_handle = info->bus_handle[i]; mngr->ctrl_index[i] = info->ctrl_index[i]; } Loading drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +26 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c +1 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,7 @@ static void dsi_catalog_phy_3_0_init(struct dsi_phy_hw *phy) phy->ops.ulps_ops.is_lanes_in_ulps = dsi_phy_hw_v3_0_is_lanes_in_ulps; phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0; phy->ops.clamp_ctrl = dsi_phy_hw_v3_0_clamp_ctrl; phy->ops.phy_lane_reset = dsi_phy_hw_v3_0_lane_reset; phy->ops.toggle_resync_fifo = dsi_phy_hw_v3_0_toggle_resync_fifo; } Loading
drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h +1 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,7 @@ u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy); bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes); int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg, u32 *timing_val, u32 size); void dsi_phy_hw_v3_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable); int dsi_phy_hw_v3_0_lane_reset(struct dsi_phy_hw *phy); void dsi_phy_hw_v3_0_toggle_resync_fifo(struct dsi_phy_hw *phy); Loading
drivers/gpu/drm/msm/dsi-staging/dsi_clk.h +44 −15 Original line number Diff line number Diff line Loading @@ -43,6 +43,13 @@ enum dsi_link_clk_type { DSI_LINK_CLK_MAX, }; enum dsi_link_clk_op_type { DSI_LINK_CLK_SET_RATE = BIT(0), DSI_LINK_CLK_PREPARE = BIT(1), DSI_LINK_CLK_ENABLE = BIT(2), DSI_LINK_CLK_START = BIT(0) | BIT(1) | BIT(2), }; enum dsi_clk_type { DSI_CORE_CLK = BIT(0), DSI_LINK_CLK = BIT(1), Loading @@ -50,6 +57,12 @@ enum dsi_clk_type { DSI_CLKS_MAX = BIT(2), }; enum dsi_lclk_type { DSI_LINK_NONE = 0, DSI_LINK_LP_CLK = BIT(0), DSI_LINK_HS_CLK = BIT(1), }; struct dsi_clk_ctrl_info { enum dsi_clk_type clk_type; enum dsi_clk_state clk_state; Loading Loading @@ -82,23 +95,29 @@ struct dsi_core_clk_info { }; /** * struct dsi_link_clk_info - Link clock information for DSI hardware. * @byte_clk: Handle to DSI byte clock. * @pixel_clk: Handle to DSI pixel clock. * @esc_clk: Handle to DSI escape clock. * struct dsi_link_hs_clk_info - Set of high speed link clocks for DSI HW * @byte_clk: Handle to DSI byte_clk. * @pixel_clk: Handle to DSI pixel_clk. * @byte_intf_clk: Handle to DSI byte intf. clock. */ struct dsi_link_clk_info { struct dsi_link_hs_clk_info { struct clk *byte_clk; struct clk *pixel_clk; struct clk *esc_clk; struct clk *byte_intf_clk; }; /** * struct dsi_link_lp_clk_info - Set of low power link clocks for DSI HW. * @esc_clk: Handle to DSI escape clock. */ struct dsi_link_lp_clk_info { struct clk *esc_clk; }; /** * struct link_clk_freq - Clock frequency information for Link clocks * @byte_clk_rate: Frequency of DSI byte clock in KHz. * @pixel_clk_rate: Frequency of DSI pixel clock in KHz. * @byte_clk_rate: Frequency of DSI byte_clk in KHz. * @pixel_clk_rate: Frequency of DSI pixel_clk in KHz. * @esc_clk_rate: Frequency of DSI escape clock in KHz. */ struct link_clk_freq { Loading @@ -111,48 +130,56 @@ struct link_clk_freq { * typedef *pre_clockoff_cb() - Callback before clock is turned off * @priv: private data pointer. * @clk_type: clock which is being turned off. * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. * @new_state: next state for the clock. * * @return: error code. */ typedef int (*pre_clockoff_cb)(void *priv, enum dsi_clk_type clk_type, enum dsi_lclk_type l_type, enum dsi_clk_state new_state); /** * typedef *post_clockoff_cb() - Callback after clock is turned off * @priv: private data pointer. * @clk_type: clock which was turned off. * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. * @curr_state: current state for the clock. * * @return: error code. */ typedef int (*post_clockoff_cb)(void *priv, enum dsi_clk_type clk_type, enum dsi_lclk_type l_type, enum dsi_clk_state curr_state); /** * typedef *post_clockon_cb() - Callback after clock is turned on * @priv: private data pointer. * @clk_type: clock which was turned on. * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. * @curr_state: current state for the clock. * * @return: error code. */ typedef int (*post_clockon_cb)(void *priv, enum dsi_clk_type clk_type, enum dsi_lclk_type l_type, enum dsi_clk_state curr_state); /** * typedef *pre_clockon_cb() - Callback before clock is turned on * @priv: private data pointer. * @clk_type: clock which is being turned on. * @l_type: specifies if the clock is HS or LP type.Valid only for link clocks. * @new_state: next state for the clock. * * @return: error code. */ typedef int (*pre_clockon_cb)(void *priv, enum dsi_clk_type clk_type, enum dsi_lclk_type l_type, enum dsi_clk_state new_state); Loading @@ -160,7 +187,8 @@ typedef int (*pre_clockon_cb)(void *priv, * struct dsi_clk_info - clock information for DSI hardware. * @name: client name. * @c_clks[MAX_DSI_CTRL] array of core clock configurations * @l_clks[MAX_DSI_CTRL] array of link clock configurations * @l_lp_clks[MAX_DSI_CTRL] array of low power(esc) clock configurations * @l_hs_clks[MAX_DSI_CTRL] array of high speed clock configurations * @bus_handle[MAX_DSI_CTRL] array of bus handles * @ctrl_index[MAX_DSI_CTRL] array of DSI controller indexes mapped * to core and link clock configurations Loading @@ -175,7 +203,8 @@ typedef int (*pre_clockon_cb)(void *priv, struct dsi_clk_info { char name[MAX_STRING_LEN]; struct dsi_core_clk_info c_clks[MAX_DSI_CTRL]; struct dsi_link_clk_info l_clks[MAX_DSI_CTRL]; struct dsi_link_lp_clk_info l_lp_clks[MAX_DSI_CTRL]; struct dsi_link_hs_clk_info l_hs_clks[MAX_DSI_CTRL]; u32 bus_handle[MAX_DSI_CTRL]; u32 ctrl_index[MAX_DSI_CTRL]; pre_clockoff_cb pre_clkoff_cb; Loading @@ -189,8 +218,8 @@ struct dsi_clk_info { /** * struct dsi_clk_link_set - Pair of clock handles to describe link clocks * @byte_clk: Handle to DSi byte clock. * @pixel_clk: Handle to DSI pixel clock. * @byte_clk: Handle to DSi byte_clk. * @pixel_clk: Handle to DSI pixel_clk. */ struct dsi_clk_link_set { struct clk *byte_clk; Loading Loading @@ -263,9 +292,9 @@ int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, /** * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock * dsi_clk_set_pixel_clk_rate() - set frequency for pixel_clk * @client: DSI clock client pointer. * @pixel_clk: Pixel clock rate in Hz. * @pixel_clk: Pixel_clk rate in Hz. * @index: Index of the DSI controller. * return: error code in case of failure or 0 for success. */ Loading
drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c +283 −134 Original line number Diff line number Diff line Loading @@ -24,7 +24,8 @@ struct dsi_core_clks { }; struct dsi_link_clks { struct dsi_link_clk_info clks; struct dsi_link_hs_clk_info hs_clks; struct dsi_link_lp_clk_info lp_clks; struct link_clk_freq freq; }; Loading Loading @@ -124,7 +125,7 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index) struct dsi_clk_mngr *mngr; mngr = c->mngr; rc = clk_set_rate(mngr->link_clks[index].clks.pixel_clk, pixel_clk); rc = clk_set_rate(mngr->link_clks[index].hs_clks.pixel_clk, pixel_clk); if (rc) pr_err("failed to set clk rate for pixel clk, rc=%d\n", rc); else Loading @@ -147,7 +148,7 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index) struct dsi_clk_mngr *mngr; mngr = c->mngr; rc = clk_set_rate(mngr->link_clks[index].clks.byte_clk, byte_clk); rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk); if (rc) pr_err("failed to set clk rate for byte clk, rc=%d\n", rc); else Loading Loading @@ -285,38 +286,39 @@ 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, int index) static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks, int index) { int rc = 0; struct dsi_clk_mngr *mngr; struct dsi_link_clks *l_clks; if (index >= MAX_DSI_CTRL) { pr_err("Invalid DSI ctrl index\n"); return -EINVAL; } l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[index]); if (mngr->is_cont_splash_enabled) return 0; /* * 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. */ rc = clk_set_rate(l_clks->clks.esc_clk, l_clks->freq.esc_clk_rate); if (rc) { pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); goto error; } if (mngr->is_cont_splash_enabled) return 0; rc = clk_set_rate(l_clks->clks.byte_clk, l_clks->freq.byte_clk_rate); rc = clk_set_rate(link_hs_clks->byte_clk, l_clks->freq.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->freq.pix_clk_rate); rc = clk_set_rate(link_hs_clks->pixel_clk, l_clks->freq.pix_clk_rate); if (rc) { pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc); goto error; Loading @@ -327,8 +329,8 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks, int index) * For DPHY: byte_intf_clk_rate = byte_clk_rate / 2 * todo: this needs to be revisited when support for CPHY is added */ if (l_clks->clks.byte_intf_clk) { rc = clk_set_rate(l_clks->clks.byte_intf_clk, if (link_hs_clks->byte_intf_clk) { rc = clk_set_rate(link_hs_clks->byte_intf_clk, (l_clks->freq.byte_clk_rate / 2)); if (rc) { pr_err("set_rate failed for byte_intf_clk rc = %d\n", Loading @@ -340,30 +342,24 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks, int index) return rc; } static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_prepare(struct dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; rc = clk_prepare(l_clks->clks.esc_clk); if (rc) { pr_err("Failed to prepare dsi esc clk, rc=%d\n", rc); goto esc_clk_err; } rc = clk_prepare(l_clks->clks.byte_clk); rc = clk_prepare(link_hs_clks->byte_clk); if (rc) { pr_err("Failed to prepare dsi byte clk, rc=%d\n", rc); goto byte_clk_err; } rc = clk_prepare(l_clks->clks.pixel_clk); rc = clk_prepare(link_hs_clks->pixel_clk); if (rc) { pr_err("Failed to prepare dsi pixel clk, rc=%d\n", rc); goto pixel_clk_err; } if (l_clks->clks.byte_intf_clk) { rc = clk_prepare(l_clks->clks.byte_intf_clk); if (link_hs_clks->byte_intf_clk) { rc = clk_prepare(link_hs_clks->byte_intf_clk); if (rc) { pr_err("Failed to prepare dsi byte intf clk, rc=%d\n", rc); Loading @@ -374,48 +370,39 @@ static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks) return rc; byte_intf_clk_err: clk_unprepare(l_clks->clks.pixel_clk); clk_unprepare(link_hs_clks->pixel_clk); 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 void dsi_link_clk_unprepare(struct dsi_link_clks *l_clks) static void dsi_link_hs_clk_unprepare(struct dsi_link_hs_clk_info *link_hs_clks) { if (l_clks->clks.byte_intf_clk) clk_unprepare(l_clks->clks.byte_intf_clk); clk_unprepare(l_clks->clks.pixel_clk); clk_unprepare(l_clks->clks.byte_clk); clk_unprepare(l_clks->clks.esc_clk); if (link_hs_clks->byte_intf_clk) clk_unprepare(link_hs_clks->byte_intf_clk); clk_unprepare(link_hs_clks->pixel_clk); clk_unprepare(link_hs_clks->byte_clk); } static int dsi_link_clk_enable(struct dsi_link_clks *l_clks) static int dsi_link_hs_clk_enable(struct dsi_link_hs_clk_info *link_hs_clks) { int rc = 0; rc = clk_enable(l_clks->clks.esc_clk); if (rc) { pr_err("Failed to enable dsi esc clk, rc=%d\n", rc); goto esc_clk_err; } rc = clk_enable(l_clks->clks.byte_clk); rc = clk_enable(link_hs_clks->byte_clk); if (rc) { pr_err("Failed to enable dsi byte clk, rc=%d\n", rc); goto byte_clk_err; } rc = clk_enable(l_clks->clks.pixel_clk); rc = clk_enable(link_hs_clks->pixel_clk); if (rc) { pr_err("Failed to enable dsi pixel clk, rc=%d\n", rc); goto pixel_clk_err; } if (l_clks->clks.byte_intf_clk) { rc = clk_enable(l_clks->clks.byte_intf_clk); if (link_hs_clks->byte_intf_clk) { rc = clk_enable(link_hs_clks->byte_intf_clk); if (rc) { pr_err("Failed to enable dsi byte intf clk, rc=%d\n", rc); Loading @@ -426,28 +413,26 @@ static int dsi_link_clk_enable(struct dsi_link_clks *l_clks) return rc; byte_intf_clk_err: clk_disable(l_clks->clks.pixel_clk); clk_disable(link_hs_clks->pixel_clk); 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 void dsi_link_clk_disable(struct dsi_link_clks *l_clks) static void dsi_link_hs_clk_disable(struct dsi_link_hs_clk_info *link_hs_clks) { if (l_clks->clks.byte_intf_clk) clk_disable(l_clks->clks.byte_intf_clk); clk_disable(l_clks->clks.esc_clk); clk_disable(l_clks->clks.pixel_clk); clk_disable(l_clks->clks.byte_clk); if (link_hs_clks->byte_intf_clk) clk_disable(link_hs_clks->byte_intf_clk); clk_disable(link_hs_clks->pixel_clk); clk_disable(link_hs_clks->byte_clk); } /** * dsi_link_clk_start() - enable dsi link clocks */ static int dsi_link_clk_start(struct dsi_link_clks *clks, int index) static int dsi_link_hs_clk_start(struct dsi_link_hs_clk_info *link_hs_clks, enum dsi_link_clk_op_type op_type, int index) { int rc = 0; Loading @@ -456,28 +441,34 @@ static int dsi_link_clk_start(struct dsi_link_clks *clks, int index) return -EINVAL; } rc = dsi_link_clk_set_rate(clks, index); if (op_type & DSI_LINK_CLK_SET_RATE) { rc = dsi_link_hs_clk_set_rate(link_hs_clks, index); 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(clks); if (op_type & 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(clks); if (op_type & 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("Link clocks are enabled\n"); pr_debug("HS Link clocks are enabled\n"); return rc; error_unprepare: dsi_link_clk_unprepare(clks); dsi_link_hs_clk_unprepare(link_hs_clks); error: return rc; } Loading @@ -485,13 +476,69 @@ static int dsi_link_clk_start(struct dsi_link_clks *clks, int index) /** * dsi_link_clk_stop() - Stop DSI link clocks. */ int dsi_link_clk_stop(struct dsi_link_clks *clks) static int dsi_link_hs_clk_stop(struct dsi_link_hs_clk_info *link_hs_clks) { struct dsi_link_clks *l_clks; l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); dsi_link_hs_clk_disable(link_hs_clks); dsi_link_hs_clk_unprepare(link_hs_clks); pr_debug("HS Link clocks disabled\n"); return 0; } static int dsi_link_lp_clk_start(struct dsi_link_lp_clk_info *link_lp_clks) { int rc = 0; struct dsi_clk_mngr *mngr; struct dsi_link_clks *l_clks; l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[0]); if (!mngr) return -EINVAL; /* * 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. */ if (mngr->is_cont_splash_enabled) goto prepare; rc = clk_set_rate(link_lp_clks->esc_clk, l_clks->freq.esc_clk_rate); if (rc) { pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); goto error; } prepare: rc = clk_prepare_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); } error: pr_debug("LP Link clocks are enabled\n"); return rc; } static int dsi_link_lp_clk_stop( struct dsi_link_lp_clk_info *link_lp_clks) { dsi_link_clk_disable(clks); dsi_link_clk_unprepare(clks); struct dsi_link_clks *l_clks; pr_debug("Link clocks disabled\n"); l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); clk_disable_unprepare(l_clks->lp_clks.esc_clk); pr_debug("LP Link clocks are disabled\n"); return 0; } Loading Loading @@ -556,7 +603,7 @@ static int dsi_display_core_clk_enable(struct dsi_core_clks *clks, } static int dsi_display_link_clk_enable(struct dsi_link_clks *clks, u32 ctrl_count, u32 master_ndx) enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx) { int rc = 0; int i; Loading @@ -570,27 +617,56 @@ static int dsi_display_link_clk_enable(struct dsi_link_clks *clks, m_clks = &clks[master_ndx]; rc = dsi_link_clk_start(m_clks, master_ndx); if (l_type & DSI_LINK_LP_CLK) { rc = dsi_link_lp_clk_start(&m_clks->lp_clks); if (rc) { pr_err("failed to turn on master clocks, rc=%d\n", rc); pr_err("failed to turn on master lp link clocks, rc=%d\n", rc); goto error; } } if (l_type & DSI_LINK_HS_CLK) { rc = dsi_link_hs_clk_start(&m_clks->hs_clks, DSI_LINK_CLK_START, master_ndx); if (rc) { pr_err("failed to turn on master hs link clocks, rc=%d\n", rc); goto error; } } /* Turn on rest of the core clocks */ for (i = 0; i < ctrl_count; i++) { clk = &clks[i]; if (!clk || (clk == m_clks)) continue; rc = dsi_link_clk_start(clk, i); if (l_type & DSI_LINK_LP_CLK) { rc = dsi_link_lp_clk_start(&clk->lp_clks); if (rc) { pr_err("failed to turn on clocks, rc=%d\n", rc); pr_err("failed to turn on lp link clocks, rc=%d\n", rc); goto error_disable_master; } } if (l_type & DSI_LINK_HS_CLK) { rc = dsi_link_hs_clk_start(&clk->hs_clks, DSI_LINK_CLK_START, i); if (rc) { pr_err("failed to turn on hs link clocks, rc=%d\n", rc); goto error_disable_master; } } } return rc; error_disable_master: (void)dsi_link_clk_stop(m_clks); if (l_type == DSI_LINK_LP_CLK) (void)dsi_link_lp_clk_stop(&m_clks->lp_clks); else if (l_type == DSI_LINK_HS_CLK) (void)dsi_link_hs_clk_stop(&m_clks->hs_clks); error: return rc; } Loading Loading @@ -646,7 +722,7 @@ static int dsi_display_core_clk_disable(struct dsi_core_clks *clks, } static int dsi_display_link_clk_disable(struct dsi_link_clks *clks, u32 ctrl_count, u32 master_ndx) enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx) { int rc = 0; int i; Loading @@ -667,15 +743,100 @@ static int dsi_display_link_clk_disable(struct dsi_link_clks *clks, if (!clk || (clk == m_clks)) continue; rc = dsi_link_clk_stop(clk); if (l_type & DSI_LINK_LP_CLK) { rc = dsi_link_lp_clk_stop(&clk->lp_clks); if (rc) pr_err("failed to turn off clocks, rc=%d\n", rc); pr_err("failed to turn off lp link clocks, rc=%d\n", rc); } rc = dsi_link_clk_stop(m_clks); if (l_type & DSI_LINK_HS_CLK) { rc = dsi_link_hs_clk_stop(&clk->hs_clks); if (rc) pr_err("failed to turn off master clocks, rc=%d\n", rc); pr_err("failed to turn off hs link clocks, rc=%d\n", rc); } } if (l_type & DSI_LINK_LP_CLK) { rc = dsi_link_lp_clk_stop(&m_clks->lp_clks); if (rc) pr_err("failed to turn off master lp link clocks, rc=%d\n", rc); } if (l_type & DSI_LINK_HS_CLK) { rc = dsi_link_hs_clk_stop(&m_clks->hs_clks); if (rc) pr_err("failed to turn off master hs link clocks, rc=%d\n", rc); } return rc; } static int dsi_clk_update_link_clk_state(struct dsi_link_clks *l_clks, enum dsi_lclk_type l_type, u32 l_state, bool enable) { int rc = 0; struct dsi_clk_mngr *mngr; mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[0]); if (!mngr) return -EINVAL; if (enable) { if (mngr->pre_clkon_cb) { rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_LINK_CLK, l_type, l_state); if (rc) { pr_err("pre link clk on cb failed for type %d\n", l_type); goto error; } } rc = dsi_display_link_clk_enable(l_clks, l_type, mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("failed to start link clk type %d rc=%d\n", l_type, rc); goto error; } if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, DSI_LINK_CLK, l_type, l_state); if (rc) { pr_err("post link clk on cb failed for type %d\n", l_type); goto error; } } } else { if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, DSI_LINK_CLK, l_type, l_state); if (rc) pr_err("pre link clk off cb failed\n"); } rc = dsi_display_link_clk_disable(l_clks, l_type, mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("failed to stop link clk type %d, rc = %d\n", l_type, rc); goto error; } if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, DSI_LINK_CLK, l_type, l_state); if (rc) pr_err("post link clk off cb failed\n"); } } error: return rc; } Loading Loading @@ -710,6 +871,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->core_clk_state == DSI_CLK_OFF) { rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_CORE_CLK, DSI_LINK_NONE, DSI_CLK_ON); if (rc) { pr_err("failed to turn on MDP FS rc= %d\n", rc); Loading @@ -726,6 +888,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, DSI_CORE_CLK, DSI_LINK_NONE, DSI_CLK_ON); if (rc) pr_err("post clk on cb failed, rc = %d\n", rc); Loading @@ -735,25 +898,15 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (l_clks) { if (l_state == DSI_CLK_ON) { if (mngr->pre_clkon_cb) { rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_LINK_CLK, l_state); rc = dsi_clk_update_link_clk_state(l_clks, DSI_LINK_LP_CLK, l_state, true); if (rc) pr_err("pre link clk on cb failed\n"); } rc = dsi_display_link_clk_enable(l_clks, mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("failed to start link clk rc= %d\n", rc); goto error; } if (mngr->post_clkon_cb) { rc = mngr->post_clkon_cb(mngr->priv_data, DSI_LINK_CLK, l_state); rc = dsi_clk_update_link_clk_state(l_clks, DSI_LINK_HS_CLK, l_state, true); if (rc) pr_err("post link clk on cb failed\n"); } goto error; } else { /* * Two conditions that need to be checked for Link Loading Loading @@ -784,36 +937,26 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, } rc = dsi_display_link_clk_enable(l_clks, (DSI_LINK_LP_CLK & DSI_LINK_HS_CLK), mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("Link clks did not start\n"); pr_err("LP Link clks did not start\n"); goto error; } l_c_on = true; pr_debug("ECG: core and Link_on\n"); } if (mngr->pre_clkoff_cb) { rc = mngr->pre_clkoff_cb(mngr->priv_data, DSI_LINK_CLK, l_state); rc = dsi_clk_update_link_clk_state(l_clks, DSI_LINK_HS_CLK, l_state, false); if (rc) pr_err("pre link clk off cb failed\n"); } rc = dsi_display_link_clk_disable(l_clks, mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("failed to stop link clk, rc = %d\n", rc); goto error; } if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, DSI_LINK_CLK, l_state); rc = dsi_clk_update_link_clk_state(l_clks, DSI_LINK_LP_CLK, l_state, false); if (rc) pr_err("post link clk off cb failed\n"); } goto error; /* * This check is to save unnecessary clock state * change when going from EARLY_GATE to OFF. In the Loading Loading @@ -872,6 +1015,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, DSI_CORE_CLK, DSI_LINK_NONE, c_state); if (rc) pr_err("pre core clk off cb failed\n"); Loading @@ -888,6 +1032,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state, if (mngr->post_clkoff_cb) { rc = mngr->post_clkoff_cb(mngr->priv_data, DSI_CORE_CLK, DSI_LINK_NONE, DSI_CLK_OFF); if (rc) pr_err("post clkoff cb fail, rc = %d\n", Loading Loading @@ -1095,6 +1240,7 @@ static int dsi_display_link_clk_force_update(void *client) } rc = dsi_display_link_clk_disable(l_clks, (DSI_LINK_LP_CLK | DSI_LINK_HS_CLK), mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("%s, failed to stop link clk, rc = %d\n", Loading @@ -1103,6 +1249,7 @@ static int dsi_display_link_clk_force_update(void *client) } rc = dsi_display_link_clk_enable(l_clks, (DSI_LINK_LP_CLK | DSI_LINK_HS_CLK), mngr->dsi_ctrl_count, mngr->master_ndx); if (rc) { pr_err("%s, failed to start link clk rc= %d\n", Loading Loading @@ -1267,8 +1414,10 @@ void *dsi_display_clk_mngr_register(struct dsi_clk_info *info) for (i = 0; i < mngr->dsi_ctrl_count; i++) { memcpy(&mngr->core_clks[i].clks, &info->c_clks[i], sizeof(struct dsi_core_clk_info)); memcpy(&mngr->link_clks[i].clks, &info->l_clks[i], sizeof(struct dsi_link_clk_info)); memcpy(&mngr->link_clks[i].hs_clks, &info->l_hs_clks[i], sizeof(struct dsi_link_hs_clk_info)); memcpy(&mngr->link_clks[i].lp_clks, &info->l_lp_clks[i], sizeof(struct dsi_link_lp_clk_info)); mngr->core_clks[i].bus_handle = info->bus_handle[i]; mngr->ctrl_index[i] = info->ctrl_index[i]; } Loading
drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +26 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes