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