cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dcn10_hubbub.c (34784B)


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