Loading drivers/gpu/drm/msm/sde/sde_core_perf.c +38 −32 Original line number Original line 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 * 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 * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -75,6 +75,31 @@ static bool _sde_core_video_mode_intf_connected(struct drm_crtc *crtc) return false; return false; } } static void _sde_core_perf_calc_crtc(struct drm_crtc *crtc, struct drm_crtc_state *state, struct sde_core_perf_params *perf) { struct sde_crtc_state *sde_cstate; if (!crtc || !state || !perf) { SDE_ERROR("invalid parameters\n"); return; } sde_cstate = to_sde_crtc_state(state); memset(perf, 0, sizeof(struct sde_core_perf_params)); perf->bw_ctl = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB); perf->max_per_pipe_ib = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB); perf->core_clk_rate = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_CLK); SDE_DEBUG("crtc=%d clk_rate=%u ib=%llu ab=%llu\n", crtc->base.id, perf->core_clk_rate, perf->max_per_pipe_ib, perf->bw_ctl); } int sde_core_perf_crtc_check(struct drm_crtc *crtc, int sde_core_perf_crtc_check(struct drm_crtc *crtc, struct drm_crtc_state *state) struct drm_crtc_state *state) { { Loading Loading @@ -102,7 +127,11 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, sde_cstate = to_sde_crtc_state(state); sde_cstate = to_sde_crtc_state(state); bw_sum_of_intfs = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB); /* swap state and obtain new values */ sde_cstate->cur_perf = sde_cstate->new_perf; _sde_core_perf_calc_crtc(crtc, state, &sde_cstate->new_perf); bw_sum_of_intfs = sde_cstate->new_perf.bw_ctl; drm_for_each_crtc(tmp_crtc, crtc->dev) { drm_for_each_crtc(tmp_crtc, crtc->dev) { if (_sde_core_perf_crtc_is_power_on(tmp_crtc) && if (_sde_core_perf_crtc_is_power_on(tmp_crtc) && Loading @@ -110,7 +139,7 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, struct sde_crtc_state *tmp_cstate = struct sde_crtc_state *tmp_cstate = to_sde_crtc_state(tmp_crtc->state); to_sde_crtc_state(tmp_crtc->state); bw_sum_of_intfs += tmp_cstate->cur_perf.bw_ctl; bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; } } } } Loading @@ -126,11 +155,11 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, SDE_DEBUG("final threshold bw limit = %d\n", threshold); SDE_DEBUG("final threshold bw limit = %d\n", threshold); if (!threshold) { if (!threshold) { sde_cstate->cur_perf.bw_ctl = 0; sde_cstate->new_perf = sde_cstate->cur_perf; SDE_ERROR("no bandwidth limits specified\n"); SDE_ERROR("no bandwidth limits specified\n"); return -E2BIG; return -E2BIG; } else if (bw > threshold) { } else if (bw > threshold) { sde_cstate->cur_perf.bw_ctl = 0; sde_cstate->new_perf = sde_cstate->cur_perf; SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); return -E2BIG; return -E2BIG; } } Loading @@ -138,26 +167,6 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, return 0; return 0; } } static void _sde_core_perf_calc_crtc(struct sde_kms *kms, struct drm_crtc *crtc, struct sde_core_perf_params *perf) { struct sde_crtc_state *sde_cstate; sde_cstate = to_sde_crtc_state(crtc->state); memset(perf, 0, sizeof(struct sde_core_perf_params)); perf->bw_ctl = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB); perf->max_per_pipe_ib = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB); perf->core_clk_rate = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_CLK); SDE_DEBUG("crtc=%d clk_rate=%u ib=%llu ab=%llu\n", crtc->base.id, perf->core_clk_rate, perf->max_per_pipe_ib, perf->bw_ctl); } static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, struct drm_crtc *crtc, struct sde_core_perf_params *perf, struct drm_crtc *crtc, struct sde_core_perf_params *perf, bool nrt_client, u32 core_clk) bool nrt_client, u32 core_clk) Loading @@ -175,13 +184,13 @@ static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, to_sde_crtc_state(tmp_crtc->state); 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); sde_cstate->new_perf.max_per_pipe_ib); bw_sum_of_intfs += sde_cstate->cur_perf.bw_ctl; bw_sum_of_intfs += sde_cstate->new_perf.bw_ctl; SDE_DEBUG("crtc=%d bw=%llu\n", SDE_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id, tmp_crtc->base.id, sde_cstate->cur_perf.bw_ctl); sde_cstate->new_perf.bw_ctl); } } } } Loading Loading @@ -308,7 +317,7 @@ static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms) drm_for_each_crtc(crtc, kms->dev) { drm_for_each_crtc(crtc, kms->dev) { if (_sde_core_perf_crtc_is_power_on(crtc)) { if (_sde_core_perf_crtc_is_power_on(crtc)) { sde_cstate = to_sde_crtc_state(crtc->state); sde_cstate = to_sde_crtc_state(crtc->state); clk_rate = max(sde_cstate->cur_perf.core_clk_rate, clk_rate = max(sde_cstate->new_perf.core_clk_rate, clk_rate); clk_rate); clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate); clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate); } } Loading Loading @@ -357,9 +366,6 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc, new = &sde_cstate->new_perf; new = &sde_cstate->new_perf; if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) { if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) { if (params_changed) _sde_core_perf_calc_crtc(kms, crtc, new); /* /* * cases for bus bandwidth update. * cases for bus bandwidth update. * 1. new bandwidth vote or writeback output vote * 1. new bandwidth vote or writeback output vote Loading drivers/gpu/drm/msm/sde/sde_crtc.c +6 −1 Original line number Original line Diff line number Diff line Loading @@ -473,6 +473,7 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) struct sde_crtc_frame_event *fevent; struct sde_crtc_frame_event *fevent; struct drm_crtc *crtc; struct drm_crtc *crtc; struct sde_crtc *sde_crtc; struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; struct sde_kms *sde_kms; struct sde_kms *sde_kms; unsigned long flags; unsigned long flags; Loading @@ -482,13 +483,14 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) } } fevent = container_of(work, struct sde_crtc_frame_event, work); fevent = container_of(work, struct sde_crtc_frame_event, work); if (!fevent->crtc) { if (!fevent->crtc || !fevent->crtc->state) { SDE_ERROR("invalid crtc\n"); SDE_ERROR("invalid crtc\n"); return; return; } } crtc = fevent->crtc; crtc = fevent->crtc; sde_crtc = to_sde_crtc(crtc); sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(crtc->state); sde_kms = _sde_crtc_get_kms(crtc); sde_kms = _sde_crtc_get_kms(crtc); if (!sde_kms) { if (!sde_kms) { Loading Loading @@ -522,6 +524,9 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) } else { } else { SDE_EVT32(DRMID(crtc), fevent->event, 2); SDE_EVT32(DRMID(crtc), fevent->event, 2); } } if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE) sde_core_perf_crtc_update(crtc, 0, false); } else { } else { SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id, SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id, ktime_to_ns(fevent->ts), ktime_to_ns(fevent->ts), Loading Loading
drivers/gpu/drm/msm/sde/sde_core_perf.c +38 −32 Original line number Original line 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 * 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 * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -75,6 +75,31 @@ static bool _sde_core_video_mode_intf_connected(struct drm_crtc *crtc) return false; return false; } } static void _sde_core_perf_calc_crtc(struct drm_crtc *crtc, struct drm_crtc_state *state, struct sde_core_perf_params *perf) { struct sde_crtc_state *sde_cstate; if (!crtc || !state || !perf) { SDE_ERROR("invalid parameters\n"); return; } sde_cstate = to_sde_crtc_state(state); memset(perf, 0, sizeof(struct sde_core_perf_params)); perf->bw_ctl = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB); perf->max_per_pipe_ib = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB); perf->core_clk_rate = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_CLK); SDE_DEBUG("crtc=%d clk_rate=%u ib=%llu ab=%llu\n", crtc->base.id, perf->core_clk_rate, perf->max_per_pipe_ib, perf->bw_ctl); } int sde_core_perf_crtc_check(struct drm_crtc *crtc, int sde_core_perf_crtc_check(struct drm_crtc *crtc, struct drm_crtc_state *state) struct drm_crtc_state *state) { { Loading Loading @@ -102,7 +127,11 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, sde_cstate = to_sde_crtc_state(state); sde_cstate = to_sde_crtc_state(state); bw_sum_of_intfs = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB); /* swap state and obtain new values */ sde_cstate->cur_perf = sde_cstate->new_perf; _sde_core_perf_calc_crtc(crtc, state, &sde_cstate->new_perf); bw_sum_of_intfs = sde_cstate->new_perf.bw_ctl; drm_for_each_crtc(tmp_crtc, crtc->dev) { drm_for_each_crtc(tmp_crtc, crtc->dev) { if (_sde_core_perf_crtc_is_power_on(tmp_crtc) && if (_sde_core_perf_crtc_is_power_on(tmp_crtc) && Loading @@ -110,7 +139,7 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, struct sde_crtc_state *tmp_cstate = struct sde_crtc_state *tmp_cstate = to_sde_crtc_state(tmp_crtc->state); to_sde_crtc_state(tmp_crtc->state); bw_sum_of_intfs += tmp_cstate->cur_perf.bw_ctl; bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; } } } } Loading @@ -126,11 +155,11 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, SDE_DEBUG("final threshold bw limit = %d\n", threshold); SDE_DEBUG("final threshold bw limit = %d\n", threshold); if (!threshold) { if (!threshold) { sde_cstate->cur_perf.bw_ctl = 0; sde_cstate->new_perf = sde_cstate->cur_perf; SDE_ERROR("no bandwidth limits specified\n"); SDE_ERROR("no bandwidth limits specified\n"); return -E2BIG; return -E2BIG; } else if (bw > threshold) { } else if (bw > threshold) { sde_cstate->cur_perf.bw_ctl = 0; sde_cstate->new_perf = sde_cstate->cur_perf; SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); SDE_DEBUG("exceeds bandwidth: %ukb > %ukb\n", bw, threshold); return -E2BIG; return -E2BIG; } } Loading @@ -138,26 +167,6 @@ int sde_core_perf_crtc_check(struct drm_crtc *crtc, return 0; return 0; } } static void _sde_core_perf_calc_crtc(struct sde_kms *kms, struct drm_crtc *crtc, struct sde_core_perf_params *perf) { struct sde_crtc_state *sde_cstate; sde_cstate = to_sde_crtc_state(crtc->state); memset(perf, 0, sizeof(struct sde_core_perf_params)); perf->bw_ctl = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_AB); perf->max_per_pipe_ib = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_IB); perf->core_clk_rate = sde_crtc_get_property(sde_cstate, CRTC_PROP_CORE_CLK); SDE_DEBUG("crtc=%d clk_rate=%u ib=%llu ab=%llu\n", crtc->base.id, perf->core_clk_rate, perf->max_per_pipe_ib, perf->bw_ctl); } static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, struct drm_crtc *crtc, struct sde_core_perf_params *perf, struct drm_crtc *crtc, struct sde_core_perf_params *perf, bool nrt_client, u32 core_clk) bool nrt_client, u32 core_clk) Loading @@ -175,13 +184,13 @@ static u64 _sde_core_perf_crtc_calc_client_vote(struct sde_kms *kms, to_sde_crtc_state(tmp_crtc->state); 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); sde_cstate->new_perf.max_per_pipe_ib); bw_sum_of_intfs += sde_cstate->cur_perf.bw_ctl; bw_sum_of_intfs += sde_cstate->new_perf.bw_ctl; SDE_DEBUG("crtc=%d bw=%llu\n", SDE_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id, tmp_crtc->base.id, sde_cstate->cur_perf.bw_ctl); sde_cstate->new_perf.bw_ctl); } } } } Loading Loading @@ -308,7 +317,7 @@ static u32 _sde_core_perf_get_core_clk_rate(struct sde_kms *kms) drm_for_each_crtc(crtc, kms->dev) { drm_for_each_crtc(crtc, kms->dev) { if (_sde_core_perf_crtc_is_power_on(crtc)) { if (_sde_core_perf_crtc_is_power_on(crtc)) { sde_cstate = to_sde_crtc_state(crtc->state); sde_cstate = to_sde_crtc_state(crtc->state); clk_rate = max(sde_cstate->cur_perf.core_clk_rate, clk_rate = max(sde_cstate->new_perf.core_clk_rate, clk_rate); clk_rate); clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate); clk_rate = clk_round_rate(kms->perf.core_clk, clk_rate); } } Loading Loading @@ -357,9 +366,6 @@ void sde_core_perf_crtc_update(struct drm_crtc *crtc, new = &sde_cstate->new_perf; new = &sde_cstate->new_perf; if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) { if (_sde_core_perf_crtc_is_power_on(crtc) && !stop_req) { if (params_changed) _sde_core_perf_calc_crtc(kms, crtc, new); /* /* * cases for bus bandwidth update. * cases for bus bandwidth update. * 1. new bandwidth vote or writeback output vote * 1. new bandwidth vote or writeback output vote Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +6 −1 Original line number Original line Diff line number Diff line Loading @@ -473,6 +473,7 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) struct sde_crtc_frame_event *fevent; struct sde_crtc_frame_event *fevent; struct drm_crtc *crtc; struct drm_crtc *crtc; struct sde_crtc *sde_crtc; struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; struct sde_kms *sde_kms; struct sde_kms *sde_kms; unsigned long flags; unsigned long flags; Loading @@ -482,13 +483,14 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) } } fevent = container_of(work, struct sde_crtc_frame_event, work); fevent = container_of(work, struct sde_crtc_frame_event, work); if (!fevent->crtc) { if (!fevent->crtc || !fevent->crtc->state) { SDE_ERROR("invalid crtc\n"); SDE_ERROR("invalid crtc\n"); return; return; } } crtc = fevent->crtc; crtc = fevent->crtc; sde_crtc = to_sde_crtc(crtc); sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(crtc->state); sde_kms = _sde_crtc_get_kms(crtc); sde_kms = _sde_crtc_get_kms(crtc); if (!sde_kms) { if (!sde_kms) { Loading Loading @@ -522,6 +524,9 @@ static void sde_crtc_frame_event_work(struct kthread_work *work) } else { } else { SDE_EVT32(DRMID(crtc), fevent->event, 2); SDE_EVT32(DRMID(crtc), fevent->event, 2); } } if (fevent->event == SDE_ENCODER_FRAME_EVENT_DONE) sde_core_perf_crtc_update(crtc, 0, false); } else { } else { SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id, SDE_ERROR("crtc%d ts:%lld unknown event %u\n", crtc->base.id, ktime_to_ns(fevent->ts), ktime_to_ns(fevent->ts), Loading