brintos

brintos / linux-shallow public Read only

0
0
Text · 45.7 KiB · 37d26fa Raw
1239 lines · c
1/*2 * Copyright 2023 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 "dcn401_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 44static void dcn401_init_crb(struct hubbub *hubbub)45{46	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);47 48	REG_GET(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT,49		&hubbub2->det0_size);50 51	REG_GET(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT,52		&hubbub2->det1_size);53 54	REG_GET(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT,55		&hubbub2->det2_size);56 57	REG_GET(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT,58		&hubbub2->det3_size);59 60	REG_GET(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT,61		&hubbub2->compbuf_size_segments);62 63	REG_SET(COMPBUF_RESERVED_SPACE, 0,64			COMPBUF_RESERVED_SPACE_64B, hubbub2->pixel_chunk_size / 32); // 256 64Bytes65}66 67bool hubbub401_program_urgent_watermarks(68		struct hubbub *hubbub,69		union dcn_watermark_set *watermarks,70		unsigned int refclk_mhz,71		bool safe_to_lower)72{73	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);74	bool wm_pending = false;75 76	/* Repeat for water mark set A and B */77	/* clock state A */78	if (safe_to_lower || watermarks->dcn4x.a.urgent > hubbub2->watermarks.dcn4x.a.urgent) {79		hubbub2->watermarks.dcn4x.a.urgent = watermarks->dcn4x.a.urgent;80		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,81				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, watermarks->dcn4x.a.urgent);82		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"83			"HW register value = 0x%x\n",84			watermarks->dcn4x.a.urgent, watermarks->dcn4x.a.urgent);85	} else if (watermarks->dcn4x.a.urgent < hubbub2->watermarks.dcn4x.a.urgent)86		wm_pending = true;87 88	/* determine the transfer time for a quantity of data for a particular requestor.*/89	if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_flip90			> hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) {91		hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip = watermarks->dcn4x.a.frac_urg_bw_flip;92		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,93				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->dcn4x.a.frac_urg_bw_flip);94	} else if (watermarks->dcn4x.a.frac_urg_bw_flip95			< hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip)96		wm_pending = true;97 98	if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_nom99			> hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) {100		hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom = watermarks->dcn4x.a.frac_urg_bw_nom;101		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,102				DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->dcn4x.a.frac_urg_bw_nom);103	} else if (watermarks->dcn4x.a.frac_urg_bw_nom104			< hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom)105		wm_pending = true;106 107	if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_mall108			> hubbub2->watermarks.dcn4x.a.frac_urg_bw_mall) {109		hubbub2->watermarks.dcn4x.a.frac_urg_bw_mall = watermarks->dcn4x.a.frac_urg_bw_mall;110		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_MALL_A, 0,111				DCHUBBUB_ARB_FRAC_URG_BW_MALL_A, watermarks->dcn4x.a.frac_urg_bw_mall);112	} else if (watermarks->dcn4x.a.frac_urg_bw_mall < hubbub2->watermarks.dcn4x.a.frac_urg_bw_mall)113		wm_pending = true;114 115	if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) {116		hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem = watermarks->dcn4x.a.refcyc_per_trip_to_mem;117		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,118				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, watermarks->dcn4x.a.refcyc_per_trip_to_mem);119	} else if (watermarks->dcn4x.a.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem)120		wm_pending = true;121 122	if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_meta_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_meta_trip_to_mem) {123		hubbub2->watermarks.dcn4x.a.refcyc_per_meta_trip_to_mem = watermarks->dcn4x.a.refcyc_per_meta_trip_to_mem;124		REG_SET(DCHUBBUB_ARB_REFCYC_PER_META_TRIP_A, 0,125				DCHUBBUB_ARB_REFCYC_PER_META_TRIP_A, watermarks->dcn4x.a.refcyc_per_meta_trip_to_mem);126	} else if (watermarks->dcn4x.a.refcyc_per_meta_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_meta_trip_to_mem)127		wm_pending = true;128 129 130	/* clock state B */131	if (safe_to_lower || watermarks->dcn4x.b.urgent > hubbub2->watermarks.dcn4x.b.urgent) {132		hubbub2->watermarks.dcn4x.b.urgent = watermarks->dcn4x.b.urgent;133		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,134				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, watermarks->dcn4x.b.urgent);135		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"136			"HW register value = 0x%x\n",137			watermarks->dcn4x.b.urgent, watermarks->dcn4x.b.urgent);138	} else if (watermarks->dcn4x.b.urgent < hubbub2->watermarks.dcn4x.b.urgent)139		wm_pending = true;140 141	/* determine the transfer time for a quantity of data for a particular requestor.*/142	if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_flip143			> hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) {144		hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip = watermarks->dcn4x.b.frac_urg_bw_flip;145		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,146				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->dcn4x.b.frac_urg_bw_flip);147	} else if (watermarks->dcn4x.b.frac_urg_bw_flip148			< hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip)149		wm_pending = true;150 151	if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_nom152			> hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) {153		hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom = watermarks->dcn4x.b.frac_urg_bw_nom;154		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,155				DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->dcn4x.b.frac_urg_bw_nom);156	} else if (watermarks->dcn4x.b.frac_urg_bw_nom157			< hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom)158		wm_pending = true;159 160	if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_mall161			> hubbub2->watermarks.dcn4x.b.frac_urg_bw_mall) {162		hubbub2->watermarks.dcn4x.b.frac_urg_bw_mall = watermarks->dcn4x.b.frac_urg_bw_mall;163		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_MALL_B, 0,164				DCHUBBUB_ARB_FRAC_URG_BW_MALL_B, watermarks->dcn4x.b.frac_urg_bw_mall);165	} else if (watermarks->dcn4x.b.frac_urg_bw_mall < hubbub2->watermarks.dcn4x.b.frac_urg_bw_mall)166		wm_pending = true;167 168	if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) {169		hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem = watermarks->dcn4x.b.refcyc_per_trip_to_mem;170		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,171				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, watermarks->dcn4x.b.refcyc_per_trip_to_mem);172	} else if (watermarks->dcn4x.b.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem)173		wm_pending = true;174 175	if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_meta_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_meta_trip_to_mem) {176		hubbub2->watermarks.dcn4x.b.refcyc_per_meta_trip_to_mem = watermarks->dcn4x.b.refcyc_per_meta_trip_to_mem;177		REG_SET(DCHUBBUB_ARB_REFCYC_PER_META_TRIP_B, 0,178				DCHUBBUB_ARB_REFCYC_PER_META_TRIP_B, watermarks->dcn4x.b.refcyc_per_meta_trip_to_mem);179	} else if (watermarks->dcn4x.b.refcyc_per_meta_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_meta_trip_to_mem)180		wm_pending = true;181 182	return wm_pending;183}184 185bool hubbub401_program_stutter_watermarks(186		struct hubbub *hubbub,187		union dcn_watermark_set *watermarks,188		unsigned int refclk_mhz,189		bool safe_to_lower)190{191	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);192	bool wm_pending = false;193 194	/* clock state A */195	if (safe_to_lower || watermarks->dcn4x.a.sr_enter196			> hubbub2->watermarks.dcn4x.a.sr_enter) {197		hubbub2->watermarks.dcn4x.a.sr_enter =198				watermarks->dcn4x.a.sr_enter;199		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,200				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, watermarks->dcn4x.a.sr_enter);201		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"202			"HW register value = 0x%x\n",203			watermarks->dcn4x.a.sr_enter, watermarks->dcn4x.a.sr_enter);204		// On dGPU Z states are N/A, so program all other 3 Stutter Enter wm A with the same value205		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_A, 0,206				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_A, watermarks->dcn4x.a.sr_enter);207		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_A, 0,208				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_A, watermarks->dcn4x.a.sr_enter);209		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_A, 0,210				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_A, watermarks->dcn4x.a.sr_enter);211 212	} else if (watermarks->dcn4x.a.sr_enter213			< hubbub2->watermarks.dcn4x.a.sr_enter)214		wm_pending = true;215 216	if (safe_to_lower || watermarks->dcn4x.a.sr_exit217			> hubbub2->watermarks.dcn4x.a.sr_exit) {218		hubbub2->watermarks.dcn4x.a.sr_exit =219				watermarks->dcn4x.a.sr_exit;220		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,221				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, watermarks->dcn4x.a.sr_exit);222		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"223			"HW register value = 0x%x\n",224			watermarks->dcn4x.a.sr_exit, watermarks->dcn4x.a.sr_exit);225		// On dGPU Z states are N/A, so program all other 3 Stutter Exit wm A with the same value226		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_A, 0,227				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_A, watermarks->dcn4x.a.sr_exit);228		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_A, 0,229				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_A, watermarks->dcn4x.a.sr_exit);230		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_A, 0,231				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_A, watermarks->dcn4x.a.sr_exit);232 233	} else if (watermarks->dcn4x.a.sr_exit234			< hubbub2->watermarks.dcn4x.a.sr_exit)235		wm_pending = true;236 237	/* clock state B */238	if (safe_to_lower || watermarks->dcn4x.b.sr_enter239			> hubbub2->watermarks.dcn4x.b.sr_enter) {240		hubbub2->watermarks.dcn4x.b.sr_enter =241				watermarks->dcn4x.b.sr_enter;242		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,243				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, watermarks->dcn4x.b.sr_enter);244		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"245			"HW register value = 0x%x\n",246			watermarks->dcn4x.b.sr_enter, watermarks->dcn4x.b.sr_enter);247		// On dGPU Z states are N/A, so program all other 3 Stutter Enter wm A with the same value248		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_B, 0,249				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_B, watermarks->dcn4x.b.sr_enter);250		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_B, 0,251				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_B, watermarks->dcn4x.b.sr_enter);252		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_B, 0,253				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_B, watermarks->dcn4x.b.sr_enter);254 255	} else if (watermarks->dcn4x.b.sr_enter256			< hubbub2->watermarks.dcn4x.b.sr_enter)257		wm_pending = true;258 259	if (safe_to_lower || watermarks->dcn4x.b.sr_exit260			> hubbub2->watermarks.dcn4x.b.sr_exit) {261		hubbub2->watermarks.dcn4x.b.sr_exit =262				watermarks->dcn4x.b.sr_exit;263		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,264				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, watermarks->dcn4x.b.sr_exit);265		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"266			"HW register value = 0x%x\n",267			watermarks->dcn4x.b.sr_exit, watermarks->dcn4x.b.sr_exit);268		// On dGPU Z states are N/A, so program all other 3 Stutter Exit wm A with the same value269		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_B, 0,270				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_B, watermarks->dcn4x.b.sr_exit);271		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_B, 0,272				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_B, watermarks->dcn4x.b.sr_exit);273		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_B, 0,274				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_B, watermarks->dcn4x.b.sr_exit);275 276	} else if (watermarks->dcn4x.b.sr_exit277			< hubbub2->watermarks.dcn4x.b.sr_exit)278		wm_pending = true;279 280	return wm_pending;281}282 283 284bool hubbub401_program_pstate_watermarks(285		struct hubbub *hubbub,286		union dcn_watermark_set *watermarks,287		unsigned int refclk_mhz,288		bool safe_to_lower)289{290	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);291	bool wm_pending = false;292 293	/* Section for UCLK_PSTATE_CHANGE_WATERMARKS */294	/* clock state A */295	if (safe_to_lower || watermarks->dcn4x.a.uclk_pstate296			> hubbub2->watermarks.dcn4x.a.uclk_pstate) {297		hubbub2->watermarks.dcn4x.a.uclk_pstate =298				watermarks->dcn4x.a.uclk_pstate;299		REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0,300				DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.uclk_pstate);301		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"302			"HW register value = 0x%x\n\n",303			watermarks->dcn4x.a.uclk_pstate, watermarks->dcn4x.a.uclk_pstate);304	} else if (watermarks->dcn4x.a.uclk_pstate305			< hubbub2->watermarks.dcn4x.a.uclk_pstate)306		wm_pending = true;307 308	/* clock state B */309	if (safe_to_lower || watermarks->dcn4x.b.uclk_pstate310			> hubbub2->watermarks.dcn4x.b.uclk_pstate) {311		hubbub2->watermarks.dcn4x.b.uclk_pstate =312				watermarks->dcn4x.b.uclk_pstate;313		REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0,314				DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.uclk_pstate);315		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"316			"HW register value = 0x%x\n\n",317			watermarks->dcn4x.b.uclk_pstate, watermarks->dcn4x.b.uclk_pstate);318	} else if (watermarks->dcn4x.b.uclk_pstate319			< hubbub2->watermarks.dcn4x.b.uclk_pstate)320		wm_pending = true;321 322	/* Section for UCLK_PSTATE_CHANGE_WATERMARKS1 (DUMMY_PSTATE/TEMP_READ/PPT) */323	if (safe_to_lower || watermarks->dcn4x.a.temp_read_or_ppt324			> hubbub2->watermarks.dcn4x.a.temp_read_or_ppt) {325		hubbub2->watermarks.dcn4x.a.temp_read_or_ppt =326				watermarks->dcn4x.a.temp_read_or_ppt;327		REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_A, 0,328				DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_A, watermarks->dcn4x.a.temp_read_or_ppt);329		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK1_A calculated =%d\n"330			"HW register value = 0x%x\n\n",331			watermarks->dcn4x.a.temp_read_or_ppt, watermarks->dcn4x.a.temp_read_or_ppt);332	} else if (watermarks->dcn4x.a.temp_read_or_ppt333			< hubbub2->watermarks.dcn4x.a.temp_read_or_ppt)334		wm_pending = true;335 336	/* clock state B */337	if (safe_to_lower || watermarks->dcn4x.b.temp_read_or_ppt338			> hubbub2->watermarks.dcn4x.b.temp_read_or_ppt) {339		hubbub2->watermarks.dcn4x.b.temp_read_or_ppt =340				watermarks->dcn4x.b.temp_read_or_ppt;341		REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_B, 0,342				DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_B, watermarks->dcn4x.b.temp_read_or_ppt);343		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK1_B calculated =%d\n"344			"HW register value = 0x%x\n\n",345			watermarks->dcn4x.b.temp_read_or_ppt, watermarks->dcn4x.b.temp_read_or_ppt);346	} else if (watermarks->dcn4x.b.temp_read_or_ppt347			< hubbub2->watermarks.dcn4x.b.temp_read_or_ppt)348		wm_pending = true;349 350	/* Section for FCLK_PSTATE_CHANGE_WATERMARKS */351	/* clock state A */352	if (safe_to_lower || watermarks->dcn4x.a.fclk_pstate353			> hubbub2->watermarks.dcn4x.a.fclk_pstate) {354		hubbub2->watermarks.dcn4x.a.fclk_pstate =355				watermarks->dcn4x.a.fclk_pstate;356		REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0,357				DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.fclk_pstate);358		DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_A calculated =%d\n"359			"HW register value = 0x%x\n\n",360			watermarks->dcn4x.a.fclk_pstate, watermarks->dcn4x.a.fclk_pstate);361	} else if (watermarks->dcn4x.a.fclk_pstate362			< hubbub2->watermarks.dcn4x.a.fclk_pstate)363		wm_pending = true;364 365	/* clock state B */366	if (safe_to_lower || watermarks->dcn4x.b.fclk_pstate367			> hubbub2->watermarks.dcn4x.b.fclk_pstate) {368		hubbub2->watermarks.dcn4x.b.fclk_pstate =369				watermarks->dcn4x.b.fclk_pstate;370		REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0,371				DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.fclk_pstate);372		DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_B calculated =%d\n"373			"HW register value = 0x%x\n\n",374			watermarks->dcn4x.b.fclk_pstate, watermarks->dcn4x.b.fclk_pstate);375	} else if (watermarks->dcn4x.b.fclk_pstate376			< hubbub2->watermarks.dcn4x.b.fclk_pstate)377		wm_pending = true;378 379	/* Section for FCLK_CHANGE_WATERMARKS1 (DUMMY_PSTATE/TEMP_READ/PPT) */380	if (safe_to_lower || watermarks->dcn4x.a.temp_read_or_ppt381			> hubbub2->watermarks.dcn4x.a.temp_read_or_ppt) {382		hubbub2->watermarks.dcn4x.a.temp_read_or_ppt =383				watermarks->dcn4x.a.temp_read_or_ppt;384		REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_A, 0,385				DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_A, watermarks->dcn4x.a.temp_read_or_ppt);386		DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK1_A calculated =%d\n"387			"HW register value = 0x%x\n\n",388			watermarks->dcn4x.a.temp_read_or_ppt, watermarks->dcn4x.a.temp_read_or_ppt);389	} else if (watermarks->dcn4x.a.temp_read_or_ppt390			< hubbub2->watermarks.dcn4x.a.temp_read_or_ppt)391		wm_pending = true;392 393	/* clock state B */394	if (safe_to_lower || watermarks->dcn4x.b.temp_read_or_ppt395			> hubbub2->watermarks.dcn4x.b.temp_read_or_ppt) {396		hubbub2->watermarks.dcn4x.b.temp_read_or_ppt =397				watermarks->dcn4x.b.temp_read_or_ppt;398		REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_B, 0,399				DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_B, watermarks->dcn4x.b.temp_read_or_ppt);400		DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK1_B calculated =%d\n"401			"HW register value = 0x%x\n\n",402			watermarks->dcn4x.b.temp_read_or_ppt, watermarks->dcn4x.b.temp_read_or_ppt);403	} else if (watermarks->dcn4x.b.temp_read_or_ppt404			< hubbub2->watermarks.dcn4x.b.temp_read_or_ppt)405		wm_pending = true;406 407	return wm_pending;408}409 410 411bool hubbub401_program_usr_watermarks(412		struct hubbub *hubbub,413		union dcn_watermark_set *watermarks,414		unsigned int refclk_mhz,415		bool safe_to_lower)416{417	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);418	bool wm_pending = false;419 420	/* clock state A */421	if (safe_to_lower || watermarks->dcn4x.a.usr422			> hubbub2->watermarks.dcn4x.a.usr) {423		hubbub2->watermarks.dcn4x.a.usr = watermarks->dcn4x.a.usr;424		REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0,425				DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, watermarks->dcn4x.a.usr);426		DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_A calculated =%d\n"427			"HW register value = 0x%x\n\n",428			watermarks->dcn4x.a.usr, watermarks->dcn4x.a.usr);429	} else if (watermarks->dcn4x.a.usr430			< hubbub2->watermarks.dcn4x.a.usr)431		wm_pending = true;432 433	/* clock state B */434	if (safe_to_lower || watermarks->dcn4x.b.usr435			> hubbub2->watermarks.dcn4x.b.usr) {436		hubbub2->watermarks.dcn4x.b.usr = watermarks->dcn4x.b.usr;437		REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0,438				DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, watermarks->dcn4x.b.usr);439		DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_B calculated =%d\n"440			"HW register value = 0x%x\n\n",441			watermarks->dcn4x.b.usr, watermarks->dcn4x.b.usr);442	} else if (watermarks->dcn4x.b.usr443			< hubbub2->watermarks.dcn4x.b.usr)444		wm_pending = true;445 446	return wm_pending;447}448 449 450static bool hubbub401_program_watermarks(451		struct hubbub *hubbub,452		union dcn_watermark_set *watermarks,453		unsigned int refclk_mhz,454		bool safe_to_lower)455{456	bool wm_pending = false;457 458	if (hubbub401_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))459		wm_pending = true;460 461	if (hubbub401_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))462		wm_pending = true;463 464	if (hubbub401_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))465		wm_pending = true;466 467	if (hubbub401_program_usr_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))468		wm_pending = true;469 470	/*471	 * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric.472	 * If the memory controller is fully utilized and the DCHub requestors are473	 * well ahead of their amortized schedule, then it is safe to prevent the next winner474	 * from being committed and sent to the fabric.475	 * The utilization of the memory controller is approximated by ensuring that476	 * the number of outstanding requests is greater than a threshold specified477	 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized478	 * schedule, the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles.479	 *480	 * TODO: Revisit request limit after figure out right number. request limit for RM isn't decided yet,481	 *  set maximum value (0x1FF) to turn off it for now.482	 */483	/*REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,484			DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);485		REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,486			DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);487	*/488 489	hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);490 491	hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow);492 493	return wm_pending;494}495 496/* Copy values from WM set A to all other sets */497static void hubbub401_init_watermarks(struct hubbub *hubbub)498{499	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);500	uint32_t reg;501 502	reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);503	REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg);504 505	reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A);506	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg);507 508	reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A);509	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg);510 511	reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_MALL_A);512	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_MALL_B, reg);513 514	reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A);515	REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg);516 517	reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_META_TRIP_A);518	REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_META_TRIP_B, reg);519 520	reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);521	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg);522	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_A, reg);523	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK1_B, reg);524	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_A, reg);525	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK2_B, reg);526	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_A, reg);527	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK3_B, reg);528 529	reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);530	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg);531	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_A, reg);532	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK1_B, reg);533	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_A, reg);534	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK2_B, reg);535	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_A, reg);536	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK3_B, reg);537 538	reg = REG_READ(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A);539	REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, reg);540 541	reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A);542	REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, reg);543	reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_A);544	REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK1_B, reg);545 546	reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A);547	REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, reg);548	reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_A);549	REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK1_B, reg);550}551 552static void hubbub401_wm_read_state(struct hubbub *hubbub,553		struct dcn_hubbub_wm *wm)554{555	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);556	struct dcn_hubbub_wm_set *s;557 558	memset(wm, 0, sizeof(struct dcn_hubbub_wm));559 560	s = &wm->sets[0];561	s->wm_set = 0;562	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A,563			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent);564 565	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A,566			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter);567 568	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A,569			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);570 571	REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A,572			 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_change);573 574	REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A,575			 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, &s->usr_retrain);576 577	REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A,578			 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, &s->fclk_pstate_change);579 580	s = &wm->sets[1];581	s->wm_set = 1;582	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B,583			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent);584 585	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B,586			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter);587 588	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B,589			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);590 591	REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B,592			DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_change);593 594	REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B,595			 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, &s->usr_retrain);596 597	REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B,598			DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, &s->fclk_pstate_change);599}600 601bool hubbub401_dcc_support_swizzle(602		enum swizzle_mode_addr3_values swizzle,603		unsigned int plane_pitch,604		unsigned int bytes_per_element,605		enum segment_order *segment_order_horz,606		enum segment_order *segment_order_vert)607{608	bool swizzle_supported = false;609 610	switch (swizzle) {611	case DC_ADDR3_SW_LINEAR:612		if ((plane_pitch * bytes_per_element) % 256 == 0)613			swizzle_supported = true;614		break;615	case DC_ADDR3_SW_64KB_2D:616	case DC_ADDR3_SW_256KB_2D:617		swizzle_supported = true;618		break;619	default:620		swizzle_supported = false;621		break;622	}623 624	if (swizzle_supported) {625		if (bytes_per_element == 1) {626			*segment_order_horz = segment_order__contiguous;627			*segment_order_vert = segment_order__non_contiguous;628			return true;629		}630		if (bytes_per_element == 2) {631			*segment_order_horz = segment_order__non_contiguous;632			*segment_order_vert = segment_order__contiguous;633			return true;634		}635		if (bytes_per_element == 4) {636			*segment_order_horz = segment_order__contiguous;637			*segment_order_vert = segment_order__non_contiguous;638			return true;639		}640		if (bytes_per_element == 8) {641			*segment_order_horz = segment_order__contiguous;642			*segment_order_vert = segment_order__non_contiguous;643			return true;644		}645	}646 647	return false;648}649 650bool hubbub401_dcc_support_pixel_format(651		enum surface_pixel_format format,652		unsigned int *plane0_bpe,653		unsigned int *plane1_bpe)654{655	switch (format) {656	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:657	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:658		*plane0_bpe = 2;659		*plane1_bpe = 0;660		return true;661	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:662	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:663		*plane0_bpe = 1;664		*plane1_bpe = 2;665		return true;666	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:667	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:668	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:669	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:670	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:671	case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:672	case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:673	case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:674	case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:675	case SURFACE_PIXEL_FORMAT_GRPH_RGBE:676		*plane0_bpe = 4;677		*plane1_bpe = 0;678		return true;679	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:680		*plane0_bpe = 4;681		*plane1_bpe = 1;682		return true;683	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:684	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:685		*plane0_bpe = 2;686		*plane1_bpe = 4;687		return true;688	case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:689	case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:690	case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:691		*plane0_bpe = 4;692		*plane1_bpe = 0;693		return true;694	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:695	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:696	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:697	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:698		*plane0_bpe = 8;699		*plane1_bpe = 0;700		return true;701	default:702		return false;703	}704}705 706void hubbub401_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height,707		unsigned int bytes_per_element)708{709	if (bytes_per_element == 1) {710		*blk256_width = 16;711		*blk256_height = 16;712	} else if (bytes_per_element == 2) {713		*blk256_width = 16;714		*blk256_height = 8;715	} else if (bytes_per_element == 4) {716		*blk256_width = 8;717		*blk256_height = 8;718	} else if (bytes_per_element == 8) {719		*blk256_width = 8;720		*blk256_height = 4;721	}722}723 724void hubbub401_det_request_size(725		unsigned int detile_buf_size,726		enum surface_pixel_format format,727		unsigned int p0_height,728		unsigned int p0_width,729		unsigned int p0_bpe,730		unsigned int p1_height,731		unsigned int p1_width,732		unsigned int p1_bpe,733		bool *p0_req128_horz_wc,734		bool *p0_req128_vert_wc,735		bool *p1_req128_horz_wc,736		bool *p1_req128_vert_wc)737{738	unsigned int blk256_height = 0;739	unsigned int blk256_width = 0;740	unsigned int p0_swath_bytes_horz_wc, p0_swath_bytes_vert_wc;741	unsigned int p1_swath_bytes_horz_wc, p1_swath_bytes_vert_wc;742 743	//For plane0744	hubbub401_get_blk256_size(&blk256_width, &blk256_height, p0_bpe);745 746	p0_swath_bytes_horz_wc = p0_width * blk256_height * p0_bpe;747	p0_swath_bytes_vert_wc = p0_height * blk256_width * p0_bpe;748 749	*p0_req128_horz_wc = (2 * p0_swath_bytes_horz_wc <= detile_buf_size) ?750			false : /* full 256B request */751			true; /* half 128b request */752 753	*p0_req128_vert_wc = (2 * p0_swath_bytes_vert_wc <= detile_buf_size) ?754			false : /* full 256B request */755			true; /* half 128b request */756 757	/*For dual planes needs to be considered together */758	if (p1_bpe) {759		hubbub401_get_blk256_size(&blk256_width, &blk256_height, p1_bpe);760 761		p1_swath_bytes_horz_wc = p1_width * blk256_height * p1_bpe;762		p1_swath_bytes_vert_wc = p1_height * blk256_width * p1_bpe;763 764		switch (format) {765		default:766			/* No any adjustment needed*/767			break;768		case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:769		case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:770			/* Packing at the ratio of 3:2 is supported before the detile buffer771			 * for YUV420 video with 10bpc (P010). Need to adjust for that.772			 */773			p0_swath_bytes_horz_wc = (((p0_swath_bytes_horz_wc * 2) / 3 + 255) / 256) * 256;774			p0_swath_bytes_vert_wc = (((p0_swath_bytes_vert_wc * 2) / 3 + 255) / 256) * 256;775			p1_swath_bytes_horz_wc = (((p1_swath_bytes_horz_wc * 2) / 3 + 255) / 256) * 256;776			p1_swath_bytes_vert_wc = (((p1_swath_bytes_vert_wc * 2) / 3 + 255) / 256) * 256;777			break;778		}779 780		*p0_req128_horz_wc = *p1_req128_horz_wc = (2 * p0_swath_bytes_horz_wc +781			2 * p1_swath_bytes_horz_wc <= detile_buf_size) ?782				false : /* full 256B request */783				true; /* half 128B request */784 785		*p0_req128_vert_wc = *p1_req128_vert_wc = (2 * p0_swath_bytes_vert_wc +786			2 * p1_swath_bytes_vert_wc <= detile_buf_size) ?787				false : /* full 256B request */788				true; /* half 128B request */789 790		/* If 128B requests are true, meaning 2 full swaths of data cannot fit791		 * in de-tile buffer, check if one plane can use 256B request while792		 * the other plane is using 128B requests793		 */794		if (*p0_req128_horz_wc) {795			// If ratio around 1:1 between p0 and p1 try to recalulate if p0 can use 256B796			if (p0_swath_bytes_horz_wc <= p1_swath_bytes_horz_wc + p1_swath_bytes_horz_wc / 2) {797 798				*p0_req128_horz_wc = (2 * p0_swath_bytes_horz_wc + p1_swath_bytes_horz_wc <= detile_buf_size) ?799					false : /* full 256B request */800					true; /* half 128b request */801 802			} else {803				/* ratio about 2:1 between p0 and p1, try to recalulate if p1 can use 256B */804				*p1_req128_horz_wc = (p0_swath_bytes_horz_wc + 2 * p1_swath_bytes_horz_wc <= detile_buf_size) ?805					false : /* full 256B request */806					true; /* half 128b request */807			}808		}809 810		if (*p0_req128_vert_wc) {811			// If ratio around 1:1 between p0 and p1 try to recalulate if p0 can use 256B812			if (p0_swath_bytes_vert_wc <= p1_swath_bytes_vert_wc + p1_swath_bytes_vert_wc / 2) {813 814				*p0_req128_vert_wc = (2 * p0_swath_bytes_vert_wc + p1_swath_bytes_vert_wc <= detile_buf_size) ?815					false : /* full 256B request */816					true; /* half 128b request */817 818			} else {819				/* ratio about 2:1 between p0 and p1, try to recalulate if p1 can use 256B */820				*p1_req128_vert_wc = (p0_swath_bytes_vert_wc + 2 * p1_swath_bytes_vert_wc <= detile_buf_size) ?821					false : /* full 256B request */822					true; /* half 128b request */823			}824		}825	}826}827bool hubbub401_get_dcc_compression_cap(struct hubbub *hubbub,828		const struct dc_dcc_surface_param *input,829		struct dc_surface_dcc_cap *output)830{831	struct dc *dc = hubbub->ctx->dc;832	const unsigned int max_dcc_plane_width = dc->caps.dcc_plane_width_limit;833	/* DCN4_Programming_Guide_DCHUB.docx, Section 5.11.2.2 */834	enum dcc_control dcc_control;835	unsigned int plane0_bpe, plane1_bpe;836	enum segment_order segment_order_horz, segment_order_vert;837	enum segment_order p1_segment_order_horz, p1_segment_order_vert;838	bool req128_horz_wc, req128_vert_wc;839	unsigned int plane0_width = 0, plane0_height = 0, plane1_width = 0, plane1_height = 0;840	bool p1_req128_horz_wc, p1_req128_vert_wc, is_dual_plane;841 842	memset(output, 0, sizeof(*output));843 844	if (dc->debug.disable_dcc == DCC_DISABLE)845		return false;846 847	/* Conservatively disable DCC for cases where ODM4:1 may be required. */848	if (max_dcc_plane_width != 0 &&849			(input->surface_size.width > max_dcc_plane_width || input->plane1_size.width > max_dcc_plane_width))850		return false;851 852	switch (input->format) {853	default:854		is_dual_plane = false;855 856		plane1_width = 0;857		plane1_height = 0;858 859		if (input->surface_size.width > 6144 + 16)860			plane0_width = 6160;861		else862			plane0_width = input->surface_size.width;863 864		if (input->surface_size.height > 6144 + 16)865			plane0_height = 6160;866		else867			plane0_height = input->surface_size.height;868 869		break;870	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:871	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:872	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:873	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:874		is_dual_plane = true;875 876		if (input->surface_size.width > 7680 + 16)877			plane0_width = 7696;878		else879			plane0_width = input->surface_size.width;880 881		if (input->surface_size.height > 4320 + 16)882			plane0_height = 4336;883		else884			plane0_height = input->surface_size.height;885 886		if (input->plane1_size.width > 7680 + 16)887			plane1_width = 7696 / 2;888		else889			plane1_width = input->plane1_size.width;890 891		if (input->plane1_size.height > 4320 + 16)892			plane1_height = 4336 / 2;893		else894			plane1_height = input->plane1_size.height;895 896		break;897 898	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:899		is_dual_plane = true;900 901		if (input->surface_size.width > 5120 + 16)902			plane0_width = 5136;903		else904			plane0_width = input->surface_size.width;905 906		if (input->surface_size.height > 5120 + 16)907			plane0_height = 5136;908		else909			plane0_height = input->surface_size.height;910 911		if (input->plane1_size.width > 5120 + 16)912			plane1_width = 5136;913		else914			plane1_width = input->plane1_size.width;915 916		if (input->plane1_size.height > 5120 + 16)917			plane1_height = 5136;918		else919			plane1_height = input->plane1_size.height;920 921		break;922	}923 924	if (!hubbub->funcs->dcc_support_pixel_format_plane0_plane1(input->format,925			&plane0_bpe, &plane1_bpe))926		return false;927 928	/* Find plane0 DCC Controls */929	if (!is_dual_plane) {930 931		if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,932				input->plane0_pitch, plane0_bpe,933				&segment_order_horz, &segment_order_vert))934			return false;935 936		hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format,937				plane0_height, plane0_width, plane0_bpe,938				plane1_height, plane1_width, plane1_bpe,939				&req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc);940 941		if (!req128_horz_wc && !req128_vert_wc) {942			dcc_control = dcc_control__256_256;943		} else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {944			if (!req128_horz_wc)945				dcc_control = dcc_control__256_256;946			else if (segment_order_horz == segment_order__contiguous)947				dcc_control = dcc_control__256_128;948			else949				dcc_control = dcc_control__256_64;950		} else if (input->scan == SCAN_DIRECTION_VERTICAL) {951			if (!req128_vert_wc)952				dcc_control = dcc_control__256_256;953			else if (segment_order_vert == segment_order__contiguous)954				dcc_control = dcc_control__256_128;955			else956				dcc_control = dcc_control__256_64;957		} else {958			if ((req128_horz_wc &&959				segment_order_horz == segment_order__non_contiguous) ||960				(req128_vert_wc &&961				segment_order_vert == segment_order__non_contiguous))962				/* access_dir not known, must use most constraining */963				dcc_control = dcc_control__256_64;964			else965				/* req128 is true for either horz and vert966				 * but segment_order is contiguous967				 */968				dcc_control = dcc_control__256_128;969		}970 971		if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&972			dcc_control != dcc_control__256_256)973			return false;974 975		switch (dcc_control) {976		case dcc_control__256_256:977			output->grph.rgb.dcc_controls.dcc_256_256 = 1;978			output->grph.rgb.dcc_controls.dcc_256_128 = 1;979			output->grph.rgb.dcc_controls.dcc_256_64 = 1;980			break;981		case dcc_control__256_128:982			output->grph.rgb.dcc_controls.dcc_256_128 = 1;983			output->grph.rgb.dcc_controls.dcc_256_64 = 1;984			break;985		case dcc_control__256_64:986			output->grph.rgb.dcc_controls.dcc_256_64 = 1;987			break;988		default:989			/* Shouldn't get here */990			ASSERT(0);991			break;992		}993	} else {994		/* For dual plane cases, need to examine both planes together */995		if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,996				input->plane0_pitch, plane0_bpe,997				&segment_order_horz, &segment_order_vert))998			return false;999 1000		if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,1001			input->plane1_pitch, plane1_bpe,1002			&p1_segment_order_horz, &p1_segment_order_vert))1003			return false;1004 1005		hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format,1006				plane0_height, plane0_width, plane0_bpe,1007				plane1_height, plane1_width, plane1_bpe,1008				&req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc);1009 1010		/* Determine Plane 0 DCC Controls */1011		if (!req128_horz_wc && !req128_vert_wc) {1012			dcc_control = dcc_control__256_256;1013		} else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {1014			if (!req128_horz_wc)1015				dcc_control = dcc_control__256_256;1016			else if (segment_order_horz == segment_order__contiguous)1017				dcc_control = dcc_control__256_128;1018			else1019				dcc_control = dcc_control__256_64;1020		} else if (input->scan == SCAN_DIRECTION_VERTICAL) {1021			if (!req128_vert_wc)1022				dcc_control = dcc_control__256_256;1023			else if (segment_order_vert == segment_order__contiguous)1024				dcc_control = dcc_control__256_128;1025			else1026				dcc_control = dcc_control__256_64;1027		} else {1028			if ((req128_horz_wc &&1029				segment_order_horz == segment_order__non_contiguous) ||1030				(req128_vert_wc &&1031				segment_order_vert == segment_order__non_contiguous))1032				/* access_dir not known, must use most constraining */1033				dcc_control = dcc_control__256_64;1034			else1035				/* req128 is true for either horz and vert1036				 * but segment_order is contiguous1037				 */1038				dcc_control = dcc_control__256_128;1039		}1040 1041		switch (dcc_control) {1042		case dcc_control__256_256:1043			output->video.luma.dcc_controls.dcc_256_256 = 1;1044			output->video.luma.dcc_controls.dcc_256_128 = 1;1045			output->video.luma.dcc_controls.dcc_256_64 = 1;1046			break;1047		case dcc_control__256_128:1048			output->video.luma.dcc_controls.dcc_256_128 = 1;1049			output->video.luma.dcc_controls.dcc_256_64 = 1;1050			break;1051		case dcc_control__256_64:1052			output->video.luma.dcc_controls.dcc_256_64 = 1;1053			break;1054		default:1055			ASSERT(0);1056			break;1057		}1058 1059		/* Determine Plane 1 DCC Controls */1060		if (!p1_req128_horz_wc && !p1_req128_vert_wc) {1061			dcc_control = dcc_control__256_256;1062		} else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {1063			if (!p1_req128_horz_wc)1064				dcc_control = dcc_control__256_256;1065			else if (p1_segment_order_horz == segment_order__contiguous)1066				dcc_control = dcc_control__256_128;1067			else1068				dcc_control = dcc_control__256_64;1069		} else if (input->scan == SCAN_DIRECTION_VERTICAL) {1070			if (!p1_req128_vert_wc)1071				dcc_control = dcc_control__256_256;1072			else if (p1_segment_order_vert == segment_order__contiguous)1073				dcc_control = dcc_control__256_128;1074			else1075				dcc_control = dcc_control__256_64;1076		} else {1077			if ((p1_req128_horz_wc &&1078				p1_segment_order_horz == segment_order__non_contiguous) ||1079				(p1_req128_vert_wc &&1080				p1_segment_order_vert == segment_order__non_contiguous))1081				/* access_dir not known, must use most constraining */1082				dcc_control = dcc_control__256_64;1083			else1084				/* req128 is true for either horz and vert1085				 * but segment_order is contiguous1086				 */1087				dcc_control = dcc_control__256_128;1088		}1089 1090		switch (dcc_control) {1091		case dcc_control__256_256:1092			output->video.chroma.dcc_controls.dcc_256_256 = 1;1093			output->video.chroma.dcc_controls.dcc_256_128 = 1;1094			output->video.chroma.dcc_controls.dcc_256_64 = 1;1095			break;1096		case dcc_control__256_128:1097			output->video.chroma.dcc_controls.dcc_256_128 = 1;1098			output->video.chroma.dcc_controls.dcc_256_64 = 1;1099			break;1100		case dcc_control__256_64:1101			output->video.chroma.dcc_controls.dcc_256_64 = 1;1102			break;1103		default:1104			ASSERT(0);1105			break;1106		}1107	}1108 1109	output->capable = true;1110	return true;1111}1112 1113static void dcn401_program_det_segments(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg)1114{1115	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);1116 1117	switch (hubp_inst) {1118	case 0:1119		REG_UPDATE(DCHUBBUB_DET0_CTRL,1120					DET0_SIZE, det_buffer_size_seg);1121		hubbub2->det0_size = det_buffer_size_seg;1122		break;1123	case 1:1124		REG_UPDATE(DCHUBBUB_DET1_CTRL,1125					DET1_SIZE, det_buffer_size_seg);1126		hubbub2->det1_size = det_buffer_size_seg;1127		break;1128	case 2:1129		REG_UPDATE(DCHUBBUB_DET2_CTRL,1130					DET2_SIZE, det_buffer_size_seg);1131		hubbub2->det2_size = det_buffer_size_seg;1132		break;1133	case 3:1134		REG_UPDATE(DCHUBBUB_DET3_CTRL,1135					DET3_SIZE, det_buffer_size_seg);1136		hubbub2->det3_size = det_buffer_size_seg;1137		break;1138	default:1139		break;1140	}1141	if (hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size1142			+ hubbub2->det3_size + hubbub2->compbuf_size_segments > hubbub2->crb_size_segs) {1143		/* This may happen during seamless transition from ODM 2:1 to ODM4:1 */1144		DC_LOG_WARNING("CRB Config Warning: DET size (%d,%d,%d,%d) + Compbuf size (%d) >  CRB segments (%d)\n",1145						hubbub2->det0_size, hubbub2->det1_size, hubbub2->det2_size, hubbub2->det3_size,1146						hubbub2->compbuf_size_segments, hubbub2->crb_size_segs);1147	}1148}1149 1150static void dcn401_program_compbuf_segments(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase)1151{1152	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);1153 1154	unsigned int cur_compbuf_size_seg = 0;1155 1156	if (safe_to_increase || compbuf_size_seg <= hubbub2->compbuf_size_segments) {1157		if (compbuf_size_seg > hubbub2->compbuf_size_segments) {1158			REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100);1159			REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100);1160			REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100);1161			REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100);1162		}1163		/* Should never be hit, if it is we have an erroneous hw config*/1164		ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size1165				+ hubbub2->det3_size + compbuf_size_seg <= hubbub2->crb_size_segs);1166		REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_seg);1167		hubbub2->compbuf_size_segments = compbuf_size_seg;1168 1169		ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &cur_compbuf_size_seg) && !cur_compbuf_size_seg);1170	}1171}1172 1173static void dcn401_wait_for_det_update(struct hubbub *hubbub, int hubp_inst)1174{1175	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);1176 1177	switch (hubp_inst) {1178	case 0:1179		REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100000); /* 1 vupdate at 10hz */1180		break;1181	case 1:1182		REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100000);1183		break;1184	case 2:1185		REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100000);1186		break;1187	case 3:1188		REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100000);1189		break;1190	default:1191		break;1192	}1193}1194 1195static const struct hubbub_funcs hubbub4_01_funcs = {1196	.update_dchub = hubbub2_update_dchub,1197	.init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx,1198	.init_vm_ctx = hubbub2_init_vm_ctx,1199	.dcc_support_swizzle_addr3 = hubbub401_dcc_support_swizzle,1200	.dcc_support_pixel_format_plane0_plane1 = hubbub401_dcc_support_pixel_format,1201	.get_dcc_compression_cap = hubbub401_get_dcc_compression_cap,1202	.wm_read_state = hubbub401_wm_read_state,1203	.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,1204	.program_watermarks = hubbub401_program_watermarks,1205	.allow_self_refresh_control = hubbub1_allow_self_refresh_control,1206	.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,1207	.verify_allow_pstate_change_high = NULL,1208	.force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,1209	.force_pstate_change_control = hubbub3_force_pstate_change_control,1210	.init_watermarks = hubbub401_init_watermarks,1211	.init_crb = dcn401_init_crb,1212	.hubbub_read_state = hubbub2_read_state,1213	.force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,1214	.set_request_limit = hubbub32_set_request_limit,1215	.program_det_segments = dcn401_program_det_segments,1216	.program_compbuf_segments = dcn401_program_compbuf_segments,1217	.wait_for_det_update = dcn401_wait_for_det_update,1218};1219 1220void hubbub401_construct(struct dcn20_hubbub *hubbub2,1221	struct dc_context *ctx,1222	const struct dcn_hubbub_registers *hubbub_regs,1223	const struct dcn_hubbub_shift *hubbub_shift,1224	const struct dcn_hubbub_mask *hubbub_mask,1225	int det_size_kb,1226	int pixel_chunk_size_kb,1227	int config_return_buffer_size_kb)1228{1229	hubbub2->base.ctx = ctx;1230	hubbub2->base.funcs = &hubbub4_01_funcs;1231	hubbub2->regs = hubbub_regs;1232	hubbub2->shifts = hubbub_shift;1233	hubbub2->masks = hubbub_mask;1234 1235	hubbub2->detile_buf_size = det_size_kb * 1024;1236	hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024;1237	hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN4_01_CRB_SEGMENT_SIZE_KB;1238}1239