2 * Copyright 2016 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
27 #include <linux/delay.h>
28 #include "dcn30/dcn30_hubbub.h"
29 #include "dcn31_hubbub.h"
30 #include "dm_services.h"
31 #include "reg_helper.h"
37 hubbub2->base.ctx->logger
42 #define FN(reg_name, field_name) \
43 hubbub2->shifts->field_name, hubbub2->masks->field_name
50 #define DCN31_CRB_SEGMENT_SIZE_KB 64
52 static void dcn31_init_crb(struct hubbub
*hubbub
)
54 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
56 REG_GET(DCHUBBUB_DET0_CTRL
, DET0_SIZE_CURRENT
,
59 REG_GET(DCHUBBUB_DET1_CTRL
, DET1_SIZE_CURRENT
,
62 REG_GET(DCHUBBUB_DET2_CTRL
, DET2_SIZE_CURRENT
,
65 REG_GET(DCHUBBUB_DET3_CTRL
, DET3_SIZE_CURRENT
,
68 REG_GET(DCHUBBUB_COMPBUF_CTRL
, COMPBUF_SIZE_CURRENT
,
69 &hubbub2
->compbuf_size_segments
);
71 REG_SET_2(COMPBUF_RESERVED_SPACE
, 0,
72 COMPBUF_RESERVED_SPACE_64B
, hubbub2
->pixel_chunk_size
/ 32,
73 COMPBUF_RESERVED_SPACE_ZS
, hubbub2
->pixel_chunk_size
/ 128);
74 REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0
, DET_DEPTH
, 0x17F);
77 static void dcn31_program_det_size(struct hubbub
*hubbub
, int hubp_inst
, unsigned int det_buffer_size_in_kbyte
)
79 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
81 unsigned int det_size_segments
= (det_buffer_size_in_kbyte
+ DCN31_CRB_SEGMENT_SIZE_KB
- 1) / DCN31_CRB_SEGMENT_SIZE_KB
;
85 REG_UPDATE(DCHUBBUB_DET0_CTRL
,
86 DET0_SIZE
, det_size_segments
);
87 hubbub2
->det0_size
= det_size_segments
;
90 REG_UPDATE(DCHUBBUB_DET1_CTRL
,
91 DET1_SIZE
, det_size_segments
);
92 hubbub2
->det1_size
= det_size_segments
;
95 REG_UPDATE(DCHUBBUB_DET2_CTRL
,
96 DET2_SIZE
, det_size_segments
);
97 hubbub2
->det2_size
= det_size_segments
;
100 REG_UPDATE(DCHUBBUB_DET3_CTRL
,
101 DET3_SIZE
, det_size_segments
);
102 hubbub2
->det3_size
= det_size_segments
;
107 /* Should never be hit, if it is we have an erroneous hw config*/
108 ASSERT(hubbub2
->det0_size
+ hubbub2
->det1_size
+ hubbub2
->det2_size
109 + hubbub2
->det3_size
+ hubbub2
->compbuf_size_segments
<= hubbub2
->crb_size_segs
);
112 static void dcn31_program_compbuf_size(struct hubbub
*hubbub
, unsigned int compbuf_size_kb
, bool safe_to_increase
)
114 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
115 unsigned int compbuf_size_segments
= (compbuf_size_kb
+ DCN31_CRB_SEGMENT_SIZE_KB
- 1) / DCN31_CRB_SEGMENT_SIZE_KB
;
117 if (safe_to_increase
|| compbuf_size_segments
<= hubbub2
->compbuf_size_segments
) {
118 if (compbuf_size_segments
> hubbub2
->compbuf_size_segments
) {
119 REG_WAIT(DCHUBBUB_DET0_CTRL
, DET0_SIZE_CURRENT
, hubbub2
->det0_size
, 1, 100);
120 REG_WAIT(DCHUBBUB_DET1_CTRL
, DET1_SIZE_CURRENT
, hubbub2
->det1_size
, 1, 100);
121 REG_WAIT(DCHUBBUB_DET2_CTRL
, DET2_SIZE_CURRENT
, hubbub2
->det2_size
, 1, 100);
122 REG_WAIT(DCHUBBUB_DET3_CTRL
, DET3_SIZE_CURRENT
, hubbub2
->det3_size
, 1, 100);
124 /* Should never be hit, if it is we have an erroneous hw config*/
125 ASSERT(hubbub2
->det0_size
+ hubbub2
->det1_size
+ hubbub2
->det2_size
126 + hubbub2
->det3_size
+ compbuf_size_segments
<= hubbub2
->crb_size_segs
);
127 REG_UPDATE(DCHUBBUB_COMPBUF_CTRL
, COMPBUF_SIZE
, compbuf_size_segments
);
128 hubbub2
->compbuf_size_segments
= compbuf_size_segments
;
129 ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL
, CONFIG_ERROR
, &compbuf_size_segments
) && !compbuf_size_segments
);
133 static uint32_t convert_and_clamp(
136 uint32_t clamp_value
)
138 uint32_t ret_val
= 0;
139 ret_val
= wm_ns
* refclk_mhz
;
142 if (ret_val
> clamp_value
) {
143 /* clamping WMs is abnormal, unexpected and may lead to underflow*/
145 ret_val
= clamp_value
;
151 static bool hubbub31_program_urgent_watermarks(
152 struct hubbub
*hubbub
,
153 struct dcn_watermark_set
*watermarks
,
154 unsigned int refclk_mhz
,
157 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
158 uint32_t prog_wm_value
;
159 bool wm_pending
= false;
161 /* Repeat for water mark set A, B, C and D. */
163 if (safe_to_lower
|| watermarks
->a
.urgent_ns
> hubbub2
->watermarks
.a
.urgent_ns
) {
164 hubbub2
->watermarks
.a
.urgent_ns
= watermarks
->a
.urgent_ns
;
165 prog_wm_value
= convert_and_clamp(watermarks
->a
.urgent_ns
,
167 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A
, 0,
168 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A
, prog_wm_value
);
170 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
171 "HW register value = 0x%x\n",
172 watermarks
->a
.urgent_ns
, prog_wm_value
);
173 } else if (watermarks
->a
.urgent_ns
< hubbub2
->watermarks
.a
.urgent_ns
)
176 /* determine the transfer time for a quantity of data for a particular requestor.*/
177 if (safe_to_lower
|| watermarks
->a
.frac_urg_bw_flip
178 > hubbub2
->watermarks
.a
.frac_urg_bw_flip
) {
179 hubbub2
->watermarks
.a
.frac_urg_bw_flip
= watermarks
->a
.frac_urg_bw_flip
;
181 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A
, 0,
182 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A
, watermarks
->a
.frac_urg_bw_flip
);
183 } else if (watermarks
->a
.frac_urg_bw_flip
184 < hubbub2
->watermarks
.a
.frac_urg_bw_flip
)
187 if (safe_to_lower
|| watermarks
->a
.frac_urg_bw_nom
188 > hubbub2
->watermarks
.a
.frac_urg_bw_nom
) {
189 hubbub2
->watermarks
.a
.frac_urg_bw_nom
= watermarks
->a
.frac_urg_bw_nom
;
191 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A
, 0,
192 DCHUBBUB_ARB_FRAC_URG_BW_NOM_A
, watermarks
->a
.frac_urg_bw_nom
);
193 } else if (watermarks
->a
.frac_urg_bw_nom
194 < hubbub2
->watermarks
.a
.frac_urg_bw_nom
)
197 if (safe_to_lower
|| watermarks
->a
.urgent_latency_ns
> hubbub2
->watermarks
.a
.urgent_latency_ns
) {
198 hubbub2
->watermarks
.a
.urgent_latency_ns
= watermarks
->a
.urgent_latency_ns
;
199 prog_wm_value
= convert_and_clamp(watermarks
->a
.urgent_latency_ns
,
201 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A
, 0,
202 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A
, prog_wm_value
);
203 } else if (watermarks
->a
.urgent_latency_ns
< hubbub2
->watermarks
.a
.urgent_latency_ns
)
207 if (safe_to_lower
|| watermarks
->b
.urgent_ns
> hubbub2
->watermarks
.b
.urgent_ns
) {
208 hubbub2
->watermarks
.b
.urgent_ns
= watermarks
->b
.urgent_ns
;
209 prog_wm_value
= convert_and_clamp(watermarks
->b
.urgent_ns
,
211 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B
, 0,
212 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B
, prog_wm_value
);
214 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
215 "HW register value = 0x%x\n",
216 watermarks
->b
.urgent_ns
, prog_wm_value
);
217 } else if (watermarks
->b
.urgent_ns
< hubbub2
->watermarks
.b
.urgent_ns
)
220 /* determine the transfer time for a quantity of data for a particular requestor.*/
221 if (safe_to_lower
|| watermarks
->b
.frac_urg_bw_flip
222 > hubbub2
->watermarks
.b
.frac_urg_bw_flip
) {
223 hubbub2
->watermarks
.b
.frac_urg_bw_flip
= watermarks
->b
.frac_urg_bw_flip
;
225 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B
, 0,
226 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B
, watermarks
->b
.frac_urg_bw_flip
);
227 } else if (watermarks
->b
.frac_urg_bw_flip
228 < hubbub2
->watermarks
.b
.frac_urg_bw_flip
)
231 if (safe_to_lower
|| watermarks
->b
.frac_urg_bw_nom
232 > hubbub2
->watermarks
.b
.frac_urg_bw_nom
) {
233 hubbub2
->watermarks
.b
.frac_urg_bw_nom
= watermarks
->b
.frac_urg_bw_nom
;
235 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B
, 0,
236 DCHUBBUB_ARB_FRAC_URG_BW_NOM_B
, watermarks
->b
.frac_urg_bw_nom
);
237 } else if (watermarks
->b
.frac_urg_bw_nom
238 < hubbub2
->watermarks
.b
.frac_urg_bw_nom
)
241 if (safe_to_lower
|| watermarks
->b
.urgent_latency_ns
> hubbub2
->watermarks
.b
.urgent_latency_ns
) {
242 hubbub2
->watermarks
.b
.urgent_latency_ns
= watermarks
->b
.urgent_latency_ns
;
243 prog_wm_value
= convert_and_clamp(watermarks
->b
.urgent_latency_ns
,
245 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B
, 0,
246 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B
, prog_wm_value
);
247 } else if (watermarks
->b
.urgent_latency_ns
< hubbub2
->watermarks
.b
.urgent_latency_ns
)
251 if (safe_to_lower
|| watermarks
->c
.urgent_ns
> hubbub2
->watermarks
.c
.urgent_ns
) {
252 hubbub2
->watermarks
.c
.urgent_ns
= watermarks
->c
.urgent_ns
;
253 prog_wm_value
= convert_and_clamp(watermarks
->c
.urgent_ns
,
255 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C
, 0,
256 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C
, prog_wm_value
);
258 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
259 "HW register value = 0x%x\n",
260 watermarks
->c
.urgent_ns
, prog_wm_value
);
261 } else if (watermarks
->c
.urgent_ns
< hubbub2
->watermarks
.c
.urgent_ns
)
264 /* determine the transfer time for a quantity of data for a particular requestor.*/
265 if (safe_to_lower
|| watermarks
->c
.frac_urg_bw_flip
266 > hubbub2
->watermarks
.c
.frac_urg_bw_flip
) {
267 hubbub2
->watermarks
.c
.frac_urg_bw_flip
= watermarks
->c
.frac_urg_bw_flip
;
269 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C
, 0,
270 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C
, watermarks
->c
.frac_urg_bw_flip
);
271 } else if (watermarks
->c
.frac_urg_bw_flip
272 < hubbub2
->watermarks
.c
.frac_urg_bw_flip
)
275 if (safe_to_lower
|| watermarks
->c
.frac_urg_bw_nom
276 > hubbub2
->watermarks
.c
.frac_urg_bw_nom
) {
277 hubbub2
->watermarks
.c
.frac_urg_bw_nom
= watermarks
->c
.frac_urg_bw_nom
;
279 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C
, 0,
280 DCHUBBUB_ARB_FRAC_URG_BW_NOM_C
, watermarks
->c
.frac_urg_bw_nom
);
281 } else if (watermarks
->c
.frac_urg_bw_nom
282 < hubbub2
->watermarks
.c
.frac_urg_bw_nom
)
285 if (safe_to_lower
|| watermarks
->c
.urgent_latency_ns
> hubbub2
->watermarks
.c
.urgent_latency_ns
) {
286 hubbub2
->watermarks
.c
.urgent_latency_ns
= watermarks
->c
.urgent_latency_ns
;
287 prog_wm_value
= convert_and_clamp(watermarks
->c
.urgent_latency_ns
,
289 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C
, 0,
290 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C
, prog_wm_value
);
291 } else if (watermarks
->c
.urgent_latency_ns
< hubbub2
->watermarks
.c
.urgent_latency_ns
)
295 if (safe_to_lower
|| watermarks
->d
.urgent_ns
> hubbub2
->watermarks
.d
.urgent_ns
) {
296 hubbub2
->watermarks
.d
.urgent_ns
= watermarks
->d
.urgent_ns
;
297 prog_wm_value
= convert_and_clamp(watermarks
->d
.urgent_ns
,
299 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D
, 0,
300 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D
, prog_wm_value
);
302 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
303 "HW register value = 0x%x\n",
304 watermarks
->d
.urgent_ns
, prog_wm_value
);
305 } else if (watermarks
->d
.urgent_ns
< hubbub2
->watermarks
.d
.urgent_ns
)
308 /* determine the transfer time for a quantity of data for a particular requestor.*/
309 if (safe_to_lower
|| watermarks
->d
.frac_urg_bw_flip
310 > hubbub2
->watermarks
.d
.frac_urg_bw_flip
) {
311 hubbub2
->watermarks
.d
.frac_urg_bw_flip
= watermarks
->d
.frac_urg_bw_flip
;
313 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D
, 0,
314 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D
, watermarks
->d
.frac_urg_bw_flip
);
315 } else if (watermarks
->d
.frac_urg_bw_flip
316 < hubbub2
->watermarks
.d
.frac_urg_bw_flip
)
319 if (safe_to_lower
|| watermarks
->d
.frac_urg_bw_nom
320 > hubbub2
->watermarks
.d
.frac_urg_bw_nom
) {
321 hubbub2
->watermarks
.d
.frac_urg_bw_nom
= watermarks
->d
.frac_urg_bw_nom
;
323 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D
, 0,
324 DCHUBBUB_ARB_FRAC_URG_BW_NOM_D
, watermarks
->d
.frac_urg_bw_nom
);
325 } else if (watermarks
->d
.frac_urg_bw_nom
326 < hubbub2
->watermarks
.d
.frac_urg_bw_nom
)
329 if (safe_to_lower
|| watermarks
->d
.urgent_latency_ns
> hubbub2
->watermarks
.d
.urgent_latency_ns
) {
330 hubbub2
->watermarks
.d
.urgent_latency_ns
= watermarks
->d
.urgent_latency_ns
;
331 prog_wm_value
= convert_and_clamp(watermarks
->d
.urgent_latency_ns
,
333 REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D
, 0,
334 DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D
, prog_wm_value
);
335 } else if (watermarks
->d
.urgent_latency_ns
< hubbub2
->watermarks
.d
.urgent_latency_ns
)
341 static bool hubbub31_program_stutter_watermarks(
342 struct hubbub
*hubbub
,
343 struct dcn_watermark_set
*watermarks
,
344 unsigned int refclk_mhz
,
347 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
348 uint32_t prog_wm_value
;
349 bool wm_pending
= false;
352 if (safe_to_lower
|| watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_ns
353 > hubbub2
->watermarks
.a
.cstate_pstate
.cstate_enter_plus_exit_ns
) {
354 hubbub2
->watermarks
.a
.cstate_pstate
.cstate_enter_plus_exit_ns
=
355 watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_ns
;
356 prog_wm_value
= convert_and_clamp(
357 watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_ns
,
359 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A
, 0,
360 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A
, prog_wm_value
);
361 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
362 "HW register value = 0x%x\n",
363 watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_ns
, prog_wm_value
);
364 } else if (watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_ns
365 < hubbub2
->watermarks
.a
.cstate_pstate
.cstate_enter_plus_exit_ns
)
368 if (safe_to_lower
|| watermarks
->a
.cstate_pstate
.cstate_exit_ns
369 > hubbub2
->watermarks
.a
.cstate_pstate
.cstate_exit_ns
) {
370 hubbub2
->watermarks
.a
.cstate_pstate
.cstate_exit_ns
=
371 watermarks
->a
.cstate_pstate
.cstate_exit_ns
;
372 prog_wm_value
= convert_and_clamp(
373 watermarks
->a
.cstate_pstate
.cstate_exit_ns
,
375 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A
, 0,
376 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A
, prog_wm_value
);
377 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
378 "HW register value = 0x%x\n",
379 watermarks
->a
.cstate_pstate
.cstate_exit_ns
, prog_wm_value
);
380 } else if (watermarks
->a
.cstate_pstate
.cstate_exit_ns
381 < hubbub2
->watermarks
.a
.cstate_pstate
.cstate_exit_ns
)
384 if (safe_to_lower
|| watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
385 > hubbub2
->watermarks
.a
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
) {
386 hubbub2
->watermarks
.a
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
=
387 watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
;
388 prog_wm_value
= convert_and_clamp(
389 watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
,
391 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A
, 0,
392 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A
, prog_wm_value
);
393 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n"
394 "HW register value = 0x%x\n",
395 watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
, prog_wm_value
);
396 } else if (watermarks
->a
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
397 < hubbub2
->watermarks
.a
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
)
400 if (safe_to_lower
|| watermarks
->a
.cstate_pstate
.cstate_exit_z8_ns
401 > hubbub2
->watermarks
.a
.cstate_pstate
.cstate_exit_z8_ns
) {
402 hubbub2
->watermarks
.a
.cstate_pstate
.cstate_exit_z8_ns
=
403 watermarks
->a
.cstate_pstate
.cstate_exit_z8_ns
;
404 prog_wm_value
= convert_and_clamp(
405 watermarks
->a
.cstate_pstate
.cstate_exit_z8_ns
,
407 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A
, 0,
408 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A
, prog_wm_value
);
409 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n"
410 "HW register value = 0x%x\n",
411 watermarks
->a
.cstate_pstate
.cstate_exit_z8_ns
, prog_wm_value
);
412 } else if (watermarks
->a
.cstate_pstate
.cstate_exit_z8_ns
413 < hubbub2
->watermarks
.a
.cstate_pstate
.cstate_exit_z8_ns
)
417 if (safe_to_lower
|| watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_ns
418 > hubbub2
->watermarks
.b
.cstate_pstate
.cstate_enter_plus_exit_ns
) {
419 hubbub2
->watermarks
.b
.cstate_pstate
.cstate_enter_plus_exit_ns
=
420 watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_ns
;
421 prog_wm_value
= convert_and_clamp(
422 watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_ns
,
424 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B
, 0,
425 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B
, prog_wm_value
);
426 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
427 "HW register value = 0x%x\n",
428 watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_ns
, prog_wm_value
);
429 } else if (watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_ns
430 < hubbub2
->watermarks
.b
.cstate_pstate
.cstate_enter_plus_exit_ns
)
433 if (safe_to_lower
|| watermarks
->b
.cstate_pstate
.cstate_exit_ns
434 > hubbub2
->watermarks
.b
.cstate_pstate
.cstate_exit_ns
) {
435 hubbub2
->watermarks
.b
.cstate_pstate
.cstate_exit_ns
=
436 watermarks
->b
.cstate_pstate
.cstate_exit_ns
;
437 prog_wm_value
= convert_and_clamp(
438 watermarks
->b
.cstate_pstate
.cstate_exit_ns
,
440 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B
, 0,
441 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B
, prog_wm_value
);
442 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
443 "HW register value = 0x%x\n",
444 watermarks
->b
.cstate_pstate
.cstate_exit_ns
, prog_wm_value
);
445 } else if (watermarks
->b
.cstate_pstate
.cstate_exit_ns
446 < hubbub2
->watermarks
.b
.cstate_pstate
.cstate_exit_ns
)
449 if (safe_to_lower
|| watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
450 > hubbub2
->watermarks
.b
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
) {
451 hubbub2
->watermarks
.b
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
=
452 watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
;
453 prog_wm_value
= convert_and_clamp(
454 watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
,
456 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B
, 0,
457 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B
, prog_wm_value
);
458 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n"
459 "HW register value = 0x%x\n",
460 watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
, prog_wm_value
);
461 } else if (watermarks
->b
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
462 < hubbub2
->watermarks
.b
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
)
465 if (safe_to_lower
|| watermarks
->b
.cstate_pstate
.cstate_exit_z8_ns
466 > hubbub2
->watermarks
.b
.cstate_pstate
.cstate_exit_z8_ns
) {
467 hubbub2
->watermarks
.b
.cstate_pstate
.cstate_exit_z8_ns
=
468 watermarks
->b
.cstate_pstate
.cstate_exit_z8_ns
;
469 prog_wm_value
= convert_and_clamp(
470 watermarks
->b
.cstate_pstate
.cstate_exit_z8_ns
,
472 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B
, 0,
473 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B
, prog_wm_value
);
474 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n"
475 "HW register value = 0x%x\n",
476 watermarks
->b
.cstate_pstate
.cstate_exit_z8_ns
, prog_wm_value
);
477 } else if (watermarks
->b
.cstate_pstate
.cstate_exit_z8_ns
478 < hubbub2
->watermarks
.b
.cstate_pstate
.cstate_exit_z8_ns
)
482 if (safe_to_lower
|| watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_ns
483 > hubbub2
->watermarks
.c
.cstate_pstate
.cstate_enter_plus_exit_ns
) {
484 hubbub2
->watermarks
.c
.cstate_pstate
.cstate_enter_plus_exit_ns
=
485 watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_ns
;
486 prog_wm_value
= convert_and_clamp(
487 watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_ns
,
489 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C
, 0,
490 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C
, prog_wm_value
);
491 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
492 "HW register value = 0x%x\n",
493 watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_ns
, prog_wm_value
);
494 } else if (watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_ns
495 < hubbub2
->watermarks
.c
.cstate_pstate
.cstate_enter_plus_exit_ns
)
498 if (safe_to_lower
|| watermarks
->c
.cstate_pstate
.cstate_exit_ns
499 > hubbub2
->watermarks
.c
.cstate_pstate
.cstate_exit_ns
) {
500 hubbub2
->watermarks
.c
.cstate_pstate
.cstate_exit_ns
=
501 watermarks
->c
.cstate_pstate
.cstate_exit_ns
;
502 prog_wm_value
= convert_and_clamp(
503 watermarks
->c
.cstate_pstate
.cstate_exit_ns
,
505 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C
, 0,
506 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C
, prog_wm_value
);
507 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
508 "HW register value = 0x%x\n",
509 watermarks
->c
.cstate_pstate
.cstate_exit_ns
, prog_wm_value
);
510 } else if (watermarks
->c
.cstate_pstate
.cstate_exit_ns
511 < hubbub2
->watermarks
.c
.cstate_pstate
.cstate_exit_ns
)
514 if (safe_to_lower
|| watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
515 > hubbub2
->watermarks
.c
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
) {
516 hubbub2
->watermarks
.c
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
=
517 watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
;
518 prog_wm_value
= convert_and_clamp(
519 watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
,
521 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C
, 0,
522 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C
, prog_wm_value
);
523 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n"
524 "HW register value = 0x%x\n",
525 watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
, prog_wm_value
);
526 } else if (watermarks
->c
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
527 < hubbub2
->watermarks
.c
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
)
530 if (safe_to_lower
|| watermarks
->c
.cstate_pstate
.cstate_exit_z8_ns
531 > hubbub2
->watermarks
.c
.cstate_pstate
.cstate_exit_z8_ns
) {
532 hubbub2
->watermarks
.c
.cstate_pstate
.cstate_exit_z8_ns
=
533 watermarks
->c
.cstate_pstate
.cstate_exit_z8_ns
;
534 prog_wm_value
= convert_and_clamp(
535 watermarks
->c
.cstate_pstate
.cstate_exit_z8_ns
,
537 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C
, 0,
538 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C
, prog_wm_value
);
539 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n"
540 "HW register value = 0x%x\n",
541 watermarks
->c
.cstate_pstate
.cstate_exit_z8_ns
, prog_wm_value
);
542 } else if (watermarks
->c
.cstate_pstate
.cstate_exit_z8_ns
543 < hubbub2
->watermarks
.c
.cstate_pstate
.cstate_exit_z8_ns
)
547 if (safe_to_lower
|| watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_ns
548 > hubbub2
->watermarks
.d
.cstate_pstate
.cstate_enter_plus_exit_ns
) {
549 hubbub2
->watermarks
.d
.cstate_pstate
.cstate_enter_plus_exit_ns
=
550 watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_ns
;
551 prog_wm_value
= convert_and_clamp(
552 watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_ns
,
554 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D
, 0,
555 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D
, prog_wm_value
);
556 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
557 "HW register value = 0x%x\n",
558 watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_ns
, prog_wm_value
);
559 } else if (watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_ns
560 < hubbub2
->watermarks
.d
.cstate_pstate
.cstate_enter_plus_exit_ns
)
563 if (safe_to_lower
|| watermarks
->d
.cstate_pstate
.cstate_exit_ns
564 > hubbub2
->watermarks
.d
.cstate_pstate
.cstate_exit_ns
) {
565 hubbub2
->watermarks
.d
.cstate_pstate
.cstate_exit_ns
=
566 watermarks
->d
.cstate_pstate
.cstate_exit_ns
;
567 prog_wm_value
= convert_and_clamp(
568 watermarks
->d
.cstate_pstate
.cstate_exit_ns
,
570 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D
, 0,
571 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D
, prog_wm_value
);
572 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
573 "HW register value = 0x%x\n",
574 watermarks
->d
.cstate_pstate
.cstate_exit_ns
, prog_wm_value
);
575 } else if (watermarks
->d
.cstate_pstate
.cstate_exit_ns
576 < hubbub2
->watermarks
.d
.cstate_pstate
.cstate_exit_ns
)
579 if (safe_to_lower
|| watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
580 > hubbub2
->watermarks
.d
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
) {
581 hubbub2
->watermarks
.d
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
=
582 watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
;
583 prog_wm_value
= convert_and_clamp(
584 watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
,
586 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D
, 0,
587 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D
, prog_wm_value
);
588 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n"
589 "HW register value = 0x%x\n",
590 watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
, prog_wm_value
);
591 } else if (watermarks
->d
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
592 < hubbub2
->watermarks
.d
.cstate_pstate
.cstate_enter_plus_exit_z8_ns
)
595 if (safe_to_lower
|| watermarks
->d
.cstate_pstate
.cstate_exit_z8_ns
596 > hubbub2
->watermarks
.d
.cstate_pstate
.cstate_exit_z8_ns
) {
597 hubbub2
->watermarks
.d
.cstate_pstate
.cstate_exit_z8_ns
=
598 watermarks
->d
.cstate_pstate
.cstate_exit_z8_ns
;
599 prog_wm_value
= convert_and_clamp(
600 watermarks
->d
.cstate_pstate
.cstate_exit_z8_ns
,
602 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D
, 0,
603 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D
, prog_wm_value
);
604 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n"
605 "HW register value = 0x%x\n",
606 watermarks
->d
.cstate_pstate
.cstate_exit_z8_ns
, prog_wm_value
);
607 } else if (watermarks
->d
.cstate_pstate
.cstate_exit_z8_ns
608 < hubbub2
->watermarks
.d
.cstate_pstate
.cstate_exit_z8_ns
)
614 static bool hubbub31_program_pstate_watermarks(
615 struct hubbub
*hubbub
,
616 struct dcn_watermark_set
*watermarks
,
617 unsigned int refclk_mhz
,
620 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
621 uint32_t prog_wm_value
;
623 bool wm_pending
= false;
626 if (safe_to_lower
|| watermarks
->a
.cstate_pstate
.pstate_change_ns
627 > hubbub2
->watermarks
.a
.cstate_pstate
.pstate_change_ns
) {
628 hubbub2
->watermarks
.a
.cstate_pstate
.pstate_change_ns
=
629 watermarks
->a
.cstate_pstate
.pstate_change_ns
;
630 prog_wm_value
= convert_and_clamp(
631 watermarks
->a
.cstate_pstate
.pstate_change_ns
,
633 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A
, 0,
634 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A
, prog_wm_value
);
635 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
636 "HW register value = 0x%x\n\n",
637 watermarks
->a
.cstate_pstate
.pstate_change_ns
, prog_wm_value
);
638 } else if (watermarks
->a
.cstate_pstate
.pstate_change_ns
639 < hubbub2
->watermarks
.a
.cstate_pstate
.pstate_change_ns
)
643 if (safe_to_lower
|| watermarks
->b
.cstate_pstate
.pstate_change_ns
644 > hubbub2
->watermarks
.b
.cstate_pstate
.pstate_change_ns
) {
645 hubbub2
->watermarks
.b
.cstate_pstate
.pstate_change_ns
=
646 watermarks
->b
.cstate_pstate
.pstate_change_ns
;
647 prog_wm_value
= convert_and_clamp(
648 watermarks
->b
.cstate_pstate
.pstate_change_ns
,
650 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B
, 0,
651 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B
, prog_wm_value
);
652 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
653 "HW register value = 0x%x\n\n",
654 watermarks
->b
.cstate_pstate
.pstate_change_ns
, prog_wm_value
);
655 } else if (watermarks
->b
.cstate_pstate
.pstate_change_ns
656 < hubbub2
->watermarks
.b
.cstate_pstate
.pstate_change_ns
)
660 if (safe_to_lower
|| watermarks
->c
.cstate_pstate
.pstate_change_ns
661 > hubbub2
->watermarks
.c
.cstate_pstate
.pstate_change_ns
) {
662 hubbub2
->watermarks
.c
.cstate_pstate
.pstate_change_ns
=
663 watermarks
->c
.cstate_pstate
.pstate_change_ns
;
664 prog_wm_value
= convert_and_clamp(
665 watermarks
->c
.cstate_pstate
.pstate_change_ns
,
667 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C
, 0,
668 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C
, prog_wm_value
);
669 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
670 "HW register value = 0x%x\n\n",
671 watermarks
->c
.cstate_pstate
.pstate_change_ns
, prog_wm_value
);
672 } else if (watermarks
->c
.cstate_pstate
.pstate_change_ns
673 < hubbub2
->watermarks
.c
.cstate_pstate
.pstate_change_ns
)
677 if (safe_to_lower
|| watermarks
->d
.cstate_pstate
.pstate_change_ns
678 > hubbub2
->watermarks
.d
.cstate_pstate
.pstate_change_ns
) {
679 hubbub2
->watermarks
.d
.cstate_pstate
.pstate_change_ns
=
680 watermarks
->d
.cstate_pstate
.pstate_change_ns
;
681 prog_wm_value
= convert_and_clamp(
682 watermarks
->d
.cstate_pstate
.pstate_change_ns
,
684 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D
, 0,
685 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D
, prog_wm_value
);
686 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
687 "HW register value = 0x%x\n\n",
688 watermarks
->d
.cstate_pstate
.pstate_change_ns
, prog_wm_value
);
689 } else if (watermarks
->d
.cstate_pstate
.pstate_change_ns
690 < hubbub2
->watermarks
.d
.cstate_pstate
.pstate_change_ns
)
696 static bool hubbub31_program_watermarks(
697 struct hubbub
*hubbub
,
698 struct dcn_watermark_set
*watermarks
,
699 unsigned int refclk_mhz
,
702 bool wm_pending
= false;
704 if (hubbub31_program_urgent_watermarks(hubbub
, watermarks
, refclk_mhz
, safe_to_lower
))
707 if (hubbub31_program_stutter_watermarks(hubbub
, watermarks
, refclk_mhz
, safe_to_lower
))
710 if (hubbub31_program_pstate_watermarks(hubbub
, watermarks
, refclk_mhz
, safe_to_lower
))
714 * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric.
715 * If the memory controller is fully utilized and the DCHub requestors are
716 * well ahead of their amortized schedule, then it is safe to prevent the next winner
717 * from being committed and sent to the fabric.
718 * The utilization of the memory controller is approximated by ensuring that
719 * the number of outstanding requests is greater than a threshold specified
720 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized schedule,
721 * the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles.
723 * TODO: Revisit request limit after figure out right number. request limit for RM isn't decided yet, set maximum value (0x1FF)
724 * to turn off it for now.
726 /*REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
727 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
728 REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
729 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);*/
731 hubbub1_allow_self_refresh_control(hubbub
, !hubbub
->ctx
->dc
->debug
.disable_stutter
);
735 static void hubbub3_get_blk256_size(unsigned int *blk256_width
, unsigned int *blk256_height
,
736 unsigned int bytes_per_element
)
738 /* copied from DML. might want to refactor DML to leverage from DML */
739 /* DML : get_blk256_size */
740 if (bytes_per_element
== 1) {
743 } else if (bytes_per_element
== 2) {
746 } else if (bytes_per_element
== 4) {
749 } else if (bytes_per_element
== 8) {
755 static void hubbub31_det_request_size(
756 unsigned int detile_buf_size
,
760 bool *req128_horz_wc
,
761 bool *req128_vert_wc
)
763 unsigned int blk256_height
= 0;
764 unsigned int blk256_width
= 0;
765 unsigned int swath_bytes_horz_wc
, swath_bytes_vert_wc
;
767 hubbub3_get_blk256_size(&blk256_width
, &blk256_height
, bpe
);
769 swath_bytes_horz_wc
= width
* blk256_height
* bpe
;
770 swath_bytes_vert_wc
= height
* blk256_width
* bpe
;
772 *req128_horz_wc
= (2 * swath_bytes_horz_wc
<= detile_buf_size
) ?
773 false : /* full 256B request */
774 true; /* half 128b request */
776 *req128_vert_wc
= (2 * swath_bytes_vert_wc
<= detile_buf_size
) ?
777 false : /* full 256B request */
778 true; /* half 128b request */
781 static bool hubbub31_get_dcc_compression_cap(struct hubbub
*hubbub
,
782 const struct dc_dcc_surface_param
*input
,
783 struct dc_surface_dcc_cap
*output
)
785 struct dc
*dc
= hubbub
->ctx
->dc
;
786 enum dcc_control dcc_control
;
788 enum segment_order segment_order_horz
, segment_order_vert
;
789 bool req128_horz_wc
, req128_vert_wc
;
791 memset(output
, 0, sizeof(*output
));
793 if (dc
->debug
.disable_dcc
== DCC_DISABLE
)
796 if (!hubbub
->funcs
->dcc_support_pixel_format(input
->format
,
800 if (!hubbub
->funcs
->dcc_support_swizzle(input
->swizzle_mode
, bpe
,
801 &segment_order_horz
, &segment_order_vert
))
804 hubbub31_det_request_size(TO_DCN20_HUBBUB(hubbub
)->detile_buf_size
,
805 input
->surface_size
.height
, input
->surface_size
.width
,
806 bpe
, &req128_horz_wc
, &req128_vert_wc
);
808 if (!req128_horz_wc
&& !req128_vert_wc
) {
809 dcc_control
= dcc_control__256_256_xxx
;
810 } else if (input
->scan
== SCAN_DIRECTION_HORIZONTAL
) {
812 dcc_control
= dcc_control__256_256_xxx
;
813 else if (segment_order_horz
== segment_order__contiguous
)
814 dcc_control
= dcc_control__128_128_xxx
;
816 dcc_control
= dcc_control__256_64_64
;
817 } else if (input
->scan
== SCAN_DIRECTION_VERTICAL
) {
819 dcc_control
= dcc_control__256_256_xxx
;
820 else if (segment_order_vert
== segment_order__contiguous
)
821 dcc_control
= dcc_control__128_128_xxx
;
823 dcc_control
= dcc_control__256_64_64
;
825 if ((req128_horz_wc
&&
826 segment_order_horz
== segment_order__non_contiguous
) ||
828 segment_order_vert
== segment_order__non_contiguous
))
829 /* access_dir not known, must use most constraining */
830 dcc_control
= dcc_control__256_64_64
;
832 /* reg128 is true for either horz and vert
833 * but segment_order is contiguous
835 dcc_control
= dcc_control__128_128_xxx
;
838 /* Exception for 64KB_R_X */
839 if ((bpe
== 2) && (input
->swizzle_mode
== DC_SW_64KB_R_X
))
840 dcc_control
= dcc_control__128_128_xxx
;
842 if (dc
->debug
.disable_dcc
== DCC_HALF_REQ_DISALBE
&&
843 dcc_control
!= dcc_control__256_256_xxx
)
846 switch (dcc_control
) {
847 case dcc_control__256_256_xxx
:
848 output
->grph
.rgb
.max_uncompressed_blk_size
= 256;
849 output
->grph
.rgb
.max_compressed_blk_size
= 256;
850 output
->grph
.rgb
.independent_64b_blks
= false;
851 output
->grph
.rgb
.dcc_controls
.dcc_256_256_unconstrained
= 1;
852 output
->grph
.rgb
.dcc_controls
.dcc_256_128_128
= 1;
854 case dcc_control__128_128_xxx
:
855 output
->grph
.rgb
.max_uncompressed_blk_size
= 128;
856 output
->grph
.rgb
.max_compressed_blk_size
= 128;
857 output
->grph
.rgb
.independent_64b_blks
= false;
858 output
->grph
.rgb
.dcc_controls
.dcc_128_128_uncontrained
= 1;
859 output
->grph
.rgb
.dcc_controls
.dcc_256_128_128
= 1;
861 case dcc_control__256_64_64
:
862 output
->grph
.rgb
.max_uncompressed_blk_size
= 256;
863 output
->grph
.rgb
.max_compressed_blk_size
= 64;
864 output
->grph
.rgb
.independent_64b_blks
= true;
865 output
->grph
.rgb
.dcc_controls
.dcc_256_64_64
= 1;
867 case dcc_control__256_128_128
:
868 output
->grph
.rgb
.max_uncompressed_blk_size
= 256;
869 output
->grph
.rgb
.max_compressed_blk_size
= 128;
870 output
->grph
.rgb
.independent_64b_blks
= false;
871 output
->grph
.rgb
.dcc_controls
.dcc_256_128_128
= 1;
874 output
->capable
= true;
875 output
->const_color_support
= true;
880 static int hubbub31_init_dchub_sys_ctx(struct hubbub
*hubbub
,
881 struct dcn_hubbub_phys_addr_config
*pa_config
)
883 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
884 struct dcn_vmid_page_table_config phys_config
;
886 REG_SET(DCN_VM_FB_LOCATION_BASE
, 0,
887 FB_BASE
, pa_config
->system_aperture
.fb_base
>> 24);
888 REG_SET(DCN_VM_FB_LOCATION_TOP
, 0,
889 FB_TOP
, pa_config
->system_aperture
.fb_top
>> 24);
890 REG_SET(DCN_VM_FB_OFFSET
, 0,
891 FB_OFFSET
, pa_config
->system_aperture
.fb_offset
>> 24);
892 REG_SET(DCN_VM_AGP_BOT
, 0,
893 AGP_BOT
, pa_config
->system_aperture
.agp_bot
>> 24);
894 REG_SET(DCN_VM_AGP_TOP
, 0,
895 AGP_TOP
, pa_config
->system_aperture
.agp_top
>> 24);
896 REG_SET(DCN_VM_AGP_BASE
, 0,
897 AGP_BASE
, pa_config
->system_aperture
.agp_base
>> 24);
899 if (pa_config
->gart_config
.page_table_start_addr
!= pa_config
->gart_config
.page_table_end_addr
) {
900 phys_config
.page_table_start_addr
= pa_config
->gart_config
.page_table_start_addr
>> 12;
901 phys_config
.page_table_end_addr
= pa_config
->gart_config
.page_table_end_addr
>> 12;
902 phys_config
.page_table_base_addr
= pa_config
->gart_config
.page_table_base_addr
;
903 phys_config
.depth
= 0;
904 phys_config
.block_size
= 0;
905 // Init VMID 0 based on PA config
906 dcn20_vmid_setup(&hubbub2
->vmid
[0], &phys_config
);
908 dcn20_vmid_setup(&hubbub2
->vmid
[15], &phys_config
);
911 dcn21_dchvm_init(hubbub
);
916 static void hubbub31_get_dchub_ref_freq(struct hubbub
*hubbub
,
917 unsigned int dccg_ref_freq_inKhz
,
918 unsigned int *dchub_ref_freq_inKhz
)
920 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
921 uint32_t ref_div
= 0;
923 unsigned int dc_refclk_khz
= 24000;
925 REG_GET_2(DCHUBBUB_GLOBAL_TIMER_CNTL
, DCHUBBUB_GLOBAL_TIMER_REFDIV
, &ref_div
,
926 DCHUBBUB_GLOBAL_TIMER_ENABLE
, &ref_en
);
930 *dchub_ref_freq_inKhz
= dc_refclk_khz
/ 2;
932 *dchub_ref_freq_inKhz
= dc_refclk_khz
;
935 * The external Reference Clock may change based on the board or
936 * platform requirements and the programmable integer divide must
937 * be programmed to provide a suitable DLG RefClk frequency between
938 * a minimum of 20MHz and maximum of 50MHz
940 if (*dchub_ref_freq_inKhz
< 20000 || *dchub_ref_freq_inKhz
> 50000)
941 ASSERT_CRITICAL(false);
945 *dchub_ref_freq_inKhz
= dc_refclk_khz
;
947 // HUBBUB global timer must be enabled.
948 ASSERT_CRITICAL(false);
953 static bool hubbub31_verify_allow_pstate_change_high(struct hubbub
*hubbub
)
955 struct dcn20_hubbub
*hubbub2
= TO_DCN20_HUBBUB(hubbub
);
958 * Pstate latency is ~20us so if we wait over 40us and pstate allow
959 * still not asserted, we are probably stuck and going to hang
961 const unsigned int pstate_wait_timeout_us
= 100;
962 const unsigned int pstate_wait_expected_timeout_us
= 40;
964 static unsigned int max_sampled_pstate_wait_us
; /* data collection */
965 static bool forced_pstate_allow
; /* help with revert wa */
967 unsigned int debug_data
= 0;
970 if (forced_pstate_allow
) {
971 /* we hacked to force pstate allow to prevent hang last time
972 * we verify_allow_pstate_change_high. so disable force
973 * here so we can check status
975 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL
,
976 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE
, 0,
977 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE
, 0);
978 forced_pstate_allow
= false;
981 REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX
, hubbub2
->debug_test_index_pstate
);
983 for (i
= 0; i
< pstate_wait_timeout_us
; i
++) {
984 debug_data
= REG_READ(DCHUBBUB_TEST_DEBUG_DATA
);
986 /* Debug bit is specific to ASIC. */
987 if (debug_data
& (1 << 26)) {
988 if (i
> pstate_wait_expected_timeout_us
)
989 DC_LOG_WARNING("pstate took longer than expected ~%dus\n", i
);
992 if (max_sampled_pstate_wait_us
< i
)
993 max_sampled_pstate_wait_us
= i
;
998 /* force pstate allow to prevent system hang
999 * and break to debugger to investigate
1001 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL
,
1002 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE
, 1,
1003 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE
, 1);
1004 forced_pstate_allow
= true;
1006 DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n",
1012 static const struct hubbub_funcs hubbub31_funcs
= {
1013 .update_dchub
= hubbub2_update_dchub
,
1014 .init_dchub_sys_ctx
= hubbub31_init_dchub_sys_ctx
,
1015 .init_vm_ctx
= hubbub2_init_vm_ctx
,
1016 .dcc_support_swizzle
= hubbub3_dcc_support_swizzle
,
1017 .dcc_support_pixel_format
= hubbub2_dcc_support_pixel_format
,
1018 .get_dcc_compression_cap
= hubbub31_get_dcc_compression_cap
,
1019 .wm_read_state
= hubbub21_wm_read_state
,
1020 .get_dchub_ref_freq
= hubbub31_get_dchub_ref_freq
,
1021 .program_watermarks
= hubbub31_program_watermarks
,
1022 .allow_self_refresh_control
= hubbub1_allow_self_refresh_control
,
1023 .is_allow_self_refresh_enabled
= hubbub1_is_allow_self_refresh_enabled
,
1024 .verify_allow_pstate_change_high
= hubbub31_verify_allow_pstate_change_high
,
1025 .program_det_size
= dcn31_program_det_size
,
1026 .program_compbuf_size
= dcn31_program_compbuf_size
,
1027 .init_crb
= dcn31_init_crb
,
1028 .hubbub_read_state
= hubbub2_read_state
,
1031 void hubbub31_construct(struct dcn20_hubbub
*hubbub31
,
1032 struct dc_context
*ctx
,
1033 const struct dcn_hubbub_registers
*hubbub_regs
,
1034 const struct dcn_hubbub_shift
*hubbub_shift
,
1035 const struct dcn_hubbub_mask
*hubbub_mask
,
1037 int pixel_chunk_size_kb
,
1038 int config_return_buffer_size_kb
)
1041 hubbub3_construct(hubbub31
, ctx
, hubbub_regs
, hubbub_shift
, hubbub_mask
);
1042 hubbub31
->base
.funcs
= &hubbub31_funcs
;
1043 hubbub31
->detile_buf_size
= det_size_kb
* 1024;
1044 hubbub31
->pixel_chunk_size
= pixel_chunk_size_kb
* 1024;
1045 hubbub31
->crb_size_segs
= config_return_buffer_size_kb
/ DCN31_CRB_SEGMENT_SIZE_KB
;
1047 hubbub31
->debug_test_index_pstate
= 0x6;