1 /* $NetBSD: amdgpu_dcn10_hubbub.c,v 1.2 2021/12/18 23:45:03 riastradh Exp $ */
2
3 /*
4 * Copyright 2016 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: AMD
25 *
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dcn10_hubbub.c,v 1.2 2021/12/18 23:45:03 riastradh Exp $");
30
31 #include <linux/delay.h>
32
33 #include "dm_services.h"
34 #include "dcn10_hubp.h"
35 #include "dcn10_hubbub.h"
36 #include "reg_helper.h"
37
38 #define CTX \
39 hubbub1->base.ctx
40 #define DC_LOGGER \
41 hubbub1->base.ctx->logger
42 #define REG(reg)\
43 hubbub1->regs->reg
44
45 #undef FN
46 #define FN(reg_name, field_name) \
47 hubbub1->shifts->field_name, hubbub1->masks->field_name
48
hubbub1_wm_read_state(struct hubbub * hubbub,struct dcn_hubbub_wm * wm)49 void hubbub1_wm_read_state(struct hubbub *hubbub,
50 struct dcn_hubbub_wm *wm)
51 {
52 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
53 struct dcn_hubbub_wm_set *s;
54
55 memset(wm, 0, sizeof(struct dcn_hubbub_wm));
56
57 s = &wm->sets[0];
58 s->wm_set = 0;
59 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
60 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A);
61 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) {
62 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
63 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
64 }
65 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
66
67 s = &wm->sets[1];
68 s->wm_set = 1;
69 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B);
70 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B);
71 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) {
72 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B);
73 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B);
74 }
75 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);
76
77 s = &wm->sets[2];
78 s->wm_set = 2;
79 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C);
80 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C);
81 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) {
82 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C);
83 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C);
84 }
85 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);
86
87 s = &wm->sets[3];
88 s->wm_set = 3;
89 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D);
90 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D);
91 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) {
92 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D);
93 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D);
94 }
95 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
96 }
97
hubbub1_allow_self_refresh_control(struct hubbub * hubbub,bool allow)98 void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow)
99 {
100 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
101
102 /*
103 * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 1 means do not allow stutter
104 * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 means allow stutter
105 */
106
107 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
108 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0,
109 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow);
110 }
111
hubbub1_is_allow_self_refresh_enabled(struct hubbub * hubbub)112 bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
113 {
114 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
115 uint32_t enable = 0;
116
117 REG_GET(DCHUBBUB_ARB_DRAM_STATE_CNTL,
118 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, &enable);
119
120 return enable ? true : false;
121 }
122
123
hubbub1_verify_allow_pstate_change_high(struct hubbub * hubbub)124 bool hubbub1_verify_allow_pstate_change_high(
125 struct hubbub *hubbub)
126 {
127 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
128
129 /* pstate latency is ~20us so if we wait over 40us and pstate allow
130 * still not asserted, we are probably stuck and going to hang
131 *
132 * TODO: Figure out why it takes ~100us on linux
133 * pstate takes around ~100us on linux. Unknown currently as to
134 * why it takes that long on linux
135 */
136 static unsigned int pstate_wait_timeout_us = 200;
137 static unsigned int pstate_wait_expected_timeout_us = 40;
138 static unsigned int max_sampled_pstate_wait_us; /* data collection */
139 static bool forced_pstate_allow; /* help with revert wa */
140
141 unsigned int debug_data;
142 unsigned int i;
143
144 if (forced_pstate_allow) {
145 /* we hacked to force pstate allow to prevent hang last time
146 * we verify_allow_pstate_change_high. so disable force
147 * here so we can check status
148 */
149 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
150 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,
151 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0);
152 forced_pstate_allow = false;
153 }
154
155 /* RV2:
156 * dchubbubdebugind, at: 0xB
157 * description
158 * 0: Pipe0 Plane0 Allow Pstate Change
159 * 1: Pipe0 Plane1 Allow Pstate Change
160 * 2: Pipe0 Cursor0 Allow Pstate Change
161 * 3: Pipe0 Cursor1 Allow Pstate Change
162 * 4: Pipe1 Plane0 Allow Pstate Change
163 * 5: Pipe1 Plane1 Allow Pstate Change
164 * 6: Pipe1 Cursor0 Allow Pstate Change
165 * 7: Pipe1 Cursor1 Allow Pstate Change
166 * 8: Pipe2 Plane0 Allow Pstate Change
167 * 9: Pipe2 Plane1 Allow Pstate Change
168 * 10: Pipe2 Cursor0 Allow Pstate Change
169 * 11: Pipe2 Cursor1 Allow Pstate Change
170 * 12: Pipe3 Plane0 Allow Pstate Change
171 * 13: Pipe3 Plane1 Allow Pstate Change
172 * 14: Pipe3 Cursor0 Allow Pstate Change
173 * 15: Pipe3 Cursor1 Allow Pstate Change
174 * 16: Pipe4 Plane0 Allow Pstate Change
175 * 17: Pipe4 Plane1 Allow Pstate Change
176 * 18: Pipe4 Cursor0 Allow Pstate Change
177 * 19: Pipe4 Cursor1 Allow Pstate Change
178 * 20: Pipe5 Plane0 Allow Pstate Change
179 * 21: Pipe5 Plane1 Allow Pstate Change
180 * 22: Pipe5 Cursor0 Allow Pstate Change
181 * 23: Pipe5 Cursor1 Allow Pstate Change
182 * 24: Pipe6 Plane0 Allow Pstate Change
183 * 25: Pipe6 Plane1 Allow Pstate Change
184 * 26: Pipe6 Cursor0 Allow Pstate Change
185 * 27: Pipe6 Cursor1 Allow Pstate Change
186 * 28: WB0 Allow Pstate Change
187 * 29: WB1 Allow Pstate Change
188 * 30: Arbiter's allow_pstate_change
189 * 31: SOC pstate change request"
190 */
191 /*DCN2.x:
192 HUBBUB:DCHUBBUB_TEST_ARB_DEBUG10 DCHUBBUBDEBUGIND:0xB
193 0: Pipe0 Plane0 Allow P-state Change
194 1: Pipe0 Plane1 Allow P-state Change
195 2: Pipe0 Cursor0 Allow P-state Change
196 3: Pipe0 Cursor1 Allow P-state Change
197 4: Pipe1 Plane0 Allow P-state Change
198 5: Pipe1 Plane1 Allow P-state Change
199 6: Pipe1 Cursor0 Allow P-state Change
200 7: Pipe1 Cursor1 Allow P-state Change
201 8: Pipe2 Plane0 Allow P-state Change
202 9: Pipe2 Plane1 Allow P-state Change
203 10: Pipe2 Cursor0 Allow P-state Change
204 11: Pipe2 Cursor1 Allow P-state Change
205 12: Pipe3 Plane0 Allow P-state Change
206 13: Pipe3 Plane1 Allow P-state Change
207 14: Pipe3 Cursor0 Allow P-state Change
208 15: Pipe3 Cursor1 Allow P-state Change
209 16: Pipe4 Plane0 Allow P-state Change
210 17: Pipe4 Plane1 Allow P-state Change
211 18: Pipe4 Cursor0 Allow P-state Change
212 19: Pipe4 Cursor1 Allow P-state Change
213 20: Pipe5 Plane0 Allow P-state Change
214 21: Pipe5 Plane1 Allow P-state Change
215 22: Pipe5 Cursor0 Allow P-state Change
216 23: Pipe5 Cursor1 Allow P-state Change
217 24: Pipe6 Plane0 Allow P-state Change
218 25: Pipe6 Plane1 Allow P-state Change
219 26: Pipe6 Cursor0 Allow P-state Change
220 27: Pipe6 Cursor1 Allow P-state Change
221 28: WB0 Allow P-state Change
222 29: WB1 Allow P-state Change
223 30: Arbiter`s Allow P-state Change
224 31: SOC P-state Change request
225 */
226 /* RV1:
227 * dchubbubdebugind, at: 0x7
228 * description "3-0: Pipe0 cursor0 QOS
229 * 7-4: Pipe1 cursor0 QOS
230 * 11-8: Pipe2 cursor0 QOS
231 * 15-12: Pipe3 cursor0 QOS
232 * 16: Pipe0 Plane0 Allow Pstate Change
233 * 17: Pipe1 Plane0 Allow Pstate Change
234 * 18: Pipe2 Plane0 Allow Pstate Change
235 * 19: Pipe3 Plane0 Allow Pstate Change
236 * 20: Pipe0 Plane1 Allow Pstate Change
237 * 21: Pipe1 Plane1 Allow Pstate Change
238 * 22: Pipe2 Plane1 Allow Pstate Change
239 * 23: Pipe3 Plane1 Allow Pstate Change
240 * 24: Pipe0 cursor0 Allow Pstate Change
241 * 25: Pipe1 cursor0 Allow Pstate Change
242 * 26: Pipe2 cursor0 Allow Pstate Change
243 * 27: Pipe3 cursor0 Allow Pstate Change
244 * 28: WB0 Allow Pstate Change
245 * 29: WB1 Allow Pstate Change
246 * 30: Arbiter's allow_pstate_change
247 * 31: SOC pstate change request
248 */
249
250 REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub1->debug_test_index_pstate);
251
252 for (i = 0; i < pstate_wait_timeout_us; i++) {
253 debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
254
255 if (debug_data & (1 << 30)) {
256
257 if (i > pstate_wait_expected_timeout_us)
258 DC_LOG_WARNING("pstate took longer than expected ~%dus\n",
259 i);
260
261 return true;
262 }
263 if (max_sampled_pstate_wait_us < i)
264 max_sampled_pstate_wait_us = i;
265
266 udelay(1);
267 }
268
269 /* force pstate allow to prevent system hang
270 * and break to debugger to investigate
271 */
272 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
273 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1,
274 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
275 forced_pstate_allow = true;
276
277 DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n",
278 debug_data);
279
280 return false;
281 }
282
convert_and_clamp(uint32_t wm_ns,uint32_t refclk_mhz,uint32_t clamp_value)283 static uint32_t convert_and_clamp(
284 uint32_t wm_ns,
285 uint32_t refclk_mhz,
286 uint32_t clamp_value)
287 {
288 uint32_t ret_val = 0;
289 ret_val = wm_ns * refclk_mhz;
290 ret_val /= 1000;
291
292 if (ret_val > clamp_value)
293 ret_val = clamp_value;
294
295 return ret_val;
296 }
297
298
hubbub1_wm_change_req_wa(struct hubbub * hubbub)299 void hubbub1_wm_change_req_wa(struct hubbub *hubbub)
300 {
301 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
302
303 REG_UPDATE_SEQ_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
304 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0,
305 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
306 }
307
hubbub1_program_urgent_watermarks(struct hubbub * hubbub,struct dcn_watermark_set * watermarks,unsigned int refclk_mhz,bool safe_to_lower)308 void hubbub1_program_urgent_watermarks(
309 struct hubbub *hubbub,
310 struct dcn_watermark_set *watermarks,
311 unsigned int refclk_mhz,
312 bool safe_to_lower)
313 {
314 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
315 uint32_t prog_wm_value;
316
317 /* Repeat for water mark set A, B, C and D. */
318 /* clock state A */
319 if (safe_to_lower || watermarks->a.urgent_ns > hubbub1->watermarks.a.urgent_ns) {
320 hubbub1->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
321 prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
322 refclk_mhz, 0x1fffff);
323 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
324 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
325
326 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
327 "HW register value = 0x%x\n",
328 watermarks->a.urgent_ns, prog_wm_value);
329 }
330
331 if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub1->watermarks.a.pte_meta_urgent_ns) {
332 hubbub1->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns;
333 prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns,
334 refclk_mhz, 0x1fffff);
335 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value);
336 DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
337 "HW register value = 0x%x\n",
338 watermarks->a.pte_meta_urgent_ns, prog_wm_value);
339 }
340
341 /* clock state B */
342 if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) {
343 hubbub1->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
344 prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
345 refclk_mhz, 0x1fffff);
346 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
347 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
348
349 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
350 "HW register value = 0x%x\n",
351 watermarks->b.urgent_ns, prog_wm_value);
352 }
353
354 if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub1->watermarks.b.pte_meta_urgent_ns) {
355 hubbub1->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns;
356 prog_wm_value = convert_and_clamp(watermarks->b.pte_meta_urgent_ns,
357 refclk_mhz, 0x1fffff);
358 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value);
359 DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
360 "HW register value = 0x%x\n",
361 watermarks->b.pte_meta_urgent_ns, prog_wm_value);
362 }
363
364 /* clock state C */
365 if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) {
366 hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
367 prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
368 refclk_mhz, 0x1fffff);
369 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
370 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
371
372 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
373 "HW register value = 0x%x\n",
374 watermarks->c.urgent_ns, prog_wm_value);
375 }
376
377 if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub1->watermarks.c.pte_meta_urgent_ns) {
378 hubbub1->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns;
379 prog_wm_value = convert_and_clamp(watermarks->c.pte_meta_urgent_ns,
380 refclk_mhz, 0x1fffff);
381 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value);
382 DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
383 "HW register value = 0x%x\n",
384 watermarks->c.pte_meta_urgent_ns, prog_wm_value);
385 }
386
387 /* clock state D */
388 if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) {
389 hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
390 prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
391 refclk_mhz, 0x1fffff);
392 REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
393 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
394
395 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
396 "HW register value = 0x%x\n",
397 watermarks->d.urgent_ns, prog_wm_value);
398 }
399
400 if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub1->watermarks.d.pte_meta_urgent_ns) {
401 hubbub1->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns;
402 prog_wm_value = convert_and_clamp(watermarks->d.pte_meta_urgent_ns,
403 refclk_mhz, 0x1fffff);
404 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value);
405 DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
406 "HW register value = 0x%x\n",
407 watermarks->d.pte_meta_urgent_ns, prog_wm_value);
408 }
409 }
410
hubbub1_program_stutter_watermarks(struct hubbub * hubbub,struct dcn_watermark_set * watermarks,unsigned int refclk_mhz,bool safe_to_lower)411 void hubbub1_program_stutter_watermarks(
412 struct hubbub *hubbub,
413 struct dcn_watermark_set *watermarks,
414 unsigned int refclk_mhz,
415 bool safe_to_lower)
416 {
417 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
418 uint32_t prog_wm_value;
419
420 /* clock state A */
421 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
422 > hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
423 hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
424 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
425 prog_wm_value = convert_and_clamp(
426 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
427 refclk_mhz, 0x1fffff);
428 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
429 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
430 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
431 "HW register value = 0x%x\n",
432 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
433 }
434
435 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
436 > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {
437 hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns =
438 watermarks->a.cstate_pstate.cstate_exit_ns;
439 prog_wm_value = convert_and_clamp(
440 watermarks->a.cstate_pstate.cstate_exit_ns,
441 refclk_mhz, 0x1fffff);
442 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
443 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
444 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
445 "HW register value = 0x%x\n",
446 watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
447 }
448
449 /* clock state B */
450 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
451 > hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
452 hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
453 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
454 prog_wm_value = convert_and_clamp(
455 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
456 refclk_mhz, 0x1fffff);
457 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
458 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
459 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
460 "HW register value = 0x%x\n",
461 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
462 }
463
464 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
465 > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {
466 hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns =
467 watermarks->b.cstate_pstate.cstate_exit_ns;
468 prog_wm_value = convert_and_clamp(
469 watermarks->b.cstate_pstate.cstate_exit_ns,
470 refclk_mhz, 0x1fffff);
471 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
472 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
473 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
474 "HW register value = 0x%x\n",
475 watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
476 }
477
478 /* clock state C */
479 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
480 > hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
481 hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
482 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
483 prog_wm_value = convert_and_clamp(
484 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
485 refclk_mhz, 0x1fffff);
486 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
487 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
488 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
489 "HW register value = 0x%x\n",
490 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
491 }
492
493 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
494 > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {
495 hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns =
496 watermarks->c.cstate_pstate.cstate_exit_ns;
497 prog_wm_value = convert_and_clamp(
498 watermarks->c.cstate_pstate.cstate_exit_ns,
499 refclk_mhz, 0x1fffff);
500 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
501 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
502 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
503 "HW register value = 0x%x\n",
504 watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
505 }
506
507 /* clock state D */
508 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
509 > hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
510 hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
511 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
512 prog_wm_value = convert_and_clamp(
513 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
514 refclk_mhz, 0x1fffff);
515 REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
516 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
517 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
518 "HW register value = 0x%x\n",
519 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
520 }
521
522 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
523 > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {
524 hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns =
525 watermarks->d.cstate_pstate.cstate_exit_ns;
526 prog_wm_value = convert_and_clamp(
527 watermarks->d.cstate_pstate.cstate_exit_ns,
528 refclk_mhz, 0x1fffff);
529 REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
530 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
531 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
532 "HW register value = 0x%x\n",
533 watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
534 }
535
536 }
537
hubbub1_program_pstate_watermarks(struct hubbub * hubbub,struct dcn_watermark_set * watermarks,unsigned int refclk_mhz,bool safe_to_lower)538 void hubbub1_program_pstate_watermarks(
539 struct hubbub *hubbub,
540 struct dcn_watermark_set *watermarks,
541 unsigned int refclk_mhz,
542 bool safe_to_lower)
543 {
544 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
545 uint32_t prog_wm_value;
546
547 /* clock state A */
548 if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
549 > hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) {
550 hubbub1->watermarks.a.cstate_pstate.pstate_change_ns =
551 watermarks->a.cstate_pstate.pstate_change_ns;
552 prog_wm_value = convert_and_clamp(
553 watermarks->a.cstate_pstate.pstate_change_ns,
554 refclk_mhz, 0x1fffff);
555 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0,
556 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
557 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
558 "HW register value = 0x%x\n\n",
559 watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
560 }
561
562 /* clock state B */
563 if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
564 > hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) {
565 hubbub1->watermarks.b.cstate_pstate.pstate_change_ns =
566 watermarks->b.cstate_pstate.pstate_change_ns;
567 prog_wm_value = convert_and_clamp(
568 watermarks->b.cstate_pstate.pstate_change_ns,
569 refclk_mhz, 0x1fffff);
570 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0,
571 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
572 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
573 "HW register value = 0x%x\n\n",
574 watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
575 }
576
577 /* clock state C */
578 if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
579 > hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) {
580 hubbub1->watermarks.c.cstate_pstate.pstate_change_ns =
581 watermarks->c.cstate_pstate.pstate_change_ns;
582 prog_wm_value = convert_and_clamp(
583 watermarks->c.cstate_pstate.pstate_change_ns,
584 refclk_mhz, 0x1fffff);
585 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0,
586 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
587 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
588 "HW register value = 0x%x\n\n",
589 watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
590 }
591
592 /* clock state D */
593 if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
594 > hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) {
595 hubbub1->watermarks.d.cstate_pstate.pstate_change_ns =
596 watermarks->d.cstate_pstate.pstate_change_ns;
597 prog_wm_value = convert_and_clamp(
598 watermarks->d.cstate_pstate.pstate_change_ns,
599 refclk_mhz, 0x1fffff);
600 REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0,
601 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
602 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
603 "HW register value = 0x%x\n\n",
604 watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
605 }
606 }
607
hubbub1_program_watermarks(struct hubbub * hubbub,struct dcn_watermark_set * watermarks,unsigned int refclk_mhz,bool safe_to_lower)608 void hubbub1_program_watermarks(
609 struct hubbub *hubbub,
610 struct dcn_watermark_set *watermarks,
611 unsigned int refclk_mhz,
612 bool safe_to_lower)
613 {
614 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
615 /*
616 * Need to clamp to max of the register values (i.e. no wrap)
617 * for dcn1, all wm registers are 21-bit wide
618 */
619 hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
620 hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
621 hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
622
623 REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL,
624 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
625 REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
626 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68);
627
628 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
629
630 #if 0
631 REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
632 DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1,
633 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
634 #endif
635 }
636
hubbub1_update_dchub(struct hubbub * hubbub,struct dchub_init_data * dh_data)637 void hubbub1_update_dchub(
638 struct hubbub *hubbub,
639 struct dchub_init_data *dh_data)
640 {
641 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
642
643 if (REG(DCHUBBUB_SDPIF_FB_TOP) == 0) {
644 ASSERT(false);
645 /*should not come here*/
646 return;
647 }
648 /* TODO: port code from dal2 */
649 switch (dh_data->fb_mode) {
650 case FRAME_BUFFER_MODE_ZFB_ONLY:
651 /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/
652 REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP,
653 SDPIF_FB_TOP, 0);
654
655 REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE,
656 SDPIF_FB_BASE, 0x0FFFF);
657
658 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
659 SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22);
660
661 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
662 SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22);
663
664 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
665 SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr +
666 dh_data->zfb_size_in_byte - 1) >> 22);
667 break;
668 case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL:
669 /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/
670
671 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
672 SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22);
673
674 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
675 SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22);
676
677 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
678 SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr +
679 dh_data->zfb_size_in_byte - 1) >> 22);
680 break;
681 case FRAME_BUFFER_MODE_LOCAL_ONLY:
682 /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/
683 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
684 SDPIF_AGP_BASE, 0);
685
686 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
687 SDPIF_AGP_BOT, 0X03FFFF);
688
689 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
690 SDPIF_AGP_TOP, 0);
691 break;
692 default:
693 break;
694 }
695
696 dh_data->dchub_initialzied = true;
697 dh_data->dchub_info_valid = false;
698 }
699
hubbub1_toggle_watermark_change_req(struct hubbub * hubbub)700 void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub)
701 {
702 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
703
704 uint32_t watermark_change_req;
705
706 REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
707 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, &watermark_change_req);
708
709 if (watermark_change_req)
710 watermark_change_req = 0;
711 else
712 watermark_change_req = 1;
713
714 REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
715 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req);
716 }
717
hubbub1_soft_reset(struct hubbub * hubbub,bool reset)718 void hubbub1_soft_reset(struct hubbub *hubbub, bool reset)
719 {
720 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
721
722 uint32_t reset_en = reset ? 1 : 0;
723
724 REG_UPDATE(DCHUBBUB_SOFT_RESET,
725 DCHUBBUB_GLOBAL_SOFT_RESET, reset_en);
726 }
727
hubbub1_dcc_support_swizzle(enum swizzle_mode_values swizzle,unsigned int bytes_per_element,enum segment_order * segment_order_horz,enum segment_order * segment_order_vert)728 static bool hubbub1_dcc_support_swizzle(
729 enum swizzle_mode_values swizzle,
730 unsigned int bytes_per_element,
731 enum segment_order *segment_order_horz,
732 enum segment_order *segment_order_vert)
733 {
734 bool standard_swizzle = false;
735 bool display_swizzle = false;
736
737 switch (swizzle) {
738 case DC_SW_4KB_S:
739 case DC_SW_64KB_S:
740 case DC_SW_VAR_S:
741 case DC_SW_4KB_S_X:
742 case DC_SW_64KB_S_X:
743 case DC_SW_VAR_S_X:
744 standard_swizzle = true;
745 break;
746 case DC_SW_4KB_D:
747 case DC_SW_64KB_D:
748 case DC_SW_VAR_D:
749 case DC_SW_4KB_D_X:
750 case DC_SW_64KB_D_X:
751 case DC_SW_VAR_D_X:
752 display_swizzle = true;
753 break;
754 default:
755 break;
756 }
757
758 if (bytes_per_element == 1 && standard_swizzle) {
759 *segment_order_horz = segment_order__contiguous;
760 *segment_order_vert = segment_order__na;
761 return true;
762 }
763 if (bytes_per_element == 2 && standard_swizzle) {
764 *segment_order_horz = segment_order__non_contiguous;
765 *segment_order_vert = segment_order__contiguous;
766 return true;
767 }
768 if (bytes_per_element == 4 && standard_swizzle) {
769 *segment_order_horz = segment_order__non_contiguous;
770 *segment_order_vert = segment_order__contiguous;
771 return true;
772 }
773 if (bytes_per_element == 8 && standard_swizzle) {
774 *segment_order_horz = segment_order__na;
775 *segment_order_vert = segment_order__contiguous;
776 return true;
777 }
778 if (bytes_per_element == 8 && display_swizzle) {
779 *segment_order_horz = segment_order__contiguous;
780 *segment_order_vert = segment_order__non_contiguous;
781 return true;
782 }
783
784 return false;
785 }
786
hubbub1_dcc_support_pixel_format(enum surface_pixel_format format,unsigned int * bytes_per_element)787 static bool hubbub1_dcc_support_pixel_format(
788 enum surface_pixel_format format,
789 unsigned int *bytes_per_element)
790 {
791 /* DML: get_bytes_per_element */
792 switch (format) {
793 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
794 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
795 *bytes_per_element = 2;
796 return true;
797 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
798 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
799 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
800 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
801 *bytes_per_element = 4;
802 return true;
803 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
804 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
805 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
806 *bytes_per_element = 8;
807 return true;
808 default:
809 return false;
810 }
811 }
812
hubbub1_get_blk256_size(unsigned int * blk256_width,unsigned int * blk256_height,unsigned int bytes_per_element)813 static void hubbub1_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,
814 unsigned int bytes_per_element)
815 {
816 /* copied from DML. might want to refactor DML to leverage from DML */
817 /* DML : get_blk256_size */
818 if (bytes_per_element == 1) {
819 *blk256_width = 16;
820 *blk256_height = 16;
821 } else if (bytes_per_element == 2) {
822 *blk256_width = 16;
823 *blk256_height = 8;
824 } else if (bytes_per_element == 4) {
825 *blk256_width = 8;
826 *blk256_height = 8;
827 } else if (bytes_per_element == 8) {
828 *blk256_width = 8;
829 *blk256_height = 4;
830 }
831 }
832
hubbub1_det_request_size(unsigned int height,unsigned int width,unsigned int bpe,bool * req128_horz_wc,bool * req128_vert_wc)833 static void hubbub1_det_request_size(
834 unsigned int height,
835 unsigned int width,
836 unsigned int bpe,
837 bool *req128_horz_wc,
838 bool *req128_vert_wc)
839 {
840 unsigned int detile_buf_size = 164 * 1024; /* 164KB for DCN1.0 */
841
842 unsigned int blk256_height = 0;
843 unsigned int blk256_width = 0;
844 unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc;
845
846 hubbub1_get_blk256_size(&blk256_width, &blk256_height, bpe);
847
848 swath_bytes_horz_wc = height * blk256_height * bpe;
849 swath_bytes_vert_wc = width * blk256_width * bpe;
850
851 *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?
852 false : /* full 256B request */
853 true; /* half 128b request */
854
855 *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ?
856 false : /* full 256B request */
857 true; /* half 128b request */
858 }
859
hubbub1_get_dcc_compression_cap(struct hubbub * hubbub,const struct dc_dcc_surface_param * input,struct dc_surface_dcc_cap * output)860 static bool hubbub1_get_dcc_compression_cap(struct hubbub *hubbub,
861 const struct dc_dcc_surface_param *input,
862 struct dc_surface_dcc_cap *output)
863 {
864 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
865 struct dc *dc = hubbub1->base.ctx->dc;
866
867 /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */
868 enum dcc_control dcc_control;
869 unsigned int bpe;
870 enum segment_order segment_order_horz, segment_order_vert;
871 bool req128_horz_wc, req128_vert_wc;
872
873 memset(output, 0, sizeof(*output));
874
875 if (dc->debug.disable_dcc == DCC_DISABLE)
876 return false;
877
878 if (!hubbub1->base.funcs->dcc_support_pixel_format(input->format, &bpe))
879 return false;
880
881 if (!hubbub1->base.funcs->dcc_support_swizzle(input->swizzle_mode, bpe,
882 &segment_order_horz, &segment_order_vert))
883 return false;
884
885 hubbub1_det_request_size(input->surface_size.height, input->surface_size.width,
886 bpe, &req128_horz_wc, &req128_vert_wc);
887
888 if (!req128_horz_wc && !req128_vert_wc) {
889 dcc_control = dcc_control__256_256_xxx;
890 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
891 if (!req128_horz_wc)
892 dcc_control = dcc_control__256_256_xxx;
893 else if (segment_order_horz == segment_order__contiguous)
894 dcc_control = dcc_control__128_128_xxx;
895 else
896 dcc_control = dcc_control__256_64_64;
897 } else if (input->scan == SCAN_DIRECTION_VERTICAL) {
898 if (!req128_vert_wc)
899 dcc_control = dcc_control__256_256_xxx;
900 else if (segment_order_vert == segment_order__contiguous)
901 dcc_control = dcc_control__128_128_xxx;
902 else
903 dcc_control = dcc_control__256_64_64;
904 } else {
905 if ((req128_horz_wc &&
906 segment_order_horz == segment_order__non_contiguous) ||
907 (req128_vert_wc &&
908 segment_order_vert == segment_order__non_contiguous))
909 /* access_dir not known, must use most constraining */
910 dcc_control = dcc_control__256_64_64;
911 else
912 /* reg128 is true for either horz and vert
913 * but segment_order is contiguous
914 */
915 dcc_control = dcc_control__128_128_xxx;
916 }
917
918 if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&
919 dcc_control != dcc_control__256_256_xxx)
920 return false;
921
922 switch (dcc_control) {
923 case dcc_control__256_256_xxx:
924 output->grph.rgb.max_uncompressed_blk_size = 256;
925 output->grph.rgb.max_compressed_blk_size = 256;
926 output->grph.rgb.independent_64b_blks = false;
927 break;
928 case dcc_control__128_128_xxx:
929 output->grph.rgb.max_uncompressed_blk_size = 128;
930 output->grph.rgb.max_compressed_blk_size = 128;
931 output->grph.rgb.independent_64b_blks = false;
932 break;
933 case dcc_control__256_64_64:
934 output->grph.rgb.max_uncompressed_blk_size = 256;
935 output->grph.rgb.max_compressed_blk_size = 64;
936 output->grph.rgb.independent_64b_blks = true;
937 break;
938 default:
939 ASSERT(false);
940 break;
941 }
942
943 output->capable = true;
944 output->const_color_support = false;
945
946 return true;
947 }
948
949 static const struct hubbub_funcs hubbub1_funcs = {
950 .update_dchub = hubbub1_update_dchub,
951 .dcc_support_swizzle = hubbub1_dcc_support_swizzle,
952 .dcc_support_pixel_format = hubbub1_dcc_support_pixel_format,
953 .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap,
954 .wm_read_state = hubbub1_wm_read_state,
955 .program_watermarks = hubbub1_program_watermarks,
956 .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
957 .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
958 };
959
hubbub1_construct(struct hubbub * hubbub,struct dc_context * ctx,const struct dcn_hubbub_registers * hubbub_regs,const struct dcn_hubbub_shift * hubbub_shift,const struct dcn_hubbub_mask * hubbub_mask)960 void hubbub1_construct(struct hubbub *hubbub,
961 struct dc_context *ctx,
962 const struct dcn_hubbub_registers *hubbub_regs,
963 const struct dcn_hubbub_shift *hubbub_shift,
964 const struct dcn_hubbub_mask *hubbub_mask)
965 {
966 struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
967
968 hubbub1->base.ctx = ctx;
969
970 hubbub1->base.funcs = &hubbub1_funcs;
971
972 hubbub1->regs = hubbub_regs;
973 hubbub1->shifts = hubbub_shift;
974 hubbub1->masks = hubbub_mask;
975
976 hubbub1->debug_test_index_pstate = 0x7;
977 if (ctx->dce_version == DCN_VERSION_1_01)
978 hubbub1->debug_test_index_pstate = 0xB;
979 }
980
981