brintos

brintos / linux-shallow public Read only

0
0
Text · 24.2 KiB · faae12c Raw
848 lines · c
1/*2 * Copyright 2012-15 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#include "dm_services.h"27 28#include "dce/dce_11_2_d.h"29#include "dce/dce_11_2_sh_mask.h"30#include "gmc/gmc_8_1_sh_mask.h"31#include "gmc/gmc_8_1_d.h"32 33#include "include/logger_interface.h"34 35#include "dce112_compressor.h"36#define DC_LOGGER \37		cp110->base.ctx->logger38#define DCP_REG(reg)\39	(reg + cp110->offsets.dcp_offset)40#define DMIF_REG(reg)\41	(reg + cp110->offsets.dmif_offset)42 43static const struct dce112_compressor_reg_offsets reg_offsets[] = {44{45	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),46	.dmif_offset =47		(mmDMIF_PG0_DPG_PIPE_DPM_CONTROL48			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),49},50{51	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),52	.dmif_offset =53		(mmDMIF_PG1_DPG_PIPE_DPM_CONTROL54			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),55},56{57	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),58	.dmif_offset =59		(mmDMIF_PG2_DPG_PIPE_DPM_CONTROL60			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),61}62};63 64static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600;65 66enum fbc_idle_force {67	/* Bit 0 - Display registers updated */68	FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001,69 70	/* Bit 2 - FBC_GRPH_COMP_EN register updated */71	FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002,72	/* Bit 3 - FBC_SRC_SEL register updated */73	FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004,74	/* Bit 4 - FBC_MIN_COMPRESSION register updated */75	FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008,76	/* Bit 5 - FBC_ALPHA_COMP_EN register updated */77	FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010,78	/* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */79	FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020,80	/* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */81	FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040,82 83	/* Bit 24 - Memory write to region 0 defined by MC registers. */84	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000,85	/* Bit 25 - Memory write to region 1 defined by MC registers */86	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000,87	/* Bit 26 - Memory write to region 2 defined by MC registers */88	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000,89	/* Bit 27 - Memory write to region 3 defined by MC registers. */90	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000,91 92	/* Bit 28 - Memory write from any client other than MCIF */93	FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000,94	/* Bit 29 - CG statics screen signal is inactive */95	FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000,96};97 98static uint32_t lpt_size_alignment(struct dce112_compressor *cp110)99{100	/*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */101	return cp110->base.raw_size * cp110->base.banks_num *102		cp110->base.dram_channels_num;103}104 105static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110,106	uint32_t lpt_control)107{108	/*LPT MC Config */109	if (cp110->base.options.bits.LPT_MC_CONFIG == 1) {110		/* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS):111		 * 00 - 1 CHANNEL112		 * 01 - 2 CHANNELS113		 * 02 - 4 OR 6 CHANNELS114		 * (Only for discrete GPU, N/A for CZ)115		 * 03 - 8 OR 12 CHANNELS116		 * (Only for discrete GPU, N/A for CZ) */117		switch (cp110->base.dram_channels_num) {118		case 2:119			set_reg_field_value(120				lpt_control,121				1,122				LOW_POWER_TILING_CONTROL,123				LOW_POWER_TILING_NUM_PIPES);124			break;125		case 1:126			set_reg_field_value(127				lpt_control,128				0,129				LOW_POWER_TILING_CONTROL,130				LOW_POWER_TILING_NUM_PIPES);131			break;132		default:133			DC_LOG_WARNING(134				"%s: Invalid LPT NUM_PIPES!!!",135				__func__);136			break;137		}138 139		/* The mapping for LPT NUM_BANKS is in140		 * GRPH_CONTROL.GRPH_NUM_BANKS register field141		 * Specifies the number of memory banks for tiling142		 * purposes. Only applies to 2D and 3D tiling modes.143		 * POSSIBLE VALUES:144		 * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK145		 * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK146		 * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK147		 * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */148		switch (cp110->base.banks_num) {149		case 16:150			set_reg_field_value(151				lpt_control,152				3,153				LOW_POWER_TILING_CONTROL,154				LOW_POWER_TILING_NUM_BANKS);155			break;156		case 8:157			set_reg_field_value(158				lpt_control,159				2,160				LOW_POWER_TILING_CONTROL,161				LOW_POWER_TILING_NUM_BANKS);162			break;163		case 4:164			set_reg_field_value(165				lpt_control,166				1,167				LOW_POWER_TILING_CONTROL,168				LOW_POWER_TILING_NUM_BANKS);169			break;170		case 2:171			set_reg_field_value(172				lpt_control,173				0,174				LOW_POWER_TILING_CONTROL,175				LOW_POWER_TILING_NUM_BANKS);176			break;177		default:178			DC_LOG_WARNING(179				"%s: Invalid LPT NUM_BANKS!!!",180				__func__);181			break;182		}183 184		/* The mapping is in DMIF_ADDR_CALC.185		 * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for186		 * Carrizo specifies the memory interleave per pipe.187		 * It effectively specifies the location of pipe bits in188		 * the memory address.189		 * POSSIBLE VALUES:190		 * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte191		 * interleave192		 * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte193		 * interleave194		 */195		switch (cp110->base.channel_interleave_size) {196		case 256: /*256B */197			set_reg_field_value(198				lpt_control,199				0,200				LOW_POWER_TILING_CONTROL,201				LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);202			break;203		case 512: /*512B */204			set_reg_field_value(205				lpt_control,206				1,207				LOW_POWER_TILING_CONTROL,208				LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);209			break;210		default:211			DC_LOG_WARNING(212				"%s: Invalid LPT INTERLEAVE_SIZE!!!",213				__func__);214			break;215		}216 217		/* The mapping for LOW_POWER_TILING_ROW_SIZE is in218		 * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field219		 * for Carrizo. Specifies the size of dram row in bytes.220		 * This should match up with NOOFCOLS field in221		 * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns).222		 * This register DMIF_ADDR_CALC is not used by the223		 * hardware as it is only used for addrlib assertions.224		 * POSSIBLE VALUES:225		 * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row226		 * boundary227		 * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row228		 * boundary229		 * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row230		 * boundary */231		switch (cp110->base.raw_size) {232		case 4096: /*4 KB */233			set_reg_field_value(234				lpt_control,235				2,236				LOW_POWER_TILING_CONTROL,237				LOW_POWER_TILING_ROW_SIZE);238			break;239		case 2048:240			set_reg_field_value(241				lpt_control,242				1,243				LOW_POWER_TILING_CONTROL,244				LOW_POWER_TILING_ROW_SIZE);245			break;246		case 1024:247			set_reg_field_value(248				lpt_control,249				0,250				LOW_POWER_TILING_CONTROL,251				LOW_POWER_TILING_ROW_SIZE);252			break;253		default:254			DC_LOG_WARNING(255				"%s: Invalid LPT ROW_SIZE!!!",256				__func__);257			break;258		}259	} else {260		DC_LOG_WARNING(261			"%s: LPT MC Configuration is not provided",262			__func__);263	}264 265	return lpt_control;266}267 268static bool is_source_bigger_than_epanel_size(269	struct dce112_compressor *cp110,270	uint32_t source_view_width,271	uint32_t source_view_height)272{273	if (cp110->base.embedded_panel_h_size != 0 &&274		cp110->base.embedded_panel_v_size != 0 &&275		((source_view_width * source_view_height) >276		(cp110->base.embedded_panel_h_size *277			cp110->base.embedded_panel_v_size)))278		return true;279 280	return false;281}282 283static uint32_t align_to_chunks_number_per_line(284	struct dce112_compressor *cp110,285	uint32_t pixels)286{287	return 256 * ((pixels + 255) / 256);288}289 290static void wait_for_fbc_state_changed(291	struct dce112_compressor *cp110,292	bool enabled)293{294	uint8_t counter = 0;295	uint32_t addr = mmFBC_STATUS;296	uint32_t value;297 298	while (counter < 10) {299		value = dm_read_reg(cp110->base.ctx, addr);300		if (get_reg_field_value(301			value,302			FBC_STATUS,303			FBC_ENABLE_STATUS) == enabled)304			break;305		udelay(10);306		counter++;307	}308 309	if (counter == 10) {310		DC_LOG_WARNING(311			"%s: wait counter exceeded, changes to HW not applied",312			__func__);313	}314}315 316void dce112_compressor_power_up_fbc(struct compressor *compressor)317{318	uint32_t value;319	uint32_t addr;320 321	addr = mmFBC_CNTL;322	value = dm_read_reg(compressor->ctx, addr);323	set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);324	set_reg_field_value(value, 1, FBC_CNTL, FBC_EN);325	set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE);326	if (compressor->options.bits.CLK_GATING_DISABLED == 1) {327		/* HW needs to do power measurement comparison. */328		set_reg_field_value(329			value,330			0,331			FBC_CNTL,332			FBC_COMP_CLK_GATE_EN);333	}334	dm_write_reg(compressor->ctx, addr, value);335 336	addr = mmFBC_COMP_MODE;337	value = dm_read_reg(compressor->ctx, addr);338	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN);339	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN);340	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN);341	dm_write_reg(compressor->ctx, addr, value);342 343	addr = mmFBC_COMP_CNTL;344	value = dm_read_reg(compressor->ctx, addr);345	set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN);346	dm_write_reg(compressor->ctx, addr, value);347	/*FBC_MIN_COMPRESSION 0 ==> 2:1 */348	/*                    1 ==> 4:1 */349	/*                    2 ==> 8:1 */350	/*                  0xF ==> 1:1 */351	set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION);352	dm_write_reg(compressor->ctx, addr, value);353	compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1;354 355	value = 0;356	dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value);357 358	value = 0xFFFFFF;359	dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value);360}361 362void dce112_compressor_enable_fbc(363	struct compressor *compressor,364	uint32_t paths_num,365	struct compr_addr_and_pitch_params *params)366{367	struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);368 369	if (compressor->options.bits.FBC_SUPPORT &&370		(compressor->options.bits.DUMMY_BACKEND == 0) &&371		(!dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) &&372		(!is_source_bigger_than_epanel_size(373			cp110,374			params->source_view_width,375			params->source_view_height))) {376 377		uint32_t addr;378		uint32_t value;379 380		/* Before enabling FBC first need to enable LPT if applicable381		 * LPT state should always be changed (enable/disable) while FBC382		 * is disabled */383		if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) &&384			(params->source_view_width *385				params->source_view_height <=386				dce11_one_lpt_channel_max_resolution)) {387			dce112_compressor_enable_lpt(compressor);388		}389 390		addr = mmFBC_CNTL;391		value = dm_read_reg(compressor->ctx, addr);392		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);393		set_reg_field_value(394			value,395			params->inst,396			FBC_CNTL, FBC_SRC_SEL);397		dm_write_reg(compressor->ctx, addr, value);398 399		/* Keep track of enum controller_id FBC is attached to */400		compressor->is_enabled = true;401		compressor->attached_inst = params->inst;402		cp110->offsets = reg_offsets[params->inst];403 404		/*Toggle it as there is bug in HW */405		set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);406		dm_write_reg(compressor->ctx, addr, value);407		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);408		dm_write_reg(compressor->ctx, addr, value);409 410		wait_for_fbc_state_changed(cp110, true);411	}412}413 414void dce112_compressor_disable_fbc(struct compressor *compressor)415{416	struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);417 418	if (compressor->options.bits.FBC_SUPPORT &&419		dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {420		uint32_t reg_data;421		/* Turn off compression */422		reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);423		set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);424		dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);425 426		/* Reset enum controller_id to undefined */427		compressor->attached_inst = 0;428		compressor->is_enabled = false;429 430		/* Whenever disabling FBC make sure LPT is disabled if LPT431		 * supported */432		if (compressor->options.bits.LPT_SUPPORT)433			dce112_compressor_disable_lpt(compressor);434 435		wait_for_fbc_state_changed(cp110, false);436	}437}438 439bool dce112_compressor_is_fbc_enabled_in_hw(440	struct compressor *compressor,441	uint32_t *inst)442{443	/* Check the hardware register */444	uint32_t value;445 446	value = dm_read_reg(compressor->ctx, mmFBC_STATUS);447	if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) {448		if (inst != NULL)449			*inst = compressor->attached_inst;450		return true;451	}452 453	value = dm_read_reg(compressor->ctx, mmFBC_MISC);454	if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) {455		value = dm_read_reg(compressor->ctx, mmFBC_CNTL);456 457		if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) {458			if (inst != NULL)459				*inst =460					compressor->attached_inst;461			return true;462		}463	}464	return false;465}466 467bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *compressor)468{469	/* Check the hardware register */470	uint32_t value = dm_read_reg(compressor->ctx,471		mmLOW_POWER_TILING_CONTROL);472 473	return get_reg_field_value(474		value,475		LOW_POWER_TILING_CONTROL,476		LOW_POWER_TILING_ENABLE);477}478 479void dce112_compressor_program_compressed_surface_address_and_pitch(480	struct compressor *compressor,481	struct compr_addr_and_pitch_params *params)482{483	struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);484	uint32_t value = 0;485	uint32_t fbc_pitch = 0;486	uint32_t compressed_surf_address_low_part =487		compressor->compr_surface_address.addr.low_part;488 489	/* Clear content first. */490	dm_write_reg(491		compressor->ctx,492		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),493		0);494	dm_write_reg(compressor->ctx,495		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);496 497	if (compressor->options.bits.LPT_SUPPORT) {498		uint32_t lpt_alignment = lpt_size_alignment(cp110);499 500		if (lpt_alignment != 0) {501			compressed_surf_address_low_part =502				((compressed_surf_address_low_part503					+ (lpt_alignment - 1)) / lpt_alignment)504					* lpt_alignment;505		}506	}507 508	/* Write address, HIGH has to be first. */509	dm_write_reg(compressor->ctx,510		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),511		compressor->compr_surface_address.addr.high_part);512	dm_write_reg(compressor->ctx,513		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),514		compressed_surf_address_low_part);515 516	fbc_pitch = align_to_chunks_number_per_line(517		cp110,518		params->source_view_width);519 520	if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)521		fbc_pitch = fbc_pitch / 8;522	else523		DC_LOG_WARNING(524			"%s: Unexpected DCE11 compression ratio",525			__func__);526 527	/* Clear content first. */528	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);529 530	/* Write FBC Pitch. */531	set_reg_field_value(532		value,533		fbc_pitch,534		GRPH_COMPRESS_PITCH,535		GRPH_COMPRESS_PITCH);536	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);537 538}539 540void dce112_compressor_disable_lpt(struct compressor *compressor)541{542	struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);543	uint32_t value;544	uint32_t addr;545	uint32_t inx;546 547	/* Disable all pipes LPT Stutter */548	for (inx = 0; inx < 3; inx++) {549		value =550			dm_read_reg(551				compressor->ctx,552				DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));553		set_reg_field_value(554			value,555			0,556			DPG_PIPE_STUTTER_CONTROL_NONLPTCH,557			STUTTER_ENABLE_NONLPTCH);558		dm_write_reg(559			compressor->ctx,560			DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH),561			value);562	}563	/* Disable Underlay pipe LPT Stutter */564	addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;565	value = dm_read_reg(compressor->ctx, addr);566	set_reg_field_value(567		value,568		0,569		DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,570		STUTTER_ENABLE_NONLPTCH);571	dm_write_reg(compressor->ctx, addr, value);572 573	/* Disable LPT */574	addr = mmLOW_POWER_TILING_CONTROL;575	value = dm_read_reg(compressor->ctx, addr);576	set_reg_field_value(577		value,578		0,579		LOW_POWER_TILING_CONTROL,580		LOW_POWER_TILING_ENABLE);581	dm_write_reg(compressor->ctx, addr, value);582 583	/* Clear selection of Channel(s) containing Compressed Surface */584	addr = mmGMCON_LPT_TARGET;585	value = dm_read_reg(compressor->ctx, addr);586	set_reg_field_value(587		value,588		0xFFFFFFFF,589		GMCON_LPT_TARGET,590		STCTRL_LPT_TARGET);591	dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value);592}593 594void dce112_compressor_enable_lpt(struct compressor *compressor)595{596	struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);597	uint32_t value;598	uint32_t addr;599	uint32_t value_control;600	uint32_t channels;601 602	/* Enable LPT Stutter from Display pipe */603	value = dm_read_reg(compressor->ctx,604		DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));605	set_reg_field_value(606		value,607		1,608		DPG_PIPE_STUTTER_CONTROL_NONLPTCH,609		STUTTER_ENABLE_NONLPTCH);610	dm_write_reg(compressor->ctx,611		DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value);612 613	/* Enable Underlay pipe LPT Stutter */614	addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;615	value = dm_read_reg(compressor->ctx, addr);616	set_reg_field_value(617		value,618		1,619		DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,620		STUTTER_ENABLE_NONLPTCH);621	dm_write_reg(compressor->ctx, addr, value);622 623	/* Selection of Channel(s) containing Compressed Surface: 0xfffffff624	 * will disable LPT.625	 * STCTRL_LPT_TARGETn corresponds to channel n. */626	addr = mmLOW_POWER_TILING_CONTROL;627	value_control = dm_read_reg(compressor->ctx, addr);628	channels = get_reg_field_value(value_control,629			LOW_POWER_TILING_CONTROL,630			LOW_POWER_TILING_MODE);631 632	addr = mmGMCON_LPT_TARGET;633	value = dm_read_reg(compressor->ctx, addr);634	set_reg_field_value(635		value,636		channels + 1, /* not mentioned in programming guide,637				but follow DCE8.1 */638		GMCON_LPT_TARGET,639		STCTRL_LPT_TARGET);640	dm_write_reg(compressor->ctx, addr, value);641 642	/* Enable LPT */643	addr = mmLOW_POWER_TILING_CONTROL;644	value = dm_read_reg(compressor->ctx, addr);645	set_reg_field_value(646		value,647		1,648		LOW_POWER_TILING_CONTROL,649		LOW_POWER_TILING_ENABLE);650	dm_write_reg(compressor->ctx, addr, value);651}652 653void dce112_compressor_program_lpt_control(654	struct compressor *compressor,655	struct compr_addr_and_pitch_params *params)656{657	struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor);658	uint32_t rows_per_channel;659	uint32_t lpt_alignment;660	uint32_t source_view_width;661	uint32_t source_view_height;662	uint32_t lpt_control = 0;663 664	if (!compressor->options.bits.LPT_SUPPORT)665		return;666 667	lpt_control = dm_read_reg(compressor->ctx,668		mmLOW_POWER_TILING_CONTROL);669 670	/* POSSIBLE VALUES for Low Power Tiling Mode:671	 * 00 - Use channel 0672	 * 01 - Use Channel 0 and 1673	 * 02 - Use Channel 0,1,2,3674	 * 03 - reserved */675	switch (compressor->lpt_channels_num) {676	/* case 2:677	 * Use Channel 0 & 1 / Not used for DCE 11 */678	case 1:679		/*Use Channel 0 for LPT for DCE 11 */680		set_reg_field_value(681			lpt_control,682			0,683			LOW_POWER_TILING_CONTROL,684			LOW_POWER_TILING_MODE);685		break;686	default:687		DC_LOG_WARNING(688			"%s: Invalid selected DRAM channels for LPT!!!",689			__func__);690		break;691	}692 693	lpt_control = lpt_memory_control_config(cp110, lpt_control);694 695	/* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on696	 * FBC compressed surface pitch.697	 * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height *698	 * Surface Pitch) / (Row Size * Number of Channels *699	 * Number of Banks)). */700	rows_per_channel = 0;701	lpt_alignment = lpt_size_alignment(cp110);702	source_view_width =703		align_to_chunks_number_per_line(704			cp110,705			params->source_view_width);706	source_view_height = (params->source_view_height + 1) & (~0x1);707 708	if (lpt_alignment != 0) {709		rows_per_channel = source_view_width * source_view_height * 4;710		rows_per_channel =711			(rows_per_channel % lpt_alignment) ?712				(rows_per_channel / lpt_alignment + 1) :713				rows_per_channel / lpt_alignment;714	}715 716	set_reg_field_value(717		lpt_control,718		rows_per_channel,719		LOW_POWER_TILING_CONTROL,720		LOW_POWER_TILING_ROWS_PER_CHAN);721 722	dm_write_reg(compressor->ctx,723		mmLOW_POWER_TILING_CONTROL, lpt_control);724}725 726/*727 * DCE 11 Frame Buffer Compression Implementation728 */729 730void dce112_compressor_set_fbc_invalidation_triggers(731	struct compressor *compressor,732	uint32_t fbc_trigger)733{734	/* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)735	 * for DCE 11 regions cannot be used - does not work with S/G736	 */737	uint32_t addr = mmFBC_CLIENT_REGION_MASK;738	uint32_t value = dm_read_reg(compressor->ctx, addr);739 740	set_reg_field_value(741		value,742		0,743		FBC_CLIENT_REGION_MASK,744		FBC_MEMORY_REGION_MASK);745	dm_write_reg(compressor->ctx, addr, value);746 747	/* Setup events when to clear all CSM entries (effectively marking748	 * current compressed data invalid)749	 * For DCE 11 CSM metadata 11111 means - "Not Compressed"750	 * Used as the initial value of the metadata sent to the compressor751	 * after invalidation, to indicate that the compressor should attempt752	 * to compress all chunks on the current pass.  Also used when the chunk753	 * is not successfully written to memory.754	 * When this CSM value is detected, FBC reads from the uncompressed755	 * buffer. Set events according to passed in value, these events are756	 * valid for DCE11:757	 *     - bit  0 - display register updated758	 *     - bit 28 - memory write from any client except from MCIF759	 *     - bit 29 - CG static screen signal is inactive760	 * In addition, DCE11.1 also needs to set new DCE11.1 specific events761	 * that are used to trigger invalidation on certain register changes,762	 * for example enabling of Alpha Compression may trigger invalidation of763	 * FBC once bit is set. These events are as follows:764	 *      - Bit 2 - FBC_GRPH_COMP_EN register updated765	 *      - Bit 3 - FBC_SRC_SEL register updated766	 *      - Bit 4 - FBC_MIN_COMPRESSION register updated767	 *      - Bit 5 - FBC_ALPHA_COMP_EN register updated768	 *      - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated769	 *      - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated770	 */771	addr = mmFBC_IDLE_FORCE_CLEAR_MASK;772	value = dm_read_reg(compressor->ctx, addr);773	set_reg_field_value(774		value,775		fbc_trigger |776		FBC_IDLE_FORCE_GRPH_COMP_EN |777		FBC_IDLE_FORCE_SRC_SEL_CHANGE |778		FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE |779		FBC_IDLE_FORCE_ALPHA_COMP_EN |780		FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN |781		FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF,782		FBC_IDLE_FORCE_CLEAR_MASK,783		FBC_IDLE_FORCE_CLEAR_MASK);784	dm_write_reg(compressor->ctx, addr, value);785}786 787void dce112_compressor_construct(struct dce112_compressor *compressor,788	struct dc_context *ctx)789{790	struct dc_bios *bp = ctx->dc_bios;791	struct embedded_panel_info panel_info;792 793	compressor->base.options.raw = 0;794	compressor->base.options.bits.FBC_SUPPORT = true;795	compressor->base.options.bits.LPT_SUPPORT = true;796	 /* For DCE 11 always use one DRAM channel for LPT */797	compressor->base.lpt_channels_num = 1;798	compressor->base.options.bits.DUMMY_BACKEND = false;799 800	/* Check if this system has more than 1 DRAM channel; if only 1 then LPT801	 * should not be supported */802	if (compressor->base.memory_bus_width == 64)803		compressor->base.options.bits.LPT_SUPPORT = false;804 805	compressor->base.options.bits.CLK_GATING_DISABLED = false;806 807	compressor->base.ctx = ctx;808	compressor->base.embedded_panel_h_size = 0;809	compressor->base.embedded_panel_v_size = 0;810	compressor->base.memory_bus_width = ctx->asic_id.vram_width;811	compressor->base.allocated_size = 0;812	compressor->base.preferred_requested_size = 0;813	compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID;814	compressor->base.banks_num = 0;815	compressor->base.raw_size = 0;816	compressor->base.channel_interleave_size = 0;817	compressor->base.dram_channels_num = 0;818	compressor->base.lpt_channels_num = 0;819	compressor->base.attached_inst = 0;820	compressor->base.is_enabled = false;821 822	if (BP_RESULT_OK ==823			bp->funcs->get_embedded_panel_info(bp, &panel_info)) {824		compressor->base.embedded_panel_h_size =825			panel_info.lcd_timing.horizontal_addressable;826		compressor->base.embedded_panel_v_size =827			panel_info.lcd_timing.vertical_addressable;828	}829}830 831struct compressor *dce112_compressor_create(struct dc_context *ctx)832{833	struct dce112_compressor *cp110 =834		kzalloc(sizeof(struct dce112_compressor), GFP_KERNEL);835 836	if (!cp110)837		return NULL;838 839	dce112_compressor_construct(cp110, ctx);840	return &cp110->base;841}842 843void dce112_compressor_destroy(struct compressor **compressor)844{845	kfree(TO_DCE112_COMPRESSOR(*compressor));846	*compressor = NULL;847}848