Loading drivers/gpu/drm/msm/sde_power_handle.c +76 −6 Original line number Original line Diff line number Diff line Loading @@ -847,6 +847,68 @@ void sde_power_resource_deinit(struct platform_device *pdev, sde_rsc_client_destroy(phandle->rsc_client); sde_rsc_client_destroy(phandle->rsc_client); } } int sde_power_scale_reg_bus(struct sde_power_handle *phandle, struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock) { struct sde_power_client *client; int rc = 0; u32 max_usecase_ndx = VOTE_INDEX_DISABLE; if (!skip_lock) { mutex_lock(&phandle->phandle_lock); if (WARN_ON(pclient->refcount == 0)) { /* * This is not expected, clients calling without skip * lock are outside the power resource enable, which * means that they should have enabled the power * resource before trying to scale. */ rc = -EINVAL; goto exit; } } pr_debug("%pS: current idx:%d requested:%d client:%d\n", __builtin_return_address(0), pclient->usecase_ndx, usecase_ndx, pclient->id); pclient->usecase_ndx = usecase_ndx; list_for_each_entry(client, &phandle->power_client_clist, list) { if (client->usecase_ndx < VOTE_INDEX_MAX && client->usecase_ndx > max_usecase_ndx) max_usecase_ndx = client->usecase_ndx; } rc = sde_power_reg_bus_update(phandle->reg_bus_hdl, max_usecase_ndx); if (rc) pr_err("failed to set reg bus vote rc=%d\n", rc); exit: if (!skip_lock) mutex_unlock(&phandle->phandle_lock); return rc; } static inline bool _resource_changed(u32 current_usecase_ndx, u32 max_usecase_ndx) { WARN_ON((current_usecase_ndx >= VOTE_INDEX_MAX) || (max_usecase_ndx >= VOTE_INDEX_MAX)); if (((current_usecase_ndx >= VOTE_INDEX_LOW) && /* enabled */ (max_usecase_ndx == VOTE_INDEX_DISABLE)) || /* max disabled */ ((current_usecase_ndx == VOTE_INDEX_DISABLE) && /* disabled */ (max_usecase_ndx >= VOTE_INDEX_LOW))) /* max enabled */ return true; return false; } int sde_power_resource_enable(struct sde_power_handle *phandle, int sde_power_resource_enable(struct sde_power_handle *phandle, struct sde_power_client *pclient, bool enable) struct sde_power_client *pclient, bool enable) { { Loading Loading @@ -880,7 +942,15 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, max_usecase_ndx = client->usecase_ndx; max_usecase_ndx = client->usecase_ndx; } } if (phandle->current_usecase_ndx != max_usecase_ndx) { /* * Check if we need to enable/disable the power resource, we won't * only-scale up/down the AHB vote in this API; if a client wants to * bump up the AHB clock above the LOW (default) level, it needs to * call 'sde_power_scale_reg_bus' with the desired vote after the power * resource was enabled. */ if (_resource_changed(phandle->current_usecase_ndx, max_usecase_ndx)) { changed = true; changed = true; prev_usecase_ndx = phandle->current_usecase_ndx; prev_usecase_ndx = phandle->current_usecase_ndx; phandle->current_usecase_ndx = max_usecase_ndx; phandle->current_usecase_ndx = max_usecase_ndx; Loading Loading @@ -916,8 +986,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, goto vreg_err; goto vreg_err; } } rc = sde_power_reg_bus_update(phandle->reg_bus_hdl, rc = sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx); max_usecase_ndx, true); if (rc) { if (rc) { pr_err("failed to set reg bus vote rc=%d\n", rc); pr_err("failed to set reg bus vote rc=%d\n", rc); goto reg_bus_hdl_err; goto reg_bus_hdl_err; Loading Loading @@ -948,8 +1018,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); sde_power_reg_bus_update(phandle->reg_bus_hdl, sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx); max_usecase_ndx, true); msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable); msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable); Loading @@ -970,7 +1040,7 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, clk_err: clk_err: sde_power_rsc_update(phandle, false); sde_power_rsc_update(phandle, false); rsc_err: rsc_err: sde_power_reg_bus_update(phandle->reg_bus_hdl, prev_usecase_ndx); sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx, true); reg_bus_hdl_err: reg_bus_hdl_err: msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0); msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0); vreg_err: vreg_err: Loading drivers/gpu/drm/msm/sde_power_handle.h +17 −0 Original line number Original line Diff line number Diff line Loading @@ -43,11 +43,15 @@ * mdss_bus_vote_type: register bus vote type * mdss_bus_vote_type: register bus vote type * VOTE_INDEX_DISABLE: removes the client vote * VOTE_INDEX_DISABLE: removes the client vote * VOTE_INDEX_LOW: keeps the lowest vote for register bus * VOTE_INDEX_LOW: keeps the lowest vote for register bus * VOTE_INDEX_MEDIUM: keeps medium vote for register bus * VOTE_INDEX_HIGH: keeps the highest vote for register bus * VOTE_INDEX_MAX: invalid * VOTE_INDEX_MAX: invalid */ */ enum mdss_bus_vote_type { enum mdss_bus_vote_type { VOTE_INDEX_DISABLE, VOTE_INDEX_DISABLE, VOTE_INDEX_LOW, VOTE_INDEX_LOW, VOTE_INDEX_MEDIUM, VOTE_INDEX_HIGH, VOTE_INDEX_MAX, VOTE_INDEX_MAX, }; }; Loading Loading @@ -227,6 +231,19 @@ void sde_power_client_destroy(struct sde_power_handle *phandle, int sde_power_resource_enable(struct sde_power_handle *pdata, int sde_power_resource_enable(struct sde_power_handle *pdata, struct sde_power_client *pclient, bool enable); struct sde_power_client *pclient, bool enable); /** * sde_power_scale_reg_bus() - Scale the registers bus for the specified client * @phandle: power handle containing the resources * @pclient: client information to scale its vote * @usecase_ndx: new use case to scale the reg bus * @skip_lock: will skip holding the power rsrc mutex during the call, this is * for internal callers that already hold this required lock. * * Return: error code. */ int sde_power_scale_reg_bus(struct sde_power_handle *phandle, struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock); /** /** * sde_power_resource_is_enabled() - return true if power resource is enabled * sde_power_resource_is_enabled() - return true if power resource is enabled * @pdata: power handle containing the resources * @pdata: power handle containing the resources Loading Loading
drivers/gpu/drm/msm/sde_power_handle.c +76 −6 Original line number Original line Diff line number Diff line Loading @@ -847,6 +847,68 @@ void sde_power_resource_deinit(struct platform_device *pdev, sde_rsc_client_destroy(phandle->rsc_client); sde_rsc_client_destroy(phandle->rsc_client); } } int sde_power_scale_reg_bus(struct sde_power_handle *phandle, struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock) { struct sde_power_client *client; int rc = 0; u32 max_usecase_ndx = VOTE_INDEX_DISABLE; if (!skip_lock) { mutex_lock(&phandle->phandle_lock); if (WARN_ON(pclient->refcount == 0)) { /* * This is not expected, clients calling without skip * lock are outside the power resource enable, which * means that they should have enabled the power * resource before trying to scale. */ rc = -EINVAL; goto exit; } } pr_debug("%pS: current idx:%d requested:%d client:%d\n", __builtin_return_address(0), pclient->usecase_ndx, usecase_ndx, pclient->id); pclient->usecase_ndx = usecase_ndx; list_for_each_entry(client, &phandle->power_client_clist, list) { if (client->usecase_ndx < VOTE_INDEX_MAX && client->usecase_ndx > max_usecase_ndx) max_usecase_ndx = client->usecase_ndx; } rc = sde_power_reg_bus_update(phandle->reg_bus_hdl, max_usecase_ndx); if (rc) pr_err("failed to set reg bus vote rc=%d\n", rc); exit: if (!skip_lock) mutex_unlock(&phandle->phandle_lock); return rc; } static inline bool _resource_changed(u32 current_usecase_ndx, u32 max_usecase_ndx) { WARN_ON((current_usecase_ndx >= VOTE_INDEX_MAX) || (max_usecase_ndx >= VOTE_INDEX_MAX)); if (((current_usecase_ndx >= VOTE_INDEX_LOW) && /* enabled */ (max_usecase_ndx == VOTE_INDEX_DISABLE)) || /* max disabled */ ((current_usecase_ndx == VOTE_INDEX_DISABLE) && /* disabled */ (max_usecase_ndx >= VOTE_INDEX_LOW))) /* max enabled */ return true; return false; } int sde_power_resource_enable(struct sde_power_handle *phandle, int sde_power_resource_enable(struct sde_power_handle *phandle, struct sde_power_client *pclient, bool enable) struct sde_power_client *pclient, bool enable) { { Loading Loading @@ -880,7 +942,15 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, max_usecase_ndx = client->usecase_ndx; max_usecase_ndx = client->usecase_ndx; } } if (phandle->current_usecase_ndx != max_usecase_ndx) { /* * Check if we need to enable/disable the power resource, we won't * only-scale up/down the AHB vote in this API; if a client wants to * bump up the AHB clock above the LOW (default) level, it needs to * call 'sde_power_scale_reg_bus' with the desired vote after the power * resource was enabled. */ if (_resource_changed(phandle->current_usecase_ndx, max_usecase_ndx)) { changed = true; changed = true; prev_usecase_ndx = phandle->current_usecase_ndx; prev_usecase_ndx = phandle->current_usecase_ndx; phandle->current_usecase_ndx = max_usecase_ndx; phandle->current_usecase_ndx = max_usecase_ndx; Loading Loading @@ -916,8 +986,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, goto vreg_err; goto vreg_err; } } rc = sde_power_reg_bus_update(phandle->reg_bus_hdl, rc = sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx); max_usecase_ndx, true); if (rc) { if (rc) { pr_err("failed to set reg bus vote rc=%d\n", rc); pr_err("failed to set reg bus vote rc=%d\n", rc); goto reg_bus_hdl_err; goto reg_bus_hdl_err; Loading Loading @@ -948,8 +1018,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); sde_power_reg_bus_update(phandle->reg_bus_hdl, sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx); max_usecase_ndx, true); msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable); msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable); Loading @@ -970,7 +1040,7 @@ int sde_power_resource_enable(struct sde_power_handle *phandle, clk_err: clk_err: sde_power_rsc_update(phandle, false); sde_power_rsc_update(phandle, false); rsc_err: rsc_err: sde_power_reg_bus_update(phandle->reg_bus_hdl, prev_usecase_ndx); sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx, true); reg_bus_hdl_err: reg_bus_hdl_err: msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0); msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0); vreg_err: vreg_err: Loading
drivers/gpu/drm/msm/sde_power_handle.h +17 −0 Original line number Original line Diff line number Diff line Loading @@ -43,11 +43,15 @@ * mdss_bus_vote_type: register bus vote type * mdss_bus_vote_type: register bus vote type * VOTE_INDEX_DISABLE: removes the client vote * VOTE_INDEX_DISABLE: removes the client vote * VOTE_INDEX_LOW: keeps the lowest vote for register bus * VOTE_INDEX_LOW: keeps the lowest vote for register bus * VOTE_INDEX_MEDIUM: keeps medium vote for register bus * VOTE_INDEX_HIGH: keeps the highest vote for register bus * VOTE_INDEX_MAX: invalid * VOTE_INDEX_MAX: invalid */ */ enum mdss_bus_vote_type { enum mdss_bus_vote_type { VOTE_INDEX_DISABLE, VOTE_INDEX_DISABLE, VOTE_INDEX_LOW, VOTE_INDEX_LOW, VOTE_INDEX_MEDIUM, VOTE_INDEX_HIGH, VOTE_INDEX_MAX, VOTE_INDEX_MAX, }; }; Loading Loading @@ -227,6 +231,19 @@ void sde_power_client_destroy(struct sde_power_handle *phandle, int sde_power_resource_enable(struct sde_power_handle *pdata, int sde_power_resource_enable(struct sde_power_handle *pdata, struct sde_power_client *pclient, bool enable); struct sde_power_client *pclient, bool enable); /** * sde_power_scale_reg_bus() - Scale the registers bus for the specified client * @phandle: power handle containing the resources * @pclient: client information to scale its vote * @usecase_ndx: new use case to scale the reg bus * @skip_lock: will skip holding the power rsrc mutex during the call, this is * for internal callers that already hold this required lock. * * Return: error code. */ int sde_power_scale_reg_bus(struct sde_power_handle *phandle, struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock); /** /** * sde_power_resource_is_enabled() - return true if power resource is enabled * sde_power_resource_is_enabled() - return true if power resource is enabled * @pdata: power handle containing the resources * @pdata: power handle containing the resources Loading