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