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 <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 
44 void 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 
93 void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow)
94 {
95 	struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
96 
97 	/*
98 	 * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 1 means do not allow stutter
99 	 * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 means allow stutter
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 
107 bool 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 
119 bool hubbub1_verify_allow_pstate_change_high(
120 	struct hubbub *hubbub)
121 {
122 	struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
123 
124 	/* pstate latency is ~20us so if we wait over 40us and pstate allow
125 	 * still not asserted, we are probably stuck and going to hang
126 	 *
127 	 * TODO: Figure out why it takes ~100us on linux
128 	 * pstate takes around ~100us on linux. Unknown currently as to
129 	 * why it takes that long on linux
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; /* data collection */
134 	static bool forced_pstate_allow; /* help with revert wa */
135 
136 	unsigned int debug_data;
137 	unsigned int i;
138 
139 	if (forced_pstate_allow) {
140 		/* we hacked to force pstate allow to prevent hang last time
141 		 * we verify_allow_pstate_change_high.  so disable force
142 		 * here so we can check status
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 	/* RV2:
151 	 * dchubbubdebugind, at: 0xB
152 	 * description
153 	 * 0:     Pipe0 Plane0 Allow Pstate Change
154 	 * 1:     Pipe0 Plane1 Allow Pstate Change
155 	 * 2:     Pipe0 Cursor0 Allow Pstate Change
156 	 * 3:     Pipe0 Cursor1 Allow Pstate Change
157 	 * 4:     Pipe1 Plane0 Allow Pstate Change
158 	 * 5:     Pipe1 Plane1 Allow Pstate Change
159 	 * 6:     Pipe1 Cursor0 Allow Pstate Change
160 	 * 7:     Pipe1 Cursor1 Allow Pstate Change
161 	 * 8:     Pipe2 Plane0 Allow Pstate Change
162 	 * 9:     Pipe2 Plane1 Allow Pstate Change
163 	 * 10:    Pipe2 Cursor0 Allow Pstate Change
164 	 * 11:    Pipe2 Cursor1 Allow Pstate Change
165 	 * 12:    Pipe3 Plane0 Allow Pstate Change
166 	 * 13:    Pipe3 Plane1 Allow Pstate Change
167 	 * 14:    Pipe3 Cursor0 Allow Pstate Change
168 	 * 15:    Pipe3 Cursor1 Allow Pstate Change
169 	 * 16:    Pipe4 Plane0 Allow Pstate Change
170 	 * 17:    Pipe4 Plane1 Allow Pstate Change
171 	 * 18:    Pipe4 Cursor0 Allow Pstate Change
172 	 * 19:    Pipe4 Cursor1 Allow Pstate Change
173 	 * 20:    Pipe5 Plane0 Allow Pstate Change
174 	 * 21:    Pipe5 Plane1 Allow Pstate Change
175 	 * 22:    Pipe5 Cursor0 Allow Pstate Change
176 	 * 23:    Pipe5 Cursor1 Allow Pstate Change
177 	 * 24:    Pipe6 Plane0 Allow Pstate Change
178 	 * 25:    Pipe6 Plane1 Allow Pstate Change
179 	 * 26:    Pipe6 Cursor0 Allow Pstate Change
180 	 * 27:    Pipe6 Cursor1 Allow Pstate Change
181 	 * 28:    WB0 Allow Pstate Change
182 	 * 29:    WB1 Allow Pstate Change
183 	 * 30:    Arbiter's allow_pstate_change
184 	 * 31:    SOC pstate change request"
185 	 */
186 	/*DCN2.x:
187 	HUBBUB:DCHUBBUB_TEST_ARB_DEBUG10 DCHUBBUBDEBUGIND:0xB
188 	0: Pipe0 Plane0 Allow P-state Change
189 	1: Pipe0 Plane1 Allow P-state Change
190 	2: Pipe0 Cursor0 Allow P-state Change
191 	3: Pipe0 Cursor1 Allow P-state Change
192 	4: Pipe1 Plane0 Allow P-state Change
193 	5: Pipe1 Plane1 Allow P-state Change
194 	6: Pipe1 Cursor0 Allow P-state Change
195 	7: Pipe1 Cursor1 Allow P-state Change
196 	8: Pipe2 Plane0 Allow P-state Change
197 	9: Pipe2 Plane1 Allow P-state Change
198 	10: Pipe2 Cursor0 Allow P-state Change
199 	11: Pipe2 Cursor1 Allow P-state Change
200 	12: Pipe3 Plane0 Allow P-state Change
201 	13: Pipe3 Plane1 Allow P-state Change
202 	14: Pipe3 Cursor0 Allow P-state Change
203 	15: Pipe3 Cursor1 Allow P-state Change
204 	16: Pipe4 Plane0 Allow P-state Change
205 	17: Pipe4 Plane1 Allow P-state Change
206 	18: Pipe4 Cursor0 Allow P-state Change
207 	19: Pipe4 Cursor1 Allow P-state Change
208 	20: Pipe5 Plane0 Allow P-state Change
209 	21: Pipe5 Plane1 Allow P-state Change
210 	22: Pipe5 Cursor0 Allow P-state Change
211 	23: Pipe5 Cursor1 Allow P-state Change
212 	24: Pipe6 Plane0 Allow P-state Change
213 	25: Pipe6 Plane1 Allow P-state Change
214 	26: Pipe6 Cursor0 Allow P-state Change
215 	27: Pipe6 Cursor1 Allow P-state Change
216 	28: WB0 Allow P-state Change
217 	29: WB1 Allow P-state Change
218 	30: Arbiter`s Allow P-state Change
219 	31: SOC P-state Change request
220 	*/
221 	/* RV1:
222 	 * dchubbubdebugind, at: 0x7
223 	 * description "3-0:   Pipe0 cursor0 QOS
224 	 * 7-4:   Pipe1 cursor0 QOS
225 	 * 11-8:  Pipe2 cursor0 QOS
226 	 * 15-12: Pipe3 cursor0 QOS
227 	 * 16:    Pipe0 Plane0 Allow Pstate Change
228 	 * 17:    Pipe1 Plane0 Allow Pstate Change
229 	 * 18:    Pipe2 Plane0 Allow Pstate Change
230 	 * 19:    Pipe3 Plane0 Allow Pstate Change
231 	 * 20:    Pipe0 Plane1 Allow Pstate Change
232 	 * 21:    Pipe1 Plane1 Allow Pstate Change
233 	 * 22:    Pipe2 Plane1 Allow Pstate Change
234 	 * 23:    Pipe3 Plane1 Allow Pstate Change
235 	 * 24:    Pipe0 cursor0 Allow Pstate Change
236 	 * 25:    Pipe1 cursor0 Allow Pstate Change
237 	 * 26:    Pipe2 cursor0 Allow Pstate Change
238 	 * 27:    Pipe3 cursor0 Allow Pstate Change
239 	 * 28:    WB0 Allow Pstate Change
240 	 * 29:    WB1 Allow Pstate Change
241 	 * 30:    Arbiter's allow_pstate_change
242 	 * 31:    SOC pstate change request
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 	/* force pstate allow to prevent system hang
265 	 * and break to debugger to investigate
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 
278 static 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 
294 void 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 
303 void 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 	/* Repeat for water mark set A, B, C and D. */
313 	/* clock state A */
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 	/* clock state B */
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 	/* clock state C */
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 	/* clock state D */
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 
406 void 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 	/* clock state A */
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 	/* clock state B */
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 	/* clock state C */
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 	/* clock state D */
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 
533 void 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 	/* clock state A */
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 	/* clock state B */
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 	/* clock state C */
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 	/* clock state D */
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 
603 void 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 	 * Need to clamp to max of the register values (i.e. no wrap)
612 	 * for dcn1, all wm registers are 21-bit wide
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 
632 void 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 		/*should not come here*/
641 		return;
642 	}
643 	/* TODO: port code from dal2 */
644 	switch (dh_data->fb_mode) {
645 	case FRAME_BUFFER_MODE_ZFB_ONLY:
646 		/*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/
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 		/*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/
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 		/*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/
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 
695 void 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 
713 void 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 
723 static 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 
782 static bool hubbub1_dcc_support_pixel_format(
783 		enum surface_pixel_format format,
784 		unsigned int *bytes_per_element)
785 {
786 	/* DML: get_bytes_per_element */
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 
808 static void hubbub1_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,
809 		unsigned int bytes_per_element)
810 {
811 	/* copied from DML.  might want to refactor DML to leverage from DML */
812 	/* DML : get_blk256_size */
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 
828 static 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;  /* 164KB for DCN1.0 */
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 : /* full 256B request */
848 			true; /* half 128b request */
849 
850 	*req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ?
851 			false : /* full 256B request */
852 			true; /* half 128b request */
853 }
854 
855 static 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 	/* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */
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 			/* access_dir not known, must use most constraining */
905 			dcc_control = dcc_control__256_64_64;
906 		else
907 			/* reg128 is true for either horz and vert
908 			 * but segment_order is contiguous
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 
941 static 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 
952 void 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