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