Loading drivers/gpu/drm/msm/sde/sde_core_perf.c +62 −102 Original line number Diff line number Diff line /* Copyright (c) 2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -22,16 +22,10 @@ #include "msm_prop.h" #include "sde_kms.h" #include "sde_fence.h" #include "sde_formats.h" #include "sde_hw_sspp.h" #include "sde_trace.h" #include "sde_crtc.h" #include "sde_plane.h" #include "sde_encoder.h" #include "sde_wb.h" #include "sde_rsc.h" #include "sde_core_perf.h" #include "sde_trace.h" static struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc) { Loading Loading @@ -59,20 +53,23 @@ static bool _sde_core_perf_crtc_is_power_on(struct drm_crtc *crtc) static bool _sde_core_video_mode_intf_connected(struct drm_crtc *crtc) { struct drm_crtc *tmp_crtc; bool intf_connected = false; if (!crtc) return 0; goto end; drm_for_each_crtc(tmp_crtc, crtc->dev) { if ((sde_crtc_get_intf_mode(tmp_crtc) == INTF_MODE_VIDEO) && _sde_core_perf_crtc_is_power_on(tmp_crtc)) { SDE_DEBUG("video interface connected crtc:%d\n", tmp_crtc->base.id); return true; intf_connected = true; goto end; } } return false; end: return intf_connected; } int sde_core_perf_crtc_check(struct drm_crtc *crtc, Loading @@ -80,6 +77,7 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, { u32 bw, threshold; u64 bw_sum_of_intfs = 0; enum sde_crtc_client_type curr_client_type; bool is_video_mode; struct sde_crtc_state *sde_cstate; struct drm_crtc *tmp_crtc; Loading @@ -97,16 +95,18 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, } /* we only need bandwidth check on real-time clients (interfaces) */ if (sde_crtc_is_wb(crtc)) if (sde_crtc_get_client_type(crtc) == NRT_CLIENT) return 0; sde_cstate = to_sde_crtc_state(state); bw_sum_of_intfs = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB); curr_client_type = sde_crtc_get_client_type(crtc); drm_for_each_crtc(tmp_crtc, crtc->dev) { if (_sde_core_perf_crtc_is_power_on(tmp_crtc) && sde_crtc_is_rt(tmp_crtc) && tmp_crtc != crtc) { (sde_crtc_get_client_type(tmp_crtc) == curr_client_type) && (tmp_crtc != crtc)) { struct sde_crtc_state *tmp_cstate = to_sde_crtc_state(tmp_crtc->state); Loading @@ -131,7 +131,7 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, return -E2BIG; } else if (bw > threshold) { sde_cstate->cur_perf.bw_ctl = 0; SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); SDE_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); return -E2BIG; } Loading @@ -158,23 +158,23 @@ static void _sde_core_perf_calc_crtc(struct sde_kms *kms, perf->max_per_pipe_ib, perf->bw_ctl); } static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, struct drm_crtc *crtc, struct sde_core_perf_params *perf, bool nrt_client, u32 core_clk) static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms, struct drm_crtc *crtc) { u64 bw_sum_of_intfs = 0; u64 bw_sum_of_intfs = 0, bus_ab_quota, bus_ib_quota; struct sde_core_perf_params perf = {0}; enum sde_crtc_client_type curr_client_type = sde_crtc_get_client_type(crtc); struct drm_crtc *tmp_crtc; struct sde_crtc_state *sde_cstate; struct msm_drm_private *priv = kms->dev->dev_private; drm_for_each_crtc(tmp_crtc, crtc->dev) { if (_sde_core_perf_crtc_is_power_on(crtc) && /* RealTime clients */ ((!nrt_client) || /* Non-RealTime clients */ (nrt_client && sde_crtc_is_nrt(tmp_crtc)))) { struct sde_crtc_state *sde_cstate = to_sde_crtc_state(tmp_crtc->state); if (_sde_core_perf_crtc_is_power_on(tmp_crtc) && (curr_client_type == sde_crtc_get_client_type(tmp_crtc))) { sde_cstate = to_sde_crtc_state(tmp_crtc->state); perf->max_per_pipe_ib = max(perf->max_per_pipe_ib, perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, sde_cstate->cur_perf.max_per_pipe_ib); bw_sum_of_intfs += sde_cstate->cur_perf.bw_ctl; Loading @@ -185,57 +185,38 @@ static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, } } return bw_sum_of_intfs; } bus_ab_quota = max(bw_sum_of_intfs, kms->perf.perf_tune.min_bus_vote); bus_ib_quota = perf.max_per_pipe_ib; static void _sde_core_perf_crtc_update_client_vote(struct sde_kms *kms, struct sde_core_perf_params *params, bool nrt_client, u64 bw_vote) { struct msm_drm_private *priv = kms->dev->dev_private; u64 bus_ab_quota, bus_ib_quota; bus_ab_quota = max(bw_vote, kms->perf.perf_tune.min_bus_vote); bus_ib_quota = params->max_per_pipe_ib; switch (curr_client_type) { case NRT_CLIENT: sde_power_data_bus_set_quota(&priv->phandle, kms->core_client, SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT, bus_ab_quota, bus_ib_quota); SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "nrt", bus_ab_quota, bus_ib_quota); break; SDE_ATRACE_INT("bus_quota", bus_ib_quota); case RT_CLIENT: sde_power_data_bus_set_quota(&priv->phandle, kms->core_client, nrt_client ? SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT : SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, bus_ab_quota, bus_ib_quota); SDE_DEBUG("client:%s ab=%llu ib=%llu\n", nrt_client ? "nrt" : "rt", SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "rt", bus_ab_quota, bus_ib_quota); } static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms, struct drm_crtc *crtc, u32 core_clk) { u64 bw_sum_of_rt_intfs = 0, bw_sum_of_nrt_intfs = 0; struct sde_core_perf_params params = {0}; SDE_ATRACE_BEGIN(__func__); break; /* * non-real time client */ if (sde_crtc_is_nrt(crtc)) { bw_sum_of_nrt_intfs = _sde_core_perf_crtc_calc_client_vote( kms, crtc, ¶ms, true, core_clk); _sde_core_perf_crtc_update_client_vote(kms, ¶ms, true, bw_sum_of_nrt_intfs); } case RT_RSC_CLIENT: sde_cstate = to_sde_crtc_state(crtc->state); sde_rsc_client_vote(sde_cstate->rsc_client, bus_ab_quota, bus_ib_quota); SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "rt_rsc", bus_ab_quota, bus_ib_quota); break; /* * real time client */ if (!sde_crtc_is_nrt(crtc) || sde_crtc_is_wb(crtc)) { bw_sum_of_rt_intfs = _sde_core_perf_crtc_calc_client_vote(kms, crtc, ¶ms, false, core_clk); _sde_core_perf_crtc_update_client_vote(kms, ¶ms, false, bw_sum_of_rt_intfs); default: SDE_ERROR("invalid client type:%d\n", curr_client_type); break; } SDE_ATRACE_END(__func__); } /** Loading Loading @@ -265,9 +246,9 @@ void sde_core_perf_crtc_release_bw(struct drm_crtc *crtc) sde_cstate = to_sde_crtc_state(crtc->state); /* only do this for command panel or writeback */ /* only do this for command mode rt client (non-rsc client) */ if ((sde_crtc_get_intf_mode(crtc) != INTF_MODE_CMD) && (sde_crtc_get_intf_mode(crtc) != INTF_MODE_WB_LINE)) (sde_crtc_get_client_type(crtc) != RT_RSC_CLIENT)) return; /* Loading @@ -288,14 +269,8 @@ void sde_core_perf_crtc_release_bw(struct drm_crtc *crtc) sde_cstate->cur_perf.bw_ctl = 0; sde_cstate->new_perf.bw_ctl = 0; SDE_DEBUG("Release BW crtc=%d\n", crtc->base.id); _sde_core_perf_crtc_update_bus(kms, crtc, 0); } _sde_core_perf_crtc_update_bus(kms, crtc); } static int _sde_core_select_clk_lvl(struct sde_kms *kms, u32 clk_rate) { return clk_round_rate(kms->perf.core_clk, clk_rate); } static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms) Loading @@ -303,7 +278,6 @@ static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms) u32 clk_rate = 0; struct drm_crtc *crtc; struct sde_crtc_state *sde_cstate; int ncrtc = 0; drm_for_each_crtc(crtc, kms->dev) { if (_sde_core_perf_crtc_is_power_on(crtc)) { Loading @@ -312,11 +286,9 @@ static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms) clk_rate); clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate); } ncrtc++; } clk_rate = _sde_core_select_clk_lvl(kms, clk_rate); SDE_DEBUG("clk:%u ncrtc:%d\n", clk_rate, ncrtc); SDE_DEBUG("clk:%u\n", clk_rate); return clk_rate; } Loading Loading @@ -351,8 +323,6 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc, SDE_DEBUG("crtc:%d stop_req:%d core_clk:%u\n", crtc->base.id, stop_req, kms->perf.core_clk_rate); SDE_ATRACE_BEGIN(__func__); old = &sde_cstate->cur_perf; new = &sde_cstate->new_perf; Loading Loading @@ -392,38 +362,28 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc, update_clk = 1; } /* * Calculate mdp clock before bandwidth calculation. If traffic shaper * is enabled and clock increased, the bandwidth calculation can * use the new clock for the rotator bw calculation. */ if (update_clk) clk_rate = _sde_core_perf_get_core_clk_rate(kms); if (update_bus) _sde_core_perf_crtc_update_bus(kms, crtc, clk_rate); _sde_core_perf_crtc_update_bus(kms, crtc); /* * Update the clock after bandwidth vote to ensure * bandwidth is available before clock rate is increased. */ if (update_clk) { SDE_ATRACE_INT(kms->perf.clk_name, clk_rate); clk_rate = _sde_core_perf_get_core_clk_rate(kms); SDE_EVT32(kms->dev, stop_req, clk_rate); ret = sde_power_clk_set_rate(&priv->phandle, kms->perf.clk_name, clk_rate); if (ret) { SDE_ERROR("failed to set %s clock rate %u\n", kms->perf.clk_name, clk_rate); goto end; return; } kms->perf.core_clk_rate = clk_rate; SDE_DEBUG("update clk rate = %d HZ\n", clk_rate); } end: SDE_ATRACE_END(__func__); } #ifdef CONFIG_DEBUG_FS Loading drivers/gpu/drm/msm/sde/sde_crtc.c +1 −14 Original line number Diff line number Diff line Loading @@ -417,7 +417,6 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, SDE_EVT32(DRMID(crtc)); /* identify connectors attached to this crtc */ cstate->is_rt = false; cstate->num_connectors = 0; drm_for_each_connector(conn, crtc->dev) Loading @@ -425,9 +424,6 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, cstate->num_connectors < MAX_CONNECTORS) { cstate->connectors[cstate->num_connectors++] = conn; sde_connector_prepare_fence(conn); if (conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL) cstate->is_rt = true; } if (cstate->num_connectors > 0 && cstate->connectors[0]->encoder) Loading @@ -440,15 +436,6 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, sde_fence_prepare(&sde_crtc->output_fence); } bool sde_crtc_is_rt(struct drm_crtc *crtc) { if (!crtc || !crtc->state) { SDE_ERROR("invalid crtc or state\n"); return true; } return to_sde_crtc_state(crtc->state)->is_rt; } /* if file!=NULL, this is preclose potential cancel-flip path */ static void _sde_crtc_complete_flip(struct drm_crtc *crtc, struct drm_file *file) Loading Loading @@ -1869,7 +1856,7 @@ static int sde_crtc_debugfs_state_show(struct seq_file *s, void *v) struct sde_crtc_state *cstate = to_sde_crtc_state(crtc->state); seq_printf(s, "num_connectors: %d\n", cstate->num_connectors); seq_printf(s, "is_rt: %d\n", cstate->is_rt); seq_printf(s, "client type: %d\n", sde_crtc_get_client_type(crtc)); seq_printf(s, "intf_mode: %d\n", cstate->intf_mode); seq_printf(s, "bw_ctl: %llu\n", cstate->cur_perf.bw_ctl); seq_printf(s, "core_clk_rate: %u\n", cstate->cur_perf.core_clk_rate); Loading drivers/gpu/drm/msm/sde/sde_crtc.h +22 −21 Original line number Diff line number Diff line Loading @@ -30,6 +30,20 @@ /* define the maximum number of in-flight frame events */ #define SDE_CRTC_FRAME_EVENT_SIZE 2 /** * enum sde_crtc_client_type: crtc client type * @RT_CLIENT: RealTime client like video/cmd mode display * voting through apps rsc * @NRT_CLIENT: Non-RealTime client like WB display * voting through apps rsc * @RT_RSC_CLIENT: Realtime display RSC voting client */ enum sde_crtc_client_type { RT_CLIENT, NRT_CLIENT, RT_RSC_CLIENT, }; /** * struct sde_crtc_mixer: stores the map for each virtual pipeline in the CRTC * @hw_lm: LM HW Driver context Loading Loading @@ -136,8 +150,9 @@ struct sde_crtc { * @base: Base drm crtc state structure * @connectors : Currently associated drm connectors * @num_connectors: Number of associated drm connectors * @is_rt : Whether or not the current commit contains RT connectors * @intf_mode : Interface mode of the primary connector * @rsc_mode : Client vote through sde rsc * @rsc_client : sde rsc client when mode is valid * @property_values: Current crtc property values * @input_fence_timeout_ns : Cached input fence timeout, in ns * @property_blobs: Reference pointers for blob properties Loading @@ -151,8 +166,9 @@ struct sde_crtc_state { struct drm_connector *connectors[MAX_CONNECTORS]; int num_connectors; bool is_rt; enum sde_intf_mode intf_mode; bool rsc_mode; struct sde_rsc_client *rsc_client; uint64_t property_values[CRTC_PROP_COUNT]; uint64_t input_fence_timeout_ns; Loading Loading @@ -254,13 +270,6 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane); */ void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file); /** * sde_crtc_is_rt - query whether real time connectors are present on the crtc * @crtc: Pointer to drm crtc structure * Returns: True if a connector is present with real time constraints */ bool sde_crtc_is_rt(struct drm_crtc *crtc); /** * sde_crtc_get_intf_mode - get interface mode of the given crtc * @crtc: Pointert to crtc Loading @@ -274,24 +283,16 @@ static inline enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc) } /** * sde_core_perf_crtc_is_wb - check if writeback is primary output of this crtc * sde_crtc_get_client_type - check the crtc type- rt, nrt, rsc, etc. * @crtc: Pointer to crtc */ static inline bool sde_crtc_is_wb(struct drm_crtc *crtc) static inline bool sde_crtc_get_client_type(struct drm_crtc *crtc) { struct sde_crtc_state *cstate = crtc ? to_sde_crtc_state(crtc->state) : NULL; return cstate ? (cstate->intf_mode == INTF_MODE_WB_LINE) : false; } /** * sde_crtc_is_nrt - check if primary output of this crtc is non-realtime client * @crtc: Pointer to crtc */ static inline bool sde_crtc_is_nrt(struct drm_crtc *crtc) { return sde_crtc_is_wb(crtc); return cstate && (cstate->intf_mode == INTF_MODE_WB_LINE) ? NRT_CLIENT : cstate && cstate->rsc_mode ? RT_RSC_CLIENT : RT_CLIENT; } /** Loading drivers/gpu/drm/msm/sde/sde_encoder.c +1 −3 Original line number Diff line number Diff line Loading @@ -862,8 +862,7 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) if (sde_enc->disp_info.is_primary) { ret = sde_rsc_client_vote(sde_enc->rsc_client, SDE_POWER_HANDLE_DATA_BUS_IB_QUOTA, SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA, true); SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA); if (ret) SDE_ERROR("sde rsc client vote failed ret:%d\n", ret); } Loading Loading @@ -1303,7 +1302,6 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc, } mutex_unlock(&sde_enc->enc_lock); return ret; } Loading drivers/gpu/drm/msm/sde/sde_plane.c +1 −1 Original line number Diff line number Diff line Loading @@ -1203,7 +1203,7 @@ static int _sde_plane_mode_set(struct drm_plane *plane, return 0; pstate->pending = true; psde->is_rt_pipe = sde_crtc_is_rt(crtc); psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT); _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL); /* update roi config */ Loading Loading
drivers/gpu/drm/msm/sde/sde_core_perf.c +62 −102 Original line number Diff line number Diff line /* Copyright (c) 2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -22,16 +22,10 @@ #include "msm_prop.h" #include "sde_kms.h" #include "sde_fence.h" #include "sde_formats.h" #include "sde_hw_sspp.h" #include "sde_trace.h" #include "sde_crtc.h" #include "sde_plane.h" #include "sde_encoder.h" #include "sde_wb.h" #include "sde_rsc.h" #include "sde_core_perf.h" #include "sde_trace.h" static struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc) { Loading Loading @@ -59,20 +53,23 @@ static bool _sde_core_perf_crtc_is_power_on(struct drm_crtc *crtc) static bool _sde_core_video_mode_intf_connected(struct drm_crtc *crtc) { struct drm_crtc *tmp_crtc; bool intf_connected = false; if (!crtc) return 0; goto end; drm_for_each_crtc(tmp_crtc, crtc->dev) { if ((sde_crtc_get_intf_mode(tmp_crtc) == INTF_MODE_VIDEO) && _sde_core_perf_crtc_is_power_on(tmp_crtc)) { SDE_DEBUG("video interface connected crtc:%d\n", tmp_crtc->base.id); return true; intf_connected = true; goto end; } } return false; end: return intf_connected; } int sde_core_perf_crtc_check(struct drm_crtc *crtc, Loading @@ -80,6 +77,7 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, { u32 bw, threshold; u64 bw_sum_of_intfs = 0; enum sde_crtc_client_type curr_client_type; bool is_video_mode; struct sde_crtc_state *sde_cstate; struct drm_crtc *tmp_crtc; Loading @@ -97,16 +95,18 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, } /* we only need bandwidth check on real-time clients (interfaces) */ if (sde_crtc_is_wb(crtc)) if (sde_crtc_get_client_type(crtc) == NRT_CLIENT) return 0; sde_cstate = to_sde_crtc_state(state); bw_sum_of_intfs = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB); curr_client_type = sde_crtc_get_client_type(crtc); drm_for_each_crtc(tmp_crtc, crtc->dev) { if (_sde_core_perf_crtc_is_power_on(tmp_crtc) && sde_crtc_is_rt(tmp_crtc) && tmp_crtc != crtc) { (sde_crtc_get_client_type(tmp_crtc) == curr_client_type) && (tmp_crtc != crtc)) { struct sde_crtc_state *tmp_cstate = to_sde_crtc_state(tmp_crtc->state); Loading @@ -131,7 +131,7 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, return -E2BIG; } else if (bw > threshold) { sde_cstate->cur_perf.bw_ctl = 0; SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); SDE_ERROR("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); return -E2BIG; } Loading @@ -158,23 +158,23 @@ static void _sde_core_perf_calc_crtc(struct sde_kms *kms, perf->max_per_pipe_ib, perf->bw_ctl); } static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, struct drm_crtc *crtc, struct sde_core_perf_params *perf, bool nrt_client, u32 core_clk) static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms, struct drm_crtc *crtc) { u64 bw_sum_of_intfs = 0; u64 bw_sum_of_intfs = 0, bus_ab_quota, bus_ib_quota; struct sde_core_perf_params perf = {0}; enum sde_crtc_client_type curr_client_type = sde_crtc_get_client_type(crtc); struct drm_crtc *tmp_crtc; struct sde_crtc_state *sde_cstate; struct msm_drm_private *priv = kms->dev->dev_private; drm_for_each_crtc(tmp_crtc, crtc->dev) { if (_sde_core_perf_crtc_is_power_on(crtc) && /* RealTime clients */ ((!nrt_client) || /* Non-RealTime clients */ (nrt_client && sde_crtc_is_nrt(tmp_crtc)))) { struct sde_crtc_state *sde_cstate = to_sde_crtc_state(tmp_crtc->state); if (_sde_core_perf_crtc_is_power_on(tmp_crtc) && (curr_client_type == sde_crtc_get_client_type(tmp_crtc))) { sde_cstate = to_sde_crtc_state(tmp_crtc->state); perf->max_per_pipe_ib = max(perf->max_per_pipe_ib, perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, sde_cstate->cur_perf.max_per_pipe_ib); bw_sum_of_intfs += sde_cstate->cur_perf.bw_ctl; Loading @@ -185,57 +185,38 @@ static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, } } return bw_sum_of_intfs; } bus_ab_quota = max(bw_sum_of_intfs, kms->perf.perf_tune.min_bus_vote); bus_ib_quota = perf.max_per_pipe_ib; static void _sde_core_perf_crtc_update_client_vote(struct sde_kms *kms, struct sde_core_perf_params *params, bool nrt_client, u64 bw_vote) { struct msm_drm_private *priv = kms->dev->dev_private; u64 bus_ab_quota, bus_ib_quota; bus_ab_quota = max(bw_vote, kms->perf.perf_tune.min_bus_vote); bus_ib_quota = params->max_per_pipe_ib; switch (curr_client_type) { case NRT_CLIENT: sde_power_data_bus_set_quota(&priv->phandle, kms->core_client, SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT, bus_ab_quota, bus_ib_quota); SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "nrt", bus_ab_quota, bus_ib_quota); break; SDE_ATRACE_INT("bus_quota", bus_ib_quota); case RT_CLIENT: sde_power_data_bus_set_quota(&priv->phandle, kms->core_client, nrt_client ? SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT : SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, bus_ab_quota, bus_ib_quota); SDE_DEBUG("client:%s ab=%llu ib=%llu\n", nrt_client ? "nrt" : "rt", SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "rt", bus_ab_quota, bus_ib_quota); } static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms, struct drm_crtc *crtc, u32 core_clk) { u64 bw_sum_of_rt_intfs = 0, bw_sum_of_nrt_intfs = 0; struct sde_core_perf_params params = {0}; SDE_ATRACE_BEGIN(__func__); break; /* * non-real time client */ if (sde_crtc_is_nrt(crtc)) { bw_sum_of_nrt_intfs = _sde_core_perf_crtc_calc_client_vote( kms, crtc, ¶ms, true, core_clk); _sde_core_perf_crtc_update_client_vote(kms, ¶ms, true, bw_sum_of_nrt_intfs); } case RT_RSC_CLIENT: sde_cstate = to_sde_crtc_state(crtc->state); sde_rsc_client_vote(sde_cstate->rsc_client, bus_ab_quota, bus_ib_quota); SDE_DEBUG("client:%s ab=%llu ib=%llu\n", "rt_rsc", bus_ab_quota, bus_ib_quota); break; /* * real time client */ if (!sde_crtc_is_nrt(crtc) || sde_crtc_is_wb(crtc)) { bw_sum_of_rt_intfs = _sde_core_perf_crtc_calc_client_vote(kms, crtc, ¶ms, false, core_clk); _sde_core_perf_crtc_update_client_vote(kms, ¶ms, false, bw_sum_of_rt_intfs); default: SDE_ERROR("invalid client type:%d\n", curr_client_type); break; } SDE_ATRACE_END(__func__); } /** Loading Loading @@ -265,9 +246,9 @@ void sde_core_perf_crtc_release_bw(struct drm_crtc *crtc) sde_cstate = to_sde_crtc_state(crtc->state); /* only do this for command panel or writeback */ /* only do this for command mode rt client (non-rsc client) */ if ((sde_crtc_get_intf_mode(crtc) != INTF_MODE_CMD) && (sde_crtc_get_intf_mode(crtc) != INTF_MODE_WB_LINE)) (sde_crtc_get_client_type(crtc) != RT_RSC_CLIENT)) return; /* Loading @@ -288,14 +269,8 @@ void sde_core_perf_crtc_release_bw(struct drm_crtc *crtc) sde_cstate->cur_perf.bw_ctl = 0; sde_cstate->new_perf.bw_ctl = 0; SDE_DEBUG("Release BW crtc=%d\n", crtc->base.id); _sde_core_perf_crtc_update_bus(kms, crtc, 0); } _sde_core_perf_crtc_update_bus(kms, crtc); } static int _sde_core_select_clk_lvl(struct sde_kms *kms, u32 clk_rate) { return clk_round_rate(kms->perf.core_clk, clk_rate); } static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms) Loading @@ -303,7 +278,6 @@ static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms) u32 clk_rate = 0; struct drm_crtc *crtc; struct sde_crtc_state *sde_cstate; int ncrtc = 0; drm_for_each_crtc(crtc, kms->dev) { if (_sde_core_perf_crtc_is_power_on(crtc)) { Loading @@ -312,11 +286,9 @@ static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms) clk_rate); clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate); } ncrtc++; } clk_rate = _sde_core_select_clk_lvl(kms, clk_rate); SDE_DEBUG("clk:%u ncrtc:%d\n", clk_rate, ncrtc); SDE_DEBUG("clk:%u\n", clk_rate); return clk_rate; } Loading Loading @@ -351,8 +323,6 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc, SDE_DEBUG("crtc:%d stop_req:%d core_clk:%u\n", crtc->base.id, stop_req, kms->perf.core_clk_rate); SDE_ATRACE_BEGIN(__func__); old = &sde_cstate->cur_perf; new = &sde_cstate->new_perf; Loading Loading @@ -392,38 +362,28 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc, update_clk = 1; } /* * Calculate mdp clock before bandwidth calculation. If traffic shaper * is enabled and clock increased, the bandwidth calculation can * use the new clock for the rotator bw calculation. */ if (update_clk) clk_rate = _sde_core_perf_get_core_clk_rate(kms); if (update_bus) _sde_core_perf_crtc_update_bus(kms, crtc, clk_rate); _sde_core_perf_crtc_update_bus(kms, crtc); /* * Update the clock after bandwidth vote to ensure * bandwidth is available before clock rate is increased. */ if (update_clk) { SDE_ATRACE_INT(kms->perf.clk_name, clk_rate); clk_rate = _sde_core_perf_get_core_clk_rate(kms); SDE_EVT32(kms->dev, stop_req, clk_rate); ret = sde_power_clk_set_rate(&priv->phandle, kms->perf.clk_name, clk_rate); if (ret) { SDE_ERROR("failed to set %s clock rate %u\n", kms->perf.clk_name, clk_rate); goto end; return; } kms->perf.core_clk_rate = clk_rate; SDE_DEBUG("update clk rate = %d HZ\n", clk_rate); } end: SDE_ATRACE_END(__func__); } #ifdef CONFIG_DEBUG_FS Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +1 −14 Original line number Diff line number Diff line Loading @@ -417,7 +417,6 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, SDE_EVT32(DRMID(crtc)); /* identify connectors attached to this crtc */ cstate->is_rt = false; cstate->num_connectors = 0; drm_for_each_connector(conn, crtc->dev) Loading @@ -425,9 +424,6 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, cstate->num_connectors < MAX_CONNECTORS) { cstate->connectors[cstate->num_connectors++] = conn; sde_connector_prepare_fence(conn); if (conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL) cstate->is_rt = true; } if (cstate->num_connectors > 0 && cstate->connectors[0]->encoder) Loading @@ -440,15 +436,6 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, sde_fence_prepare(&sde_crtc->output_fence); } bool sde_crtc_is_rt(struct drm_crtc *crtc) { if (!crtc || !crtc->state) { SDE_ERROR("invalid crtc or state\n"); return true; } return to_sde_crtc_state(crtc->state)->is_rt; } /* if file!=NULL, this is preclose potential cancel-flip path */ static void _sde_crtc_complete_flip(struct drm_crtc *crtc, struct drm_file *file) Loading Loading @@ -1869,7 +1856,7 @@ static int sde_crtc_debugfs_state_show(struct seq_file *s, void *v) struct sde_crtc_state *cstate = to_sde_crtc_state(crtc->state); seq_printf(s, "num_connectors: %d\n", cstate->num_connectors); seq_printf(s, "is_rt: %d\n", cstate->is_rt); seq_printf(s, "client type: %d\n", sde_crtc_get_client_type(crtc)); seq_printf(s, "intf_mode: %d\n", cstate->intf_mode); seq_printf(s, "bw_ctl: %llu\n", cstate->cur_perf.bw_ctl); seq_printf(s, "core_clk_rate: %u\n", cstate->cur_perf.core_clk_rate); Loading
drivers/gpu/drm/msm/sde/sde_crtc.h +22 −21 Original line number Diff line number Diff line Loading @@ -30,6 +30,20 @@ /* define the maximum number of in-flight frame events */ #define SDE_CRTC_FRAME_EVENT_SIZE 2 /** * enum sde_crtc_client_type: crtc client type * @RT_CLIENT: RealTime client like video/cmd mode display * voting through apps rsc * @NRT_CLIENT: Non-RealTime client like WB display * voting through apps rsc * @RT_RSC_CLIENT: Realtime display RSC voting client */ enum sde_crtc_client_type { RT_CLIENT, NRT_CLIENT, RT_RSC_CLIENT, }; /** * struct sde_crtc_mixer: stores the map for each virtual pipeline in the CRTC * @hw_lm: LM HW Driver context Loading Loading @@ -136,8 +150,9 @@ struct sde_crtc { * @base: Base drm crtc state structure * @connectors : Currently associated drm connectors * @num_connectors: Number of associated drm connectors * @is_rt : Whether or not the current commit contains RT connectors * @intf_mode : Interface mode of the primary connector * @rsc_mode : Client vote through sde rsc * @rsc_client : sde rsc client when mode is valid * @property_values: Current crtc property values * @input_fence_timeout_ns : Cached input fence timeout, in ns * @property_blobs: Reference pointers for blob properties Loading @@ -151,8 +166,9 @@ struct sde_crtc_state { struct drm_connector *connectors[MAX_CONNECTORS]; int num_connectors; bool is_rt; enum sde_intf_mode intf_mode; bool rsc_mode; struct sde_rsc_client *rsc_client; uint64_t property_values[CRTC_PROP_COUNT]; uint64_t input_fence_timeout_ns; Loading Loading @@ -254,13 +270,6 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane); */ void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file); /** * sde_crtc_is_rt - query whether real time connectors are present on the crtc * @crtc: Pointer to drm crtc structure * Returns: True if a connector is present with real time constraints */ bool sde_crtc_is_rt(struct drm_crtc *crtc); /** * sde_crtc_get_intf_mode - get interface mode of the given crtc * @crtc: Pointert to crtc Loading @@ -274,24 +283,16 @@ static inline enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc) } /** * sde_core_perf_crtc_is_wb - check if writeback is primary output of this crtc * sde_crtc_get_client_type - check the crtc type- rt, nrt, rsc, etc. * @crtc: Pointer to crtc */ static inline bool sde_crtc_is_wb(struct drm_crtc *crtc) static inline bool sde_crtc_get_client_type(struct drm_crtc *crtc) { struct sde_crtc_state *cstate = crtc ? to_sde_crtc_state(crtc->state) : NULL; return cstate ? (cstate->intf_mode == INTF_MODE_WB_LINE) : false; } /** * sde_crtc_is_nrt - check if primary output of this crtc is non-realtime client * @crtc: Pointer to crtc */ static inline bool sde_crtc_is_nrt(struct drm_crtc *crtc) { return sde_crtc_is_wb(crtc); return cstate && (cstate->intf_mode == INTF_MODE_WB_LINE) ? NRT_CLIENT : cstate && cstate->rsc_mode ? RT_RSC_CLIENT : RT_CLIENT; } /** Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +1 −3 Original line number Diff line number Diff line Loading @@ -862,8 +862,7 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) if (sde_enc->disp_info.is_primary) { ret = sde_rsc_client_vote(sde_enc->rsc_client, SDE_POWER_HANDLE_DATA_BUS_IB_QUOTA, SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA, true); SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA); if (ret) SDE_ERROR("sde rsc client vote failed ret:%d\n", ret); } Loading Loading @@ -1303,7 +1302,6 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc, } mutex_unlock(&sde_enc->enc_lock); return ret; } Loading
drivers/gpu/drm/msm/sde/sde_plane.c +1 −1 Original line number Diff line number Diff line Loading @@ -1203,7 +1203,7 @@ static int _sde_plane_mode_set(struct drm_plane *plane, return 0; pstate->pending = true; psde->is_rt_pipe = sde_crtc_is_rt(crtc); psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT); _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL); /* update roi config */ Loading