Skip to content

Commit 8b0379a

Browse files
hersen wualexdeucher
authored andcommitted
drm/amd/display: dchubbub p-state warning during surface planes switch
[Why] ramp_up_dispclk_with_dpp is to change dispclk, dppclk and dprefclk according to bandwidth requirement. call stack: rv1_update_clocks --> update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth --> prepare_bandwidth / optimize_bandwidth. before change dcn hw, prepare_bandwidth will be called first to allow enough clock, watermark for change, after end of dcn hw change, optimize_bandwidth is executed to lower clock to save power for new dcn hw settings. below is sequence of commit_planes_for_stream: step 1: prepare_bandwidth - raise clock to have enough bandwidth step 2: lock_doublebuffer_enable step 3: pipe_control_lock(true) - make dchubp register change will not take effect right way step 4: apply_ctx_for_surface - program dchubp step 5: pipe_control_lock(false) - dchubp register change take effect step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream for full_date, optimize clock to save power at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be changed for new dchubp configuration. but real dcn hub dchubps are still running with old configuration until end of step 5. this need clocks settings at step 1 should not less than that before step 1. this is checked by two conditions: 1. if (should_set_clock(safe_to_lower , new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) 2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz the second condition is based on new dchubp configuration. dppclk for new dchubp may be different from dppclk before step 1. for example, before step 1, dchubps are as below: pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979) pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080) for dppclk for pipe0 need dppclk = dispclk new dchubp pipe split configuration: pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080) pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080) dppclk only needs dppclk = dispclk /2. dispclk, dppclk are not lock by otg master lock. they take effect after step 1. during this transition, dispclk are the same, but dppclk is changed to half of previous clock for old dchubp configuration between step 1 and step 6. This may cause p-state warning intermittently. [How] for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we need make sure dppclk are not changed to less between step 1 and 6. for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz, new display clock is raised, but we do not know ratio of new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz, new_clocks->dispclk_khz /2 does not guarantee equal or higher than old dppclk. we could ignore power saving different between dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6. as long as safe_to_lower = false, set dpclk = dispclk to simplify condition check. CC: Stable <[email protected]> Signed-off-by: Hersen Wu <[email protected]> Reviewed-by: Aric Cyr <[email protected]> Acked-by: Eryk Brol <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 471c1dd commit 8b0379a

File tree

1 file changed

+67
-2
lines changed

1 file changed

+67
-2
lines changed

drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,77 @@ static int rv1_determine_dppclk_threshold(struct clk_mgr_internal *clk_mgr, stru
8585
return disp_clk_threshold;
8686
}
8787

88-
static void ramp_up_dispclk_with_dpp(struct clk_mgr_internal *clk_mgr, struct dc *dc, struct dc_clocks *new_clocks)
88+
static void ramp_up_dispclk_with_dpp(
89+
struct clk_mgr_internal *clk_mgr,
90+
struct dc *dc,
91+
struct dc_clocks *new_clocks,
92+
bool safe_to_lower)
8993
{
9094
int i;
9195
int dispclk_to_dpp_threshold = rv1_determine_dppclk_threshold(clk_mgr, new_clocks);
9296
bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz;
9397

98+
/* this function is to change dispclk, dppclk and dprefclk according to
99+
* bandwidth requirement. Its call stack is rv1_update_clocks -->
100+
* update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth
101+
* --> prepare_bandwidth / optimize_bandwidth. before change dcn hw,
102+
* prepare_bandwidth will be called first to allow enough clock,
103+
* watermark for change, after end of dcn hw change, optimize_bandwidth
104+
* is executed to lower clock to save power for new dcn hw settings.
105+
*
106+
* below is sequence of commit_planes_for_stream:
107+
*
108+
* step 1: prepare_bandwidth - raise clock to have enough bandwidth
109+
* step 2: lock_doublebuffer_enable
110+
* step 3: pipe_control_lock(true) - make dchubp register change will
111+
* not take effect right way
112+
* step 4: apply_ctx_for_surface - program dchubp
113+
* step 5: pipe_control_lock(false) - dchubp register change take effect
114+
* step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream
115+
* for full_date, optimize clock to save power
116+
*
117+
* at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be
118+
* changed for new dchubp configuration. but real dcn hub dchubps are
119+
* still running with old configuration until end of step 5. this need
120+
* clocks settings at step 1 should not less than that before step 1.
121+
* this is checked by two conditions: 1. if (should_set_clock(safe_to_lower
122+
* , new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) ||
123+
* new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz)
124+
* 2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz
125+
*
126+
* the second condition is based on new dchubp configuration. dppclk
127+
* for new dchubp may be different from dppclk before step 1.
128+
* for example, before step 1, dchubps are as below:
129+
* pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979)
130+
* pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080)
131+
* for dppclk for pipe0 need dppclk = dispclk
132+
*
133+
* new dchubp pipe split configuration:
134+
* pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080)
135+
* pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080)
136+
* dppclk only needs dppclk = dispclk /2.
137+
*
138+
* dispclk, dppclk are not lock by otg master lock. they take effect
139+
* after step 1. during this transition, dispclk are the same, but
140+
* dppclk is changed to half of previous clock for old dchubp
141+
* configuration between step 1 and step 6. This may cause p-state
142+
* warning intermittently.
143+
*
144+
* for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we
145+
* need make sure dppclk are not changed to less between step 1 and 6.
146+
* for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz,
147+
* new display clock is raised, but we do not know ratio of
148+
* new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz,
149+
* new_clocks->dispclk_khz /2 does not guarantee equal or higher than
150+
* old dppclk. we could ignore power saving different between
151+
* dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6.
152+
* as long as safe_to_lower = false, set dpclk = dispclk to simplify
153+
* condition check.
154+
* todo: review this change for other asic.
155+
**/
156+
if (!safe_to_lower)
157+
request_dpp_div = false;
158+
94159
/* set disp clk to dpp clk threshold */
95160

96161
clk_mgr->funcs->set_dispclk(clk_mgr, dispclk_to_dpp_threshold);
@@ -209,7 +274,7 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base,
209274
/* program dispclk on = as a w/a for sleep resume clock ramping issues */
210275
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)
211276
|| new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) {
212-
ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks);
277+
ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks, safe_to_lower);
213278
clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
214279
send_request_to_lower = true;
215280
}

0 commit comments

Comments
 (0)