brintos

brintos / linux-shallow public Read only

0
0
Text · 42.2 KiB · 7fb5523 Raw
1094 lines · c
1/*2 * Copyright 2016 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26 27#include "dcn30/dcn30_hubbub.h"28#include "dcn31_hubbub.h"29#include "dm_services.h"30#include "reg_helper.h"31 32 33#define CTX \34	hubbub2->base.ctx35#define DC_LOGGER \36	hubbub2->base.ctx->logger37#define REG(reg)\38	hubbub2->regs->reg39 40#undef FN41#define FN(reg_name, field_name) \42	hubbub2->shifts->field_name, hubbub2->masks->field_name43 44#ifdef NUM_VMID45#undef NUM_VMID46#endif47#define NUM_VMID 1648 49#define DCN31_CRB_SEGMENT_SIZE_KB 6450 51static void dcn31_init_crb(struct hubbub *hubbub)52{53	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);54 55	REG_GET(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT,56		&hubbub2->det0_size);57 58	REG_GET(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT,59		&hubbub2->det1_size);60 61	REG_GET(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT,62		&hubbub2->det2_size);63 64	REG_GET(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT,65		&hubbub2->det3_size);66 67	REG_GET(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT,68		&hubbub2->compbuf_size_segments);69 70	REG_SET_2(COMPBUF_RESERVED_SPACE, 0,71			COMPBUF_RESERVED_SPACE_64B, hubbub2->pixel_chunk_size / 32,72			COMPBUF_RESERVED_SPACE_ZS, hubbub2->pixel_chunk_size / 128);73	REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x17F);74}75 76static void dcn31_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int det_buffer_size_in_kbyte)77{78	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);79 80	unsigned int det_size_segments = (det_buffer_size_in_kbyte + DCN31_CRB_SEGMENT_SIZE_KB - 1) / DCN31_CRB_SEGMENT_SIZE_KB;81 82	switch (hubp_inst) {83	case 0:84		REG_UPDATE(DCHUBBUB_DET0_CTRL,85					DET0_SIZE, det_size_segments);86		hubbub2->det0_size = det_size_segments;87		break;88	case 1:89		REG_UPDATE(DCHUBBUB_DET1_CTRL,90					DET1_SIZE, det_size_segments);91		hubbub2->det1_size = det_size_segments;92		break;93	case 2:94		REG_UPDATE(DCHUBBUB_DET2_CTRL,95					DET2_SIZE, det_size_segments);96		hubbub2->det2_size = det_size_segments;97		break;98	case 3:99		REG_UPDATE(DCHUBBUB_DET3_CTRL,100					DET3_SIZE, det_size_segments);101		hubbub2->det3_size = det_size_segments;102		break;103	default:104		break;105	}106	DC_LOG_DEBUG("Set DET%d to %d segments\n", hubp_inst, det_size_segments);107	/* Should never be hit, if it is we have an erroneous hw config*/108	ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size109			+ hubbub2->det3_size + hubbub2->compbuf_size_segments <= hubbub2->crb_size_segs);110}111 112static void dcn31_wait_for_det_apply(struct hubbub *hubbub, int hubp_inst)113{114	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);115 116	switch (hubp_inst) {117	case 0:118		REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1000, 30);119		break;120	case 1:121		REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1000, 30);122		break;123	case 2:124		REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1000, 30);125		break;126	case 3:127		REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1000, 30);128		break;129	default:130		break;131	}132}133 134static void dcn31_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase)135{136	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);137	unsigned int compbuf_size_segments = (compbuf_size_kb + DCN31_CRB_SEGMENT_SIZE_KB - 1) / DCN31_CRB_SEGMENT_SIZE_KB;138 139	if (safe_to_increase || compbuf_size_segments <= hubbub2->compbuf_size_segments) {140		if (compbuf_size_segments > hubbub2->compbuf_size_segments) {141			REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100);142			REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100);143			REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100);144			REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100);145		}146		/* Should never be hit, if it is we have an erroneous hw config*/147		ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size148				+ hubbub2->det3_size + compbuf_size_segments <= hubbub2->crb_size_segs);149		REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_segments);150		hubbub2->compbuf_size_segments = compbuf_size_segments;151		ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &compbuf_size_segments) && !compbuf_size_segments);152	}153}154 155static uint32_t convert_and_clamp(156	uint32_t wm_ns,157	uint32_t refclk_mhz,158	uint32_t clamp_value)159{160	uint32_t ret_val = 0;161	ret_val = wm_ns * refclk_mhz;162	ret_val /= 1000;163 164	if (ret_val > clamp_value) {165		/* clamping WMs is abnormal, unexpected and may lead to underflow*/166		ASSERT(0);167		ret_val = clamp_value;168	}169 170	return ret_val;171}172 173static bool hubbub31_program_urgent_watermarks(174		struct hubbub *hubbub,175		union dcn_watermark_set *watermarks,176		unsigned int refclk_mhz,177		bool safe_to_lower)178{179	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);180	uint32_t prog_wm_value;181	bool wm_pending = false;182 183	/* Repeat for water mark set A, B, C and D. */184	/* clock state A */185	if (safe_to_lower || watermarks->a.urgent_ns > hubbub2->watermarks.a.urgent_ns) {186		hubbub2->watermarks.a.urgent_ns = watermarks->a.urgent_ns;187		prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,188				refclk_mhz, 0x3fff);189		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,190				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);191 192		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"193			"HW register value = 0x%x\n",194			watermarks->a.urgent_ns, prog_wm_value);195	} else if (watermarks->a.urgent_ns < hubbub2->watermarks.a.urgent_ns)196		wm_pending = true;197 198	/* determine the transfer time for a quantity of data for a particular requestor.*/199	if (safe_to_lower || watermarks->a.frac_urg_bw_flip200			> hubbub2->watermarks.a.frac_urg_bw_flip) {201		hubbub2->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;202 203		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,204				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip);205	} else if (watermarks->a.frac_urg_bw_flip206			< hubbub2->watermarks.a.frac_urg_bw_flip)207		wm_pending = true;208 209	if (safe_to_lower || watermarks->a.frac_urg_bw_nom210			> hubbub2->watermarks.a.frac_urg_bw_nom) {211		hubbub2->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;212 213		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,214				DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);215	} else if (watermarks->a.frac_urg_bw_nom216			< hubbub2->watermarks.a.frac_urg_bw_nom)217		wm_pending = true;218 219	if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub2->watermarks.a.urgent_latency_ns) {220		hubbub2->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;221		prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,222				refclk_mhz, 0x3fff);223		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,224				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);225	} else if (watermarks->a.urgent_latency_ns < hubbub2->watermarks.a.urgent_latency_ns)226		wm_pending = true;227 228	/* clock state B */229	if (safe_to_lower || watermarks->b.urgent_ns > hubbub2->watermarks.b.urgent_ns) {230		hubbub2->watermarks.b.urgent_ns = watermarks->b.urgent_ns;231		prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,232				refclk_mhz, 0x3fff);233		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,234				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);235 236		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"237			"HW register value = 0x%x\n",238			watermarks->b.urgent_ns, prog_wm_value);239	} else if (watermarks->b.urgent_ns < hubbub2->watermarks.b.urgent_ns)240		wm_pending = true;241 242	/* determine the transfer time for a quantity of data for a particular requestor.*/243	if (safe_to_lower || watermarks->b.frac_urg_bw_flip244			> hubbub2->watermarks.b.frac_urg_bw_flip) {245		hubbub2->watermarks.b.frac_urg_bw_flip = watermarks->b.frac_urg_bw_flip;246 247		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,248				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->b.frac_urg_bw_flip);249	} else if (watermarks->b.frac_urg_bw_flip250			< hubbub2->watermarks.b.frac_urg_bw_flip)251		wm_pending = true;252 253	if (safe_to_lower || watermarks->b.frac_urg_bw_nom254			> hubbub2->watermarks.b.frac_urg_bw_nom) {255		hubbub2->watermarks.b.frac_urg_bw_nom = watermarks->b.frac_urg_bw_nom;256 257		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,258				DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->b.frac_urg_bw_nom);259	} else if (watermarks->b.frac_urg_bw_nom260			< hubbub2->watermarks.b.frac_urg_bw_nom)261		wm_pending = true;262 263	if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub2->watermarks.b.urgent_latency_ns) {264		hubbub2->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;265		prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,266				refclk_mhz, 0x3fff);267		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,268				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);269	} else if (watermarks->b.urgent_latency_ns < hubbub2->watermarks.b.urgent_latency_ns)270		wm_pending = true;271 272	/* clock state C */273	if (safe_to_lower || watermarks->c.urgent_ns > hubbub2->watermarks.c.urgent_ns) {274		hubbub2->watermarks.c.urgent_ns = watermarks->c.urgent_ns;275		prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,276				refclk_mhz, 0x3fff);277		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,278				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);279 280		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"281			"HW register value = 0x%x\n",282			watermarks->c.urgent_ns, prog_wm_value);283	} else if (watermarks->c.urgent_ns < hubbub2->watermarks.c.urgent_ns)284		wm_pending = true;285 286	/* determine the transfer time for a quantity of data for a particular requestor.*/287	if (safe_to_lower || watermarks->c.frac_urg_bw_flip288			> hubbub2->watermarks.c.frac_urg_bw_flip) {289		hubbub2->watermarks.c.frac_urg_bw_flip = watermarks->c.frac_urg_bw_flip;290 291		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,292				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->c.frac_urg_bw_flip);293	} else if (watermarks->c.frac_urg_bw_flip294			< hubbub2->watermarks.c.frac_urg_bw_flip)295		wm_pending = true;296 297	if (safe_to_lower || watermarks->c.frac_urg_bw_nom298			> hubbub2->watermarks.c.frac_urg_bw_nom) {299		hubbub2->watermarks.c.frac_urg_bw_nom = watermarks->c.frac_urg_bw_nom;300 301		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,302				DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->c.frac_urg_bw_nom);303	} else if (watermarks->c.frac_urg_bw_nom304			< hubbub2->watermarks.c.frac_urg_bw_nom)305		wm_pending = true;306 307	if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub2->watermarks.c.urgent_latency_ns) {308		hubbub2->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns;309		prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns,310				refclk_mhz, 0x3fff);311		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,312				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value);313	} else if (watermarks->c.urgent_latency_ns < hubbub2->watermarks.c.urgent_latency_ns)314		wm_pending = true;315 316	/* clock state D */317	if (safe_to_lower || watermarks->d.urgent_ns > hubbub2->watermarks.d.urgent_ns) {318		hubbub2->watermarks.d.urgent_ns = watermarks->d.urgent_ns;319		prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,320				refclk_mhz, 0x3fff);321		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,322				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);323 324		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"325			"HW register value = 0x%x\n",326			watermarks->d.urgent_ns, prog_wm_value);327	} else if (watermarks->d.urgent_ns < hubbub2->watermarks.d.urgent_ns)328		wm_pending = true;329 330	/* determine the transfer time for a quantity of data for a particular requestor.*/331	if (safe_to_lower || watermarks->d.frac_urg_bw_flip332			> hubbub2->watermarks.d.frac_urg_bw_flip) {333		hubbub2->watermarks.d.frac_urg_bw_flip = watermarks->d.frac_urg_bw_flip;334 335		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,336				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->d.frac_urg_bw_flip);337	} else if (watermarks->d.frac_urg_bw_flip338			< hubbub2->watermarks.d.frac_urg_bw_flip)339		wm_pending = true;340 341	if (safe_to_lower || watermarks->d.frac_urg_bw_nom342			> hubbub2->watermarks.d.frac_urg_bw_nom) {343		hubbub2->watermarks.d.frac_urg_bw_nom = watermarks->d.frac_urg_bw_nom;344 345		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,346				DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->d.frac_urg_bw_nom);347	} else if (watermarks->d.frac_urg_bw_nom348			< hubbub2->watermarks.d.frac_urg_bw_nom)349		wm_pending = true;350 351	if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub2->watermarks.d.urgent_latency_ns) {352		hubbub2->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;353		prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,354				refclk_mhz, 0x3fff);355		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,356				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);357	} else if (watermarks->d.urgent_latency_ns < hubbub2->watermarks.d.urgent_latency_ns)358		wm_pending = true;359 360	return wm_pending;361}362 363static bool hubbub31_program_stutter_watermarks(364		struct hubbub *hubbub,365		union dcn_watermark_set *watermarks,366		unsigned int refclk_mhz,367		bool safe_to_lower)368{369	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);370	uint32_t prog_wm_value;371	bool wm_pending = false;372 373	/* clock state A */374	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns375			> hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {376		hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =377				watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;378		prog_wm_value = convert_and_clamp(379				watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,380				refclk_mhz, 0xfffff);381		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,382				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);383		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"384			"HW register value = 0x%x\n",385			watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);386	} else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns387			< hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)388		wm_pending = true;389 390	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns391			> hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns) {392		hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns =393				watermarks->a.cstate_pstate.cstate_exit_ns;394		prog_wm_value = convert_and_clamp(395				watermarks->a.cstate_pstate.cstate_exit_ns,396				refclk_mhz, 0xfffff);397		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,398				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);399		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"400			"HW register value = 0x%x\n",401			watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);402	} else if (watermarks->a.cstate_pstate.cstate_exit_ns403			< hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns)404		wm_pending = true;405 406	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns407			> hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns) {408		hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns =409				watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns;410		prog_wm_value = convert_and_clamp(411				watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns,412				refclk_mhz, 0xfffff);413		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0,414				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, prog_wm_value);415		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n"416			"HW register value = 0x%x\n",417			watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);418	} else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns419			< hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns)420		wm_pending = true;421 422	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_z8_ns423			> hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns) {424		hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns =425				watermarks->a.cstate_pstate.cstate_exit_z8_ns;426		prog_wm_value = convert_and_clamp(427				watermarks->a.cstate_pstate.cstate_exit_z8_ns,428				refclk_mhz, 0xfffff);429		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0,430				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, prog_wm_value);431		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n"432			"HW register value = 0x%x\n",433			watermarks->a.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);434	} else if (watermarks->a.cstate_pstate.cstate_exit_z8_ns435			< hubbub2->watermarks.a.cstate_pstate.cstate_exit_z8_ns)436		wm_pending = true;437 438	/* clock state B */439	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns440			> hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {441		hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =442				watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;443		prog_wm_value = convert_and_clamp(444				watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,445				refclk_mhz, 0xfffff);446		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,447				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);448		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"449			"HW register value = 0x%x\n",450			watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);451	} else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns452			< hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)453		wm_pending = true;454 455	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns456			> hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns) {457		hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns =458				watermarks->b.cstate_pstate.cstate_exit_ns;459		prog_wm_value = convert_and_clamp(460				watermarks->b.cstate_pstate.cstate_exit_ns,461				refclk_mhz, 0xfffff);462		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,463				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);464		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"465			"HW register value = 0x%x\n",466			watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);467	} else if (watermarks->b.cstate_pstate.cstate_exit_ns468			< hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns)469		wm_pending = true;470 471	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns472			> hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns) {473		hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns =474				watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns;475		prog_wm_value = convert_and_clamp(476				watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns,477				refclk_mhz, 0xfffff);478		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0,479				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, prog_wm_value);480		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n"481			"HW register value = 0x%x\n",482			watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);483	} else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns484			< hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns)485		wm_pending = true;486 487	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_z8_ns488			> hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns) {489		hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns =490				watermarks->b.cstate_pstate.cstate_exit_z8_ns;491		prog_wm_value = convert_and_clamp(492				watermarks->b.cstate_pstate.cstate_exit_z8_ns,493				refclk_mhz, 0xfffff);494		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0,495				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, prog_wm_value);496		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n"497			"HW register value = 0x%x\n",498			watermarks->b.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);499	} else if (watermarks->b.cstate_pstate.cstate_exit_z8_ns500			< hubbub2->watermarks.b.cstate_pstate.cstate_exit_z8_ns)501		wm_pending = true;502 503	/* clock state C */504	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns505			> hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {506		hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =507				watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;508		prog_wm_value = convert_and_clamp(509				watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,510				refclk_mhz, 0xfffff);511		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,512				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);513		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"514			"HW register value = 0x%x\n",515			watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);516	} else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns517			< hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)518		wm_pending = true;519 520	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns521			> hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns) {522		hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns =523				watermarks->c.cstate_pstate.cstate_exit_ns;524		prog_wm_value = convert_and_clamp(525				watermarks->c.cstate_pstate.cstate_exit_ns,526				refclk_mhz, 0xfffff);527		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,528				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);529		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"530			"HW register value = 0x%x\n",531			watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);532	} else if (watermarks->c.cstate_pstate.cstate_exit_ns533			< hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns)534		wm_pending = true;535 536	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns537			> hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns) {538		hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns =539				watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns;540		prog_wm_value = convert_and_clamp(541				watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns,542				refclk_mhz, 0xfffff);543		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0,544				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, prog_wm_value);545		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n"546			"HW register value = 0x%x\n",547			watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);548	} else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns549			< hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns)550		wm_pending = true;551 552	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_z8_ns553			> hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns) {554		hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns =555				watermarks->c.cstate_pstate.cstate_exit_z8_ns;556		prog_wm_value = convert_and_clamp(557				watermarks->c.cstate_pstate.cstate_exit_z8_ns,558				refclk_mhz, 0xfffff);559		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0,560				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, prog_wm_value);561		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n"562			"HW register value = 0x%x\n",563			watermarks->c.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);564	} else if (watermarks->c.cstate_pstate.cstate_exit_z8_ns565			< hubbub2->watermarks.c.cstate_pstate.cstate_exit_z8_ns)566		wm_pending = true;567 568	/* clock state D */569	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns570			> hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {571		hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =572				watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;573		prog_wm_value = convert_and_clamp(574				watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,575				refclk_mhz, 0xfffff);576		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,577				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);578		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"579			"HW register value = 0x%x\n",580			watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);581	} else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns582			< hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)583		wm_pending = true;584 585	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns586			> hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns) {587		hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns =588				watermarks->d.cstate_pstate.cstate_exit_ns;589		prog_wm_value = convert_and_clamp(590				watermarks->d.cstate_pstate.cstate_exit_ns,591				refclk_mhz, 0xfffff);592		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,593				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);594		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"595			"HW register value = 0x%x\n",596			watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);597	} else if (watermarks->d.cstate_pstate.cstate_exit_ns598			< hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns)599		wm_pending = true;600 601	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns602			> hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns) {603		hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns =604				watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns;605		prog_wm_value = convert_and_clamp(606				watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns,607				refclk_mhz, 0xfffff);608		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0,609				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, prog_wm_value);610		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n"611			"HW register value = 0x%x\n",612			watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns, prog_wm_value);613	} else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns614			< hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns)615		wm_pending = true;616 617	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_z8_ns618			> hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns) {619		hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns =620				watermarks->d.cstate_pstate.cstate_exit_z8_ns;621		prog_wm_value = convert_and_clamp(622				watermarks->d.cstate_pstate.cstate_exit_z8_ns,623				refclk_mhz, 0xfffff);624		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0,625				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, prog_wm_value);626		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n"627			"HW register value = 0x%x\n",628			watermarks->d.cstate_pstate.cstate_exit_z8_ns, prog_wm_value);629	} else if (watermarks->d.cstate_pstate.cstate_exit_z8_ns630			< hubbub2->watermarks.d.cstate_pstate.cstate_exit_z8_ns)631		wm_pending = true;632 633	return wm_pending;634}635 636static bool hubbub31_program_pstate_watermarks(637		struct hubbub *hubbub,638		union dcn_watermark_set *watermarks,639		unsigned int refclk_mhz,640		bool safe_to_lower)641{642	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);643	uint32_t prog_wm_value;644 645	bool wm_pending = false;646 647	/* clock state A */648	if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns649			> hubbub2->watermarks.a.cstate_pstate.pstate_change_ns) {650		hubbub2->watermarks.a.cstate_pstate.pstate_change_ns =651				watermarks->a.cstate_pstate.pstate_change_ns;652		prog_wm_value = convert_and_clamp(653				watermarks->a.cstate_pstate.pstate_change_ns,654				refclk_mhz, 0xffff);655		REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0,656				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);657		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"658			"HW register value = 0x%x\n\n",659			watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);660	} else if (watermarks->a.cstate_pstate.pstate_change_ns661			< hubbub2->watermarks.a.cstate_pstate.pstate_change_ns)662		wm_pending = true;663 664	/* clock state B */665	if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns666			> hubbub2->watermarks.b.cstate_pstate.pstate_change_ns) {667		hubbub2->watermarks.b.cstate_pstate.pstate_change_ns =668				watermarks->b.cstate_pstate.pstate_change_ns;669		prog_wm_value = convert_and_clamp(670				watermarks->b.cstate_pstate.pstate_change_ns,671				refclk_mhz, 0xffff);672		REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0,673				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);674		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"675			"HW register value = 0x%x\n\n",676			watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);677	} else if (watermarks->b.cstate_pstate.pstate_change_ns678			< hubbub2->watermarks.b.cstate_pstate.pstate_change_ns)679		wm_pending = false;680 681	/* clock state C */682	if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns683			> hubbub2->watermarks.c.cstate_pstate.pstate_change_ns) {684		hubbub2->watermarks.c.cstate_pstate.pstate_change_ns =685				watermarks->c.cstate_pstate.pstate_change_ns;686		prog_wm_value = convert_and_clamp(687				watermarks->c.cstate_pstate.pstate_change_ns,688				refclk_mhz, 0xffff);689		REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0,690				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);691		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"692			"HW register value = 0x%x\n\n",693			watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);694	} else if (watermarks->c.cstate_pstate.pstate_change_ns695			< hubbub2->watermarks.c.cstate_pstate.pstate_change_ns)696		wm_pending = true;697 698	/* clock state D */699	if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns700			> hubbub2->watermarks.d.cstate_pstate.pstate_change_ns) {701		hubbub2->watermarks.d.cstate_pstate.pstate_change_ns =702				watermarks->d.cstate_pstate.pstate_change_ns;703		prog_wm_value = convert_and_clamp(704				watermarks->d.cstate_pstate.pstate_change_ns,705				refclk_mhz, 0xffff);706		REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0,707				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);708		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"709			"HW register value = 0x%x\n\n",710			watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);711	} else if (watermarks->d.cstate_pstate.pstate_change_ns712			< hubbub2->watermarks.d.cstate_pstate.pstate_change_ns)713		wm_pending = true;714 715	return wm_pending;716}717 718static bool hubbub31_program_watermarks(719		struct hubbub *hubbub,720		union dcn_watermark_set *watermarks,721		unsigned int refclk_mhz,722		bool safe_to_lower)723{724	bool wm_pending = false;725 726	if (hubbub31_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))727		wm_pending = true;728 729	if (hubbub31_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))730		wm_pending = true;731 732	if (hubbub31_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))733		wm_pending = true;734 735	/*736	 * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric.737	 * If the memory controller is fully utilized and the DCHub requestors are738	 * well ahead of their amortized schedule, then it is safe to prevent the next winner739	 * from being committed and sent to the fabric.740	 * The utilization of the memory controller is approximated by ensuring that741	 * the number of outstanding requests is greater than a threshold specified742	 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized schedule,743	 * the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles.744	 *745	 * TODO: Revisit request limit after figure out right number. request limit for RM isn't decided yet, set maximum value (0x1FF)746	 * to turn off it for now.747	 */748	/*REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,749			DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);750	REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,751			DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);*/752 753	hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);754	return wm_pending;755}756 757static void hubbub3_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,758		unsigned int bytes_per_element)759{760	/* copied from DML.  might want to refactor DML to leverage from DML */761	/* DML : get_blk256_size */762	if (bytes_per_element == 1) {763		*blk256_width = 16;764		*blk256_height = 16;765	} else if (bytes_per_element == 2) {766		*blk256_width = 16;767		*blk256_height = 8;768	} else if (bytes_per_element == 4) {769		*blk256_width = 8;770		*blk256_height = 8;771	} else if (bytes_per_element == 8) {772		*blk256_width = 8;773		*blk256_height = 4;774	}775}776 777static void hubbub31_det_request_size(778		unsigned int detile_buf_size,779		unsigned int height,780		unsigned int width,781		unsigned int bpe,782		bool *req128_horz_wc,783		bool *req128_vert_wc)784{785	unsigned int blk256_height = 0;786	unsigned int blk256_width = 0;787	unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc;788 789	hubbub3_get_blk256_size(&blk256_width, &blk256_height, bpe);790 791	swath_bytes_horz_wc = width * blk256_height * bpe;792	swath_bytes_vert_wc = height * blk256_width * bpe;793 794	*req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?795			false : /* full 256B request */796			true; /* half 128b request */797 798	*req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ?799			false : /* full 256B request */800			true; /* half 128b request */801}802 803static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub,804		const struct dc_dcc_surface_param *input,805		struct dc_surface_dcc_cap *output)806{807	struct dc *dc = hubbub->ctx->dc;808	enum dcc_control dcc_control;809	unsigned int bpe;810	enum segment_order segment_order_horz, segment_order_vert;811	bool req128_horz_wc, req128_vert_wc;812 813	memset(output, 0, sizeof(*output));814 815	if (dc->debug.disable_dcc == DCC_DISABLE)816		return false;817 818	if (!hubbub->funcs->dcc_support_pixel_format(input->format,819			&bpe))820		return false;821 822	if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe,823			&segment_order_horz, &segment_order_vert))824		return false;825 826	hubbub31_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size,827			input->surface_size.height,  input->surface_size.width,828			bpe, &req128_horz_wc, &req128_vert_wc);829 830	if (!req128_horz_wc && !req128_vert_wc) {831		dcc_control = dcc_control__256_256_xxx;832	} else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {833		if (!req128_horz_wc)834			dcc_control = dcc_control__256_256_xxx;835		else if (segment_order_horz == segment_order__contiguous)836			dcc_control = dcc_control__128_128_xxx;837		else838			dcc_control = dcc_control__256_64_64;839	} else if (input->scan == SCAN_DIRECTION_VERTICAL) {840		if (!req128_vert_wc)841			dcc_control = dcc_control__256_256_xxx;842		else if (segment_order_vert == segment_order__contiguous)843			dcc_control = dcc_control__128_128_xxx;844		else845			dcc_control = dcc_control__256_64_64;846	} else {847		if ((req128_horz_wc &&848			segment_order_horz == segment_order__non_contiguous) ||849			(req128_vert_wc &&850			segment_order_vert == segment_order__non_contiguous))851			/* access_dir not known, must use most constraining */852			dcc_control = dcc_control__256_64_64;853		else854			/* reg128 is true for either horz and vert855			 * but segment_order is contiguous856			 */857			dcc_control = dcc_control__128_128_xxx;858	}859 860	/* Exception for 64KB_R_X */861	if ((bpe == 2) && (input->swizzle_mode == DC_SW_64KB_R_X))862		dcc_control = dcc_control__128_128_xxx;863 864	if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&865		dcc_control != dcc_control__256_256_xxx)866		return false;867 868	switch (dcc_control) {869	case dcc_control__256_256:870	case dcc_control__256_256_xxx:871		output->grph.rgb.max_uncompressed_blk_size = 256;872		output->grph.rgb.max_compressed_blk_size = 256;873		output->grph.rgb.independent_64b_blks = false;874		output->grph.rgb.dcc_controls.dcc_256_256_unconstrained = 1;875		output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;876		break;877	case dcc_control__128_128_xxx:878		output->grph.rgb.max_uncompressed_blk_size = 128;879		output->grph.rgb.max_compressed_blk_size = 128;880		output->grph.rgb.independent_64b_blks = false;881		output->grph.rgb.dcc_controls.dcc_128_128_uncontrained = 1;882		output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;883		break;884	case dcc_control__256_64_64:885	case dcc_control__256_64:886		output->grph.rgb.max_uncompressed_blk_size = 256;887		output->grph.rgb.max_compressed_blk_size = 64;888		output->grph.rgb.independent_64b_blks = true;889		output->grph.rgb.dcc_controls.dcc_256_64_64 = 1;890		break;891	case dcc_control__256_128_128:892	case dcc_control__256_128:893		output->grph.rgb.max_uncompressed_blk_size = 256;894		output->grph.rgb.max_compressed_blk_size = 128;895		output->grph.rgb.independent_64b_blks = false;896		output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;897		break;898	}899	output->capable = true;900	output->const_color_support = true;901 902	return true;903}904 905int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub,906		struct dcn_hubbub_phys_addr_config *pa_config)907{908	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);909	struct dcn_vmid_page_table_config phys_config;910 911	REG_SET(DCN_VM_FB_LOCATION_BASE, 0,912			FB_BASE, pa_config->system_aperture.fb_base >> 24);913	REG_SET(DCN_VM_FB_LOCATION_TOP, 0,914			FB_TOP, pa_config->system_aperture.fb_top >> 24);915	REG_SET(DCN_VM_FB_OFFSET, 0,916			FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);917	REG_SET(DCN_VM_AGP_BOT, 0,918			AGP_BOT, pa_config->system_aperture.agp_bot >> 24);919	REG_SET(DCN_VM_AGP_TOP, 0,920			AGP_TOP, pa_config->system_aperture.agp_top >> 24);921	REG_SET(DCN_VM_AGP_BASE, 0,922			AGP_BASE, pa_config->system_aperture.agp_base >> 24);923 924	if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {925		phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;926		phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;927		phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;928		phys_config.depth = 0;929		phys_config.block_size = 0;930		// Init VMID 0 based on PA config931		dcn20_vmid_setup(&hubbub2->vmid[0], &phys_config);932 933		dcn20_vmid_setup(&hubbub2->vmid[15], &phys_config);934	}935 936	dcn21_dchvm_init(hubbub);937 938	return NUM_VMID;939}940 941static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub,942		unsigned int dccg_ref_freq_inKhz,943		unsigned int *dchub_ref_freq_inKhz)944{945	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);946	uint32_t ref_div = 0;947	uint32_t ref_en = 0;948	unsigned int dc_refclk_khz = 24000;949 950	REG_GET_2(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, &ref_div,951			DCHUBBUB_GLOBAL_TIMER_ENABLE, &ref_en);952 953	if (ref_en) {954		if (ref_div == 2)955			*dchub_ref_freq_inKhz = dc_refclk_khz / 2;956		else957			*dchub_ref_freq_inKhz = dc_refclk_khz;958 959		/*960		 * The external Reference Clock may change based on the board or961		 * platform requirements and the programmable integer divide must962		 * be programmed to provide a suitable DLG RefClk frequency between963		 * a minimum of 20MHz and maximum of 50MHz964		 */965		if (*dchub_ref_freq_inKhz < 20000 || *dchub_ref_freq_inKhz > 50000)966			ASSERT_CRITICAL(false);967 968		return;969	} else {970		*dchub_ref_freq_inKhz = dc_refclk_khz;971 972		// HUBBUB global timer must be enabled.973		ASSERT_CRITICAL(false);974		return;975	}976}977 978static bool hubbub31_verify_allow_pstate_change_high(struct hubbub *hubbub)979{980	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);981 982	/*983	 * Pstate latency is ~20us so if we wait over 40us and pstate allow984	 * still not asserted, we are probably stuck and going to hang985	 */986	const unsigned int pstate_wait_timeout_us = 100;987	const unsigned int pstate_wait_expected_timeout_us = 40;988 989	static unsigned int max_sampled_pstate_wait_us; /* data collection */990	static bool forced_pstate_allow; /* help with revert wa */991 992	unsigned int debug_data = 0;993	unsigned int i;994 995	if (forced_pstate_allow) {996		/* we hacked to force pstate allow to prevent hang last time997		 * we verify_allow_pstate_change_high.  so disable force998		 * here so we can check status999		 */1000		REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,1001			     DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,1002			     DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0);1003		forced_pstate_allow = false;1004	}1005 1006	REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub2->debug_test_index_pstate);1007 1008	for (i = 0; i < pstate_wait_timeout_us; i++) {1009		debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA);1010 1011		/* Debug bit is specific to ASIC. */1012		if (debug_data & (1 << 26)) {1013			if (i > pstate_wait_expected_timeout_us)1014				DC_LOG_WARNING("pstate took longer than expected ~%dus\n", i);1015			return true;1016		}1017		if (max_sampled_pstate_wait_us < i)1018			max_sampled_pstate_wait_us = i;1019 1020		udelay(1);1021	}1022 1023	/* force pstate allow to prevent system hang1024	 * and break to debugger to investigate1025	 */1026	REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,1027		     DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1,1028		     DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);1029	forced_pstate_allow = true;1030 1031	DC_LOG_WARNING("pstate TEST_DEBUG_DATA: 0x%X\n",1032			debug_data);1033 1034	return false;1035}1036 1037void hubbub31_init(struct hubbub *hubbub)1038{1039	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);1040 1041	/*Enable clock gate*/1042	if (hubbub->ctx->dc->debug.disable_clock_gate) {1043		/*done in hwseq*/1044		/*REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);*/1045		REG_UPDATE_2(DCHUBBUB_CLOCK_CNTL,1046				DISPCLK_R_DCHUBBUB_GATE_DIS, 1,1047				DCFCLK_R_DCHUBBUB_GATE_DIS, 1);1048	}1049 1050	/*1051	only the DCN will determine when to connect the SDP port1052	*/1053	REG_UPDATE(DCHUBBUB_SDPIF_CFG0,	SDPIF_PORT_CONTROL, 1);1054}1055static const struct hubbub_funcs hubbub31_funcs = {1056	.update_dchub = hubbub2_update_dchub,1057	.init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx,1058	.init_vm_ctx = hubbub2_init_vm_ctx,1059	.dcc_support_swizzle = hubbub3_dcc_support_swizzle,1060	.dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,1061	.get_dcc_compression_cap = hubbub31_get_dcc_compression_cap,1062	.wm_read_state = hubbub21_wm_read_state,1063	.get_dchub_ref_freq = hubbub31_get_dchub_ref_freq,1064	.program_watermarks = hubbub31_program_watermarks,1065	.allow_self_refresh_control = hubbub1_allow_self_refresh_control,1066	.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,1067	.verify_allow_pstate_change_high = hubbub31_verify_allow_pstate_change_high,1068	.program_det_size = dcn31_program_det_size,1069	.wait_for_det_apply = dcn31_wait_for_det_apply,1070	.program_compbuf_size = dcn31_program_compbuf_size,1071	.init_crb = dcn31_init_crb,1072	.hubbub_read_state = hubbub2_read_state,1073};1074 1075void hubbub31_construct(struct dcn20_hubbub *hubbub31,1076	struct dc_context *ctx,1077	const struct dcn_hubbub_registers *hubbub_regs,1078	const struct dcn_hubbub_shift *hubbub_shift,1079	const struct dcn_hubbub_mask *hubbub_mask,1080	int det_size_kb,1081	int pixel_chunk_size_kb,1082	int config_return_buffer_size_kb)1083{1084 1085	hubbub3_construct(hubbub31, ctx, hubbub_regs, hubbub_shift, hubbub_mask);1086	hubbub31->base.funcs = &hubbub31_funcs;1087	hubbub31->detile_buf_size = det_size_kb * 1024;1088	hubbub31->pixel_chunk_size = pixel_chunk_size_kb * 1024;1089	hubbub31->crb_size_segs = config_return_buffer_size_kb / DCN31_CRB_SEGMENT_SIZE_KB;1090 1091	hubbub31->debug_test_index_pstate = 0x6;1092}1093 1094