1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "dm_services.h"
27#include "dcn10_hubp.h"
28#include "dcn10_hubbub.h"
29#include "reg_helper.h"
30
31#define CTX \
32 hubbub->ctx
33#define DC_LOGGER \
34 hubbub->ctx->logger
35#define REG(reg)\
36 hubbub->regs->reg
37
38#undef FN
39#define FN(reg_name, field_name) \
40 hubbub->shifts->field_name, hubbub->masks->field_name
41
42void hubbub1_wm_read_state(struct hubbub *hubbub,
43 struct dcn_hubbub_wm *wm)
44{
45 struct dcn_hubbub_wm_set *s;
46
47 memset(wm, 0, sizeof(struct dcn_hubbub_wm));
48
49 s = &wm->sets[0];
50 s->wm_set = 0;
51 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);
52 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A);
53 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) {
54 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);
55 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);
56 }
57 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A);
58
59 s = &wm->sets[1];
60 s->wm_set = 1;
61 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B);
62 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B);
63 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) {
64 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B);
65 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B);
66 }
67 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B);
68
69 s = &wm->sets[2];
70 s->wm_set = 2;
71 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C);
72 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C);
73 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) {
74 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C);
75 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C);
76 }
77 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C);
78
79 s = &wm->sets[3];
80 s->wm_set = 3;
81 s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D);
82 s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D);
83 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) {
84 s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D);
85 s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D);
86 }
87 s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
88}
89
90void hubbub1_disable_allow_self_refresh(struct hubbub *hubbub)
91{
92 REG_UPDATE(DCHUBBUB_ARB_DRAM_STATE_CNTL,
93 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, 0);
94}
95
96bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
97{
98 uint32_t enable = 0;
99
100 REG_GET(DCHUBBUB_ARB_DRAM_STATE_CNTL,
101 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, &enable);
102
103 return enable ? true : false;
104}
105
106
107bool hubbub1_verify_allow_pstate_change_high(
108 struct hubbub *hubbub)
109{
110
111
112
113
114
115
116
117 static unsigned int pstate_wait_timeout_us = 200;
118 static unsigned int pstate_wait_expected_timeout_us = 40;
119 static unsigned int max_sampled_pstate_wait_us;
120 static bool forced_pstate_allow;
121
122 unsigned int debug_data;
123 unsigned int i;
124
125 if (forced_pstate_allow) {
126
127
128
129
130 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
131 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,
132 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0);
133 forced_pstate_allow = false;
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub->debug_test_index_pstate);
197
198 for (i = 0; i < pstate_wait_timeout_us; i++) {
199 debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);
200
201 if (debug_data & (1 << 30)) {
202
203 if (i > pstate_wait_expected_timeout_us)
204 DC_LOG_WARNING("pstate took longer than expected ~%dus\n",
205 i);
206
207 return true;
208 }
209 if (max_sampled_pstate_wait_us < i)
210 max_sampled_pstate_wait_us = i;
211
212 udelay(1);
213 }
214
215
216
217
218 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
219 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1,
220 DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
221 forced_pstate_allow = true;
222
223 DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n",
224 debug_data);
225
226 return false;
227}
228
229static uint32_t convert_and_clamp(
230 uint32_t wm_ns,
231 uint32_t refclk_mhz,
232 uint32_t clamp_value)
233{
234 uint32_t ret_val = 0;
235 ret_val = wm_ns * refclk_mhz;
236 ret_val /= 1000;
237
238 if (ret_val > clamp_value)
239 ret_val = clamp_value;
240
241 return ret_val;
242}
243
244
245void hubbub1_wm_change_req_wa(struct hubbub *hubbub)
246{
247 REG_UPDATE_SEQ(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
248 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0, 1);
249}
250
251void hubbub1_program_watermarks(
252 struct hubbub *hubbub,
253 struct dcn_watermark_set *watermarks,
254 unsigned int refclk_mhz,
255 bool safe_to_lower)
256{
257 uint32_t force_en = hubbub->ctx->dc->debug.disable_stutter ? 1 : 0;
258
259
260
261
262 uint32_t prog_wm_value;
263
264
265
266
267 if (safe_to_lower || watermarks->a.urgent_ns > hubbub->watermarks.a.urgent_ns) {
268 hubbub->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
269 prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
270 refclk_mhz, 0x1fffff);
271 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);
272
273 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
274 "HW register value = 0x%x\n",
275 watermarks->a.urgent_ns, prog_wm_value);
276 }
277
278 if (safe_to_lower || watermarks->a.pte_meta_urgent_ns > hubbub->watermarks.a.pte_meta_urgent_ns) {
279 hubbub->watermarks.a.pte_meta_urgent_ns = watermarks->a.pte_meta_urgent_ns;
280 prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns,
281 refclk_mhz, 0x1fffff);
282 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value);
283 DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_A calculated =%d\n"
284 "HW register value = 0x%x\n",
285 watermarks->a.pte_meta_urgent_ns, prog_wm_value);
286 }
287
288 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) {
289 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
290 > hubbub->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
291 hubbub->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
292 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
293 prog_wm_value = convert_and_clamp(
294 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
295 refclk_mhz, 0x1fffff);
296 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
297 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
298 "HW register value = 0x%x\n",
299 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
300 }
301
302 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
303 > hubbub->watermarks.a.cstate_pstate.cstate_exit_ns) {
304 hubbub->watermarks.a.cstate_pstate.cstate_exit_ns =
305 watermarks->a.cstate_pstate.cstate_exit_ns;
306 prog_wm_value = convert_and_clamp(
307 watermarks->a.cstate_pstate.cstate_exit_ns,
308 refclk_mhz, 0x1fffff);
309 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
310 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
311 "HW register value = 0x%x\n",
312 watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
313 }
314 }
315
316 if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
317 > hubbub->watermarks.a.cstate_pstate.pstate_change_ns) {
318 hubbub->watermarks.a.cstate_pstate.pstate_change_ns =
319 watermarks->a.cstate_pstate.pstate_change_ns;
320 prog_wm_value = convert_and_clamp(
321 watermarks->a.cstate_pstate.pstate_change_ns,
322 refclk_mhz, 0x1fffff);
323 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
324 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
325 "HW register value = 0x%x\n\n",
326 watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
327 }
328
329
330 if (safe_to_lower || watermarks->b.urgent_ns > hubbub->watermarks.b.urgent_ns) {
331 hubbub->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
332 prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
333 refclk_mhz, 0x1fffff);
334 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);
335
336 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
337 "HW register value = 0x%x\n",
338 watermarks->b.urgent_ns, prog_wm_value);
339 }
340
341 if (safe_to_lower || watermarks->b.pte_meta_urgent_ns > hubbub->watermarks.b.pte_meta_urgent_ns) {
342 hubbub->watermarks.b.pte_meta_urgent_ns = watermarks->b.pte_meta_urgent_ns;
343 prog_wm_value = convert_and_clamp(watermarks->b.pte_meta_urgent_ns,
344 refclk_mhz, 0x1fffff);
345 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value);
346 DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_B calculated =%d\n"
347 "HW register value = 0x%x\n",
348 watermarks->b.pte_meta_urgent_ns, prog_wm_value);
349 }
350
351 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) {
352 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
353 > hubbub->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
354 hubbub->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
355 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
356 prog_wm_value = convert_and_clamp(
357 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
358 refclk_mhz, 0x1fffff);
359 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
360 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
361 "HW register value = 0x%x\n",
362 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
363 }
364
365 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
366 > hubbub->watermarks.b.cstate_pstate.cstate_exit_ns) {
367 hubbub->watermarks.b.cstate_pstate.cstate_exit_ns =
368 watermarks->b.cstate_pstate.cstate_exit_ns;
369 prog_wm_value = convert_and_clamp(
370 watermarks->b.cstate_pstate.cstate_exit_ns,
371 refclk_mhz, 0x1fffff);
372 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);
373 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
374 "HW register value = 0x%x\n",
375 watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
376 }
377 }
378
379 if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
380 > hubbub->watermarks.b.cstate_pstate.pstate_change_ns) {
381 hubbub->watermarks.b.cstate_pstate.pstate_change_ns =
382 watermarks->b.cstate_pstate.pstate_change_ns;
383 prog_wm_value = convert_and_clamp(
384 watermarks->b.cstate_pstate.pstate_change_ns,
385 refclk_mhz, 0x1fffff);
386 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
387 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
388 "HW register value = 0x%x\n\n",
389 watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
390 }
391
392
393 if (safe_to_lower || watermarks->c.urgent_ns > hubbub->watermarks.c.urgent_ns) {
394 hubbub->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
395 prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
396 refclk_mhz, 0x1fffff);
397 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);
398
399 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
400 "HW register value = 0x%x\n",
401 watermarks->c.urgent_ns, prog_wm_value);
402 }
403
404 if (safe_to_lower || watermarks->c.pte_meta_urgent_ns > hubbub->watermarks.c.pte_meta_urgent_ns) {
405 hubbub->watermarks.c.pte_meta_urgent_ns = watermarks->c.pte_meta_urgent_ns;
406 prog_wm_value = convert_and_clamp(watermarks->c.pte_meta_urgent_ns,
407 refclk_mhz, 0x1fffff);
408 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value);
409 DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_C calculated =%d\n"
410 "HW register value = 0x%x\n",
411 watermarks->c.pte_meta_urgent_ns, prog_wm_value);
412 }
413
414 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) {
415 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
416 > hubbub->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
417 hubbub->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
418 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
419 prog_wm_value = convert_and_clamp(
420 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
421 refclk_mhz, 0x1fffff);
422 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
423 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
424 "HW register value = 0x%x\n",
425 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
426 }
427
428 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
429 > hubbub->watermarks.c.cstate_pstate.cstate_exit_ns) {
430 hubbub->watermarks.c.cstate_pstate.cstate_exit_ns =
431 watermarks->c.cstate_pstate.cstate_exit_ns;
432 prog_wm_value = convert_and_clamp(
433 watermarks->c.cstate_pstate.cstate_exit_ns,
434 refclk_mhz, 0x1fffff);
435 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);
436 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
437 "HW register value = 0x%x\n",
438 watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
439 }
440 }
441
442 if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
443 > hubbub->watermarks.c.cstate_pstate.pstate_change_ns) {
444 hubbub->watermarks.c.cstate_pstate.pstate_change_ns =
445 watermarks->c.cstate_pstate.pstate_change_ns;
446 prog_wm_value = convert_and_clamp(
447 watermarks->c.cstate_pstate.pstate_change_ns,
448 refclk_mhz, 0x1fffff);
449 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
450 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
451 "HW register value = 0x%x\n\n",
452 watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
453 }
454
455
456 if (safe_to_lower || watermarks->d.urgent_ns > hubbub->watermarks.d.urgent_ns) {
457 hubbub->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
458 prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
459 refclk_mhz, 0x1fffff);
460 REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);
461
462 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
463 "HW register value = 0x%x\n",
464 watermarks->d.urgent_ns, prog_wm_value);
465 }
466
467 if (safe_to_lower || watermarks->d.pte_meta_urgent_ns > hubbub->watermarks.d.pte_meta_urgent_ns) {
468 hubbub->watermarks.d.pte_meta_urgent_ns = watermarks->d.pte_meta_urgent_ns;
469 prog_wm_value = convert_and_clamp(watermarks->d.pte_meta_urgent_ns,
470 refclk_mhz, 0x1fffff);
471 REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value);
472 DC_LOG_BANDWIDTH_CALCS("PTE_META_URGENCY_WATERMARK_D calculated =%d\n"
473 "HW register value = 0x%x\n",
474 watermarks->d.pte_meta_urgent_ns, prog_wm_value);
475 }
476
477 if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) {
478 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
479 > hubbub->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
480 hubbub->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
481 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
482 prog_wm_value = convert_and_clamp(
483 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
484 refclk_mhz, 0x1fffff);
485 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
486 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
487 "HW register value = 0x%x\n",
488 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
489 }
490
491 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
492 > hubbub->watermarks.d.cstate_pstate.cstate_exit_ns) {
493 hubbub->watermarks.d.cstate_pstate.cstate_exit_ns =
494 watermarks->d.cstate_pstate.cstate_exit_ns;
495 prog_wm_value = convert_and_clamp(
496 watermarks->d.cstate_pstate.cstate_exit_ns,
497 refclk_mhz, 0x1fffff);
498 REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);
499 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
500 "HW register value = 0x%x\n",
501 watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
502 }
503 }
504
505 if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
506 > hubbub->watermarks.d.cstate_pstate.pstate_change_ns) {
507 hubbub->watermarks.d.cstate_pstate.pstate_change_ns =
508 watermarks->d.cstate_pstate.pstate_change_ns;
509 prog_wm_value = convert_and_clamp(
510 watermarks->d.cstate_pstate.pstate_change_ns,
511 refclk_mhz, 0x1fffff);
512 REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
513 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
514 "HW register value = 0x%x\n\n",
515 watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
516 }
517
518 REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL,
519 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
520 REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
521 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68);
522
523 REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
524 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0,
525 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en);
526
527#if 0
528 REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
529 DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1,
530 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1);
531#endif
532}
533
534void hubbub1_update_dchub(
535 struct hubbub *hubbub,
536 struct dchub_init_data *dh_data)
537{
538 if (REG(DCHUBBUB_SDPIF_FB_TOP) == 0) {
539 ASSERT(false);
540
541 return;
542 }
543
544 switch (dh_data->fb_mode) {
545 case FRAME_BUFFER_MODE_ZFB_ONLY:
546
547 REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP,
548 SDPIF_FB_TOP, 0);
549
550 REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE,
551 SDPIF_FB_BASE, 0x0FFFF);
552
553 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
554 SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22);
555
556 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
557 SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22);
558
559 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
560 SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr +
561 dh_data->zfb_size_in_byte - 1) >> 22);
562 break;
563 case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL:
564
565
566 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
567 SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22);
568
569 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
570 SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22);
571
572 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
573 SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr +
574 dh_data->zfb_size_in_byte - 1) >> 22);
575 break;
576 case FRAME_BUFFER_MODE_LOCAL_ONLY:
577
578 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE,
579 SDPIF_AGP_BASE, 0);
580
581 REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT,
582 SDPIF_AGP_BOT, 0X03FFFF);
583
584 REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP,
585 SDPIF_AGP_TOP, 0);
586 break;
587 default:
588 break;
589 }
590
591 dh_data->dchub_initialzied = true;
592 dh_data->dchub_info_valid = false;
593}
594
595void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub)
596{
597 uint32_t watermark_change_req;
598
599 REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
600 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, &watermark_change_req);
601
602 if (watermark_change_req)
603 watermark_change_req = 0;
604 else
605 watermark_change_req = 1;
606
607 REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL,
608 DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req);
609}
610
611void hubbub1_soft_reset(struct hubbub *hubbub, bool reset)
612{
613 uint32_t reset_en = reset ? 1 : 0;
614
615 REG_UPDATE(DCHUBBUB_SOFT_RESET,
616 DCHUBBUB_GLOBAL_SOFT_RESET, reset_en);
617}
618
619static bool hubbub1_dcc_support_swizzle(
620 enum swizzle_mode_values swizzle,
621 unsigned int bytes_per_element,
622 enum segment_order *segment_order_horz,
623 enum segment_order *segment_order_vert)
624{
625 bool standard_swizzle = false;
626 bool display_swizzle = false;
627
628 switch (swizzle) {
629 case DC_SW_4KB_S:
630 case DC_SW_64KB_S:
631 case DC_SW_VAR_S:
632 case DC_SW_4KB_S_X:
633 case DC_SW_64KB_S_X:
634 case DC_SW_VAR_S_X:
635 standard_swizzle = true;
636 break;
637 case DC_SW_4KB_D:
638 case DC_SW_64KB_D:
639 case DC_SW_VAR_D:
640 case DC_SW_4KB_D_X:
641 case DC_SW_64KB_D_X:
642 case DC_SW_VAR_D_X:
643 display_swizzle = true;
644 break;
645 default:
646 break;
647 }
648
649 if (bytes_per_element == 1 && standard_swizzle) {
650 *segment_order_horz = segment_order__contiguous;
651 *segment_order_vert = segment_order__na;
652 return true;
653 }
654 if (bytes_per_element == 2 && standard_swizzle) {
655 *segment_order_horz = segment_order__non_contiguous;
656 *segment_order_vert = segment_order__contiguous;
657 return true;
658 }
659 if (bytes_per_element == 4 && standard_swizzle) {
660 *segment_order_horz = segment_order__non_contiguous;
661 *segment_order_vert = segment_order__contiguous;
662 return true;
663 }
664 if (bytes_per_element == 8 && standard_swizzle) {
665 *segment_order_horz = segment_order__na;
666 *segment_order_vert = segment_order__contiguous;
667 return true;
668 }
669 if (bytes_per_element == 8 && display_swizzle) {
670 *segment_order_horz = segment_order__contiguous;
671 *segment_order_vert = segment_order__non_contiguous;
672 return true;
673 }
674
675 return false;
676}
677
678static bool hubbub1_dcc_support_pixel_format(
679 enum surface_pixel_format format,
680 unsigned int *bytes_per_element)
681{
682
683 switch (format) {
684 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
685 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
686 *bytes_per_element = 2;
687 return true;
688 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
689 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
690 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
691 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
692 *bytes_per_element = 4;
693 return true;
694 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
695 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
696 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
697 *bytes_per_element = 8;
698 return true;
699 default:
700 return false;
701 }
702}
703
704static void hubbub1_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,
705 unsigned int bytes_per_element)
706{
707
708
709 if (bytes_per_element == 1) {
710 *blk256_width = 16;
711 *blk256_height = 16;
712 } else if (bytes_per_element == 2) {
713 *blk256_width = 16;
714 *blk256_height = 8;
715 } else if (bytes_per_element == 4) {
716 *blk256_width = 8;
717 *blk256_height = 8;
718 } else if (bytes_per_element == 8) {
719 *blk256_width = 8;
720 *blk256_height = 4;
721 }
722}
723
724static void hubbub1_det_request_size(
725 unsigned int height,
726 unsigned int width,
727 unsigned int bpe,
728 bool *req128_horz_wc,
729 bool *req128_vert_wc)
730{
731 unsigned int detile_buf_size = 164 * 1024;
732
733 unsigned int blk256_height = 0;
734 unsigned int blk256_width = 0;
735 unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc;
736
737 hubbub1_get_blk256_size(&blk256_width, &blk256_height, bpe);
738
739 swath_bytes_horz_wc = height * blk256_height * bpe;
740 swath_bytes_vert_wc = width * blk256_width * bpe;
741
742 *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?
743 false :
744 true;
745
746 *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ?
747 false :
748 true;
749}
750
751static bool hubbub1_get_dcc_compression_cap(struct hubbub *hubbub,
752 const struct dc_dcc_surface_param *input,
753 struct dc_surface_dcc_cap *output)
754{
755 struct dc *dc = hubbub->ctx->dc;
756
757 enum dcc_control dcc_control;
758 unsigned int bpe;
759 enum segment_order segment_order_horz, segment_order_vert;
760 bool req128_horz_wc, req128_vert_wc;
761
762 memset(output, 0, sizeof(*output));
763
764 if (dc->debug.disable_dcc == DCC_DISABLE)
765 return false;
766
767 if (!hubbub->funcs->dcc_support_pixel_format(input->format, &bpe))
768 return false;
769
770 if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe,
771 &segment_order_horz, &segment_order_vert))
772 return false;
773
774 hubbub1_det_request_size(input->surface_size.height, input->surface_size.width,
775 bpe, &req128_horz_wc, &req128_vert_wc);
776
777 if (!req128_horz_wc && !req128_vert_wc) {
778 dcc_control = dcc_control__256_256_xxx;
779 } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
780 if (!req128_horz_wc)
781 dcc_control = dcc_control__256_256_xxx;
782 else if (segment_order_horz == segment_order__contiguous)
783 dcc_control = dcc_control__128_128_xxx;
784 else
785 dcc_control = dcc_control__256_64_64;
786 } else if (input->scan == SCAN_DIRECTION_VERTICAL) {
787 if (!req128_vert_wc)
788 dcc_control = dcc_control__256_256_xxx;
789 else if (segment_order_vert == segment_order__contiguous)
790 dcc_control = dcc_control__128_128_xxx;
791 else
792 dcc_control = dcc_control__256_64_64;
793 } else {
794 if ((req128_horz_wc &&
795 segment_order_horz == segment_order__non_contiguous) ||
796 (req128_vert_wc &&
797 segment_order_vert == segment_order__non_contiguous))
798
799 dcc_control = dcc_control__256_64_64;
800 else
801
802
803
804 dcc_control = dcc_control__128_128_xxx;
805 }
806
807 if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&
808 dcc_control != dcc_control__256_256_xxx)
809 return false;
810
811 switch (dcc_control) {
812 case dcc_control__256_256_xxx:
813 output->grph.rgb.max_uncompressed_blk_size = 256;
814 output->grph.rgb.max_compressed_blk_size = 256;
815 output->grph.rgb.independent_64b_blks = false;
816 break;
817 case dcc_control__128_128_xxx:
818 output->grph.rgb.max_uncompressed_blk_size = 128;
819 output->grph.rgb.max_compressed_blk_size = 128;
820 output->grph.rgb.independent_64b_blks = false;
821 break;
822 case dcc_control__256_64_64:
823 output->grph.rgb.max_uncompressed_blk_size = 256;
824 output->grph.rgb.max_compressed_blk_size = 64;
825 output->grph.rgb.independent_64b_blks = true;
826 break;
827 }
828
829 output->capable = true;
830 output->const_color_support = false;
831
832 return true;
833}
834
835static const struct hubbub_funcs hubbub1_funcs = {
836 .update_dchub = hubbub1_update_dchub,
837 .dcc_support_swizzle = hubbub1_dcc_support_swizzle,
838 .dcc_support_pixel_format = hubbub1_dcc_support_pixel_format,
839 .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap,
840};
841
842void hubbub1_construct(struct hubbub *hubbub,
843 struct dc_context *ctx,
844 const struct dcn_hubbub_registers *hubbub_regs,
845 const struct dcn_hubbub_shift *hubbub_shift,
846 const struct dcn_hubbub_mask *hubbub_mask)
847{
848 hubbub->ctx = ctx;
849
850 hubbub->funcs = &hubbub1_funcs;
851
852 hubbub->regs = hubbub_regs;
853 hubbub->shifts = hubbub_shift;
854 hubbub->masks = hubbub_mask;
855
856 hubbub->debug_test_index_pstate = 0x7;
857#if defined(CONFIG_DRM_AMD_DC_DCN1_01)
858 if (ctx->dce_version == DCN_VERSION_1_01)
859 hubbub->debug_test_index_pstate = 0xB;
860#endif
861}
862
863