Home | History | Annotate | Line # | Download | only in dcn10
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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