brintos

brintos / linux-shallow public Read only

0
0
Text · 14.4 KiB · d241ee1 Raw
472 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_0_d.h"29#include "dce/dce_11_0_sh_mask.h"30#include "gmc/gmc_8_2_sh_mask.h"31#include "gmc/gmc_8_2_d.h"32 33#include "include/logger_interface.h"34 35#include "dce110_compressor.h"36 37#define DC_LOGGER \38		cp110->base.ctx->logger39#define DCP_REG(reg)\40	(reg + cp110->offsets.dcp_offset)41#define DMIF_REG(reg)\42	(reg + cp110->offsets.dmif_offset)43 44static const struct dce110_compressor_reg_offsets reg_offsets[] = {45{46	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),47	.dmif_offset =48		(mmDMIF_PG0_DPG_PIPE_DPM_CONTROL49			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),50},51{52	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),53	.dmif_offset =54		(mmDMIF_PG1_DPG_PIPE_DPM_CONTROL55			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),56},57{58	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),59	.dmif_offset =60		(mmDMIF_PG2_DPG_PIPE_DPM_CONTROL61			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),62}63};64 65static uint32_t align_to_chunks_number_per_line(uint32_t pixels)66{67	return 256 * ((pixels + 255) / 256);68}69 70static void reset_lb_on_vblank(struct compressor *compressor, uint32_t crtc_inst)71{72	uint32_t value;73	uint32_t frame_count;74	uint32_t status_pos;75	uint32_t retry = 0;76	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);77 78	cp110->offsets = reg_offsets[crtc_inst];79 80	status_pos = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION));81 82 83	/* Only if CRTC is enabled and counter is moving we wait for one frame. */84	if (status_pos != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_POSITION))) {85		/* Resetting LB on VBlank */86		value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL));87		set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL);88		set_reg_field_value(value, 1, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2);89		dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value);90 91		frame_count = dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT));92 93 94		for (retry = 10000; retry > 0; retry--) {95			if (frame_count != dm_read_reg(compressor->ctx, DCP_REG(mmCRTC_STATUS_FRAME_COUNT)))96				break;97			udelay(10);98		}99		if (!retry)100			dm_error("Frame count did not increase for 100ms.\n");101 102		/* Resetting LB on VBlank */103		value = dm_read_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL));104		set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL);105		set_reg_field_value(value, 0, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2);106		dm_write_reg(compressor->ctx, DCP_REG(mmLB_SYNC_RESET_SEL), value);107	}108}109 110static void wait_for_fbc_state_changed(111	struct dce110_compressor *cp110,112	bool enabled)113{114	uint32_t counter = 0;115	uint32_t addr = mmFBC_STATUS;116	uint32_t value;117 118	while (counter < 1000) {119		value = dm_read_reg(cp110->base.ctx, addr);120		if (get_reg_field_value(121			value,122			FBC_STATUS,123			FBC_ENABLE_STATUS) == enabled)124			break;125		udelay(100);126		counter++;127	}128 129	if (counter == 1000) {130		DC_LOG_WARNING("%s: wait counter exceeded, changes to HW not applied",131			__func__);132	} else {133		DC_LOG_SYNC("FBC status changed to %d", enabled);134	}135 136 137}138 139void dce110_compressor_power_up_fbc(struct compressor *compressor)140{141	uint32_t value;142	uint32_t addr;143 144	addr = mmFBC_CNTL;145	value = dm_read_reg(compressor->ctx, addr);146	set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);147	set_reg_field_value(value, 1, FBC_CNTL, FBC_EN);148	set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE);149	if (compressor->options.bits.CLK_GATING_DISABLED == 1) {150		/* HW needs to do power measurement comparison. */151		set_reg_field_value(152			value,153			0,154			FBC_CNTL,155			FBC_COMP_CLK_GATE_EN);156	}157	dm_write_reg(compressor->ctx, addr, value);158 159	addr = mmFBC_COMP_MODE;160	value = dm_read_reg(compressor->ctx, addr);161	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN);162	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN);163	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN);164	dm_write_reg(compressor->ctx, addr, value);165 166	addr = mmFBC_COMP_CNTL;167	value = dm_read_reg(compressor->ctx, addr);168	set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN);169	dm_write_reg(compressor->ctx, addr, value);170	/*FBC_MIN_COMPRESSION 0 ==> 2:1 */171	/*                    1 ==> 4:1 */172	/*                    2 ==> 8:1 */173	/*                  0xF ==> 1:1 */174	set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION);175	dm_write_reg(compressor->ctx, addr, value);176	compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1;177 178	value = 0;179	dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value);180 181	value = 0xFFFFFF;182	dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value);183}184 185void dce110_compressor_enable_fbc(186	struct compressor *compressor,187	struct compr_addr_and_pitch_params *params)188{189	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);190 191	if (compressor->options.bits.FBC_SUPPORT &&192		(!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL))) {193 194		uint32_t addr;195		uint32_t value, misc_value;196 197		addr = mmFBC_CNTL;198		value = dm_read_reg(compressor->ctx, addr);199		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);200		/* params->inst is valid HW CRTC instance start from 0 */201		set_reg_field_value(202			value,203			params->inst,204			FBC_CNTL, FBC_SRC_SEL);205		dm_write_reg(compressor->ctx, addr, value);206 207		/* Keep track of enum controller_id FBC is attached to */208		compressor->is_enabled = true;209		/* attached_inst is SW CRTC instance start from 1210		 * 0 = CONTROLLER_ID_UNDEFINED means not attached crtc211		 */212		compressor->attached_inst = params->inst + CONTROLLER_ID_D0;213 214		/* Toggle it as there is bug in HW */215		set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);216		dm_write_reg(compressor->ctx, addr, value);217 218		/* FBC usage with scatter & gather for dce110 */219		misc_value = dm_read_reg(compressor->ctx, mmFBC_MISC);220 221		set_reg_field_value(misc_value, 1,222				FBC_MISC, FBC_INVALIDATE_ON_ERROR);223		set_reg_field_value(misc_value, 1,224				FBC_MISC, FBC_DECOMPRESS_ERROR_CLEAR);225		set_reg_field_value(misc_value, 0x14,226				FBC_MISC, FBC_SLOW_REQ_INTERVAL);227 228		dm_write_reg(compressor->ctx, mmFBC_MISC, misc_value);229 230		/* Enable FBC */231		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);232		dm_write_reg(compressor->ctx, addr, value);233 234		wait_for_fbc_state_changed(cp110, true);235	}236}237 238void dce110_compressor_disable_fbc(struct compressor *compressor)239{240	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);241	uint32_t crtc_inst = 0;242 243	if (compressor->options.bits.FBC_SUPPORT) {244		if (dce110_compressor_is_fbc_enabled_in_hw(compressor, &crtc_inst)) {245			uint32_t reg_data;246			/* Turn off compression */247			reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);248			set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);249			dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);250 251			/* Reset enum controller_id to undefined */252			compressor->attached_inst = 0;253			compressor->is_enabled = false;254 255			wait_for_fbc_state_changed(cp110, false);256		}257 258		/* Sync line buffer which fbc was attached to dce100/110 only */259		if (crtc_inst > CONTROLLER_ID_UNDEFINED && crtc_inst < CONTROLLER_ID_D3)260			reset_lb_on_vblank(compressor,261					crtc_inst - CONTROLLER_ID_D0);262	}263}264 265bool dce110_compressor_is_fbc_enabled_in_hw(266	struct compressor *compressor,267	uint32_t *inst)268{269	/* Check the hardware register */270	uint32_t value;271 272	value = dm_read_reg(compressor->ctx, mmFBC_STATUS);273	if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) {274		if (inst != NULL)275			*inst = compressor->attached_inst;276		return true;277	}278 279	value = dm_read_reg(compressor->ctx, mmFBC_MISC);280	if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) {281		value = dm_read_reg(compressor->ctx, mmFBC_CNTL);282 283		if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) {284			if (inst != NULL)285				*inst =286					compressor->attached_inst;287			return true;288		}289	}290	return false;291}292 293 294void dce110_compressor_program_compressed_surface_address_and_pitch(295	struct compressor *compressor,296	struct compr_addr_and_pitch_params *params)297{298	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);299	uint32_t value = 0;300	uint32_t fbc_pitch = 0;301	uint32_t compressed_surf_address_low_part =302		compressor->compr_surface_address.addr.low_part;303 304	cp110->offsets = reg_offsets[params->inst];305 306	/* Clear content first. */307	dm_write_reg(308		compressor->ctx,309		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),310		0);311	dm_write_reg(compressor->ctx,312		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);313 314	/* Write address, HIGH has to be first. */315	dm_write_reg(compressor->ctx,316		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),317		compressor->compr_surface_address.addr.high_part);318	dm_write_reg(compressor->ctx,319		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),320		compressed_surf_address_low_part);321 322	fbc_pitch = align_to_chunks_number_per_line(params->source_view_width);323 324	if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)325		fbc_pitch = fbc_pitch / 8;326	else327		DC_LOG_WARNING("%s: Unexpected DCE11 compression ratio",328			__func__);329 330	/* Clear content first. */331	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);332 333	/* Write FBC Pitch. */334	set_reg_field_value(335		value,336		fbc_pitch,337		GRPH_COMPRESS_PITCH,338		GRPH_COMPRESS_PITCH);339	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);340 341}342 343void dce110_compressor_set_fbc_invalidation_triggers(344	struct compressor *compressor,345	uint32_t fbc_trigger)346{347	/* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)348	 * for DCE 11 regions cannot be used - does not work with S/G349	 */350	uint32_t addr = mmFBC_CLIENT_REGION_MASK;351	uint32_t value = dm_read_reg(compressor->ctx, addr);352 353	set_reg_field_value(354		value,355		0,356		FBC_CLIENT_REGION_MASK,357		FBC_MEMORY_REGION_MASK);358	dm_write_reg(compressor->ctx, addr, value);359 360	/* Setup events when to clear all CSM entries (effectively marking361	 * current compressed data invalid)362	 * For DCE 11 CSM metadata 11111 means - "Not Compressed"363	 * Used as the initial value of the metadata sent to the compressor364	 * after invalidation, to indicate that the compressor should attempt365	 * to compress all chunks on the current pass.  Also used when the chunk366	 * is not successfully written to memory.367	 * When this CSM value is detected, FBC reads from the uncompressed368	 * buffer. Set events according to passed in value, these events are369	 * valid for DCE11:370	 *     - bit  0 - display register updated371	 *     - bit 28 - memory write from any client except from MCIF372	 *     - bit 29 - CG static screen signal is inactive373	 * In addition, DCE11.1 also needs to set new DCE11.1 specific events374	 * that are used to trigger invalidation on certain register changes,375	 * for example enabling of Alpha Compression may trigger invalidation of376	 * FBC once bit is set. These events are as follows:377	 *      - Bit 2 - FBC_GRPH_COMP_EN register updated378	 *      - Bit 3 - FBC_SRC_SEL register updated379	 *      - Bit 4 - FBC_MIN_COMPRESSION register updated380	 *      - Bit 5 - FBC_ALPHA_COMP_EN register updated381	 *      - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated382	 *      - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated383	 */384	addr = mmFBC_IDLE_FORCE_CLEAR_MASK;385	value = dm_read_reg(compressor->ctx, addr);386	set_reg_field_value(387		value,388		fbc_trigger,389		FBC_IDLE_FORCE_CLEAR_MASK,390		FBC_IDLE_FORCE_CLEAR_MASK);391	dm_write_reg(compressor->ctx, addr, value);392}393 394struct compressor *dce110_compressor_create(struct dc_context *ctx)395{396	struct dce110_compressor *cp110 =397		kzalloc(sizeof(struct dce110_compressor), GFP_KERNEL);398 399	if (!cp110)400		return NULL;401 402	dce110_compressor_construct(cp110, ctx);403	return &cp110->base;404}405 406void dce110_compressor_destroy(struct compressor **compressor)407{408	kfree(TO_DCE110_COMPRESSOR(*compressor));409	*compressor = NULL;410}411 412void get_max_support_fbc_buffersize(unsigned int *max_x, unsigned int *max_y)413{414	*max_x = FBC_MAX_X;415	*max_y = FBC_MAX_Y;416 417	/* if (m_smallLocalFrameBufferMemory == 1)418	 * {419	 *	*max_x = FBC_MAX_X_SG;420	 *	*max_y = FBC_MAX_Y_SG;421	 * }422	 */423}424 425static const struct compressor_funcs dce110_compressor_funcs = {426	.power_up_fbc = dce110_compressor_power_up_fbc,427	.enable_fbc = dce110_compressor_enable_fbc,428	.disable_fbc = dce110_compressor_disable_fbc,429	.set_fbc_invalidation_triggers = dce110_compressor_set_fbc_invalidation_triggers,430	.surface_address_and_pitch = dce110_compressor_program_compressed_surface_address_and_pitch,431	.is_fbc_enabled_in_hw = dce110_compressor_is_fbc_enabled_in_hw432};433 434 435void dce110_compressor_construct(struct dce110_compressor *compressor,436	struct dc_context *ctx)437{438 439	compressor->base.options.raw = 0;440	compressor->base.options.bits.FBC_SUPPORT = true;441 442	/* for dce 11 always use one dram channel for lpt */443	compressor->base.lpt_channels_num = 1;444	compressor->base.options.bits.DUMMY_BACKEND = false;445 446	/*447	 * check if this system has more than 1 dram channel; if only 1 then lpt448	 * should not be supported449	 */450 451 452	compressor->base.options.bits.CLK_GATING_DISABLED = false;453 454	compressor->base.ctx = ctx;455	compressor->base.embedded_panel_h_size = 0;456	compressor->base.embedded_panel_v_size = 0;457	compressor->base.memory_bus_width = ctx->asic_id.vram_width;458	compressor->base.allocated_size = 0;459	compressor->base.preferred_requested_size = 0;460	compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID;461	compressor->base.banks_num = 0;462	compressor->base.raw_size = 0;463	compressor->base.channel_interleave_size = 0;464	compressor->base.dram_channels_num = 0;465	compressor->base.lpt_channels_num = 0;466	compressor->base.attached_inst = CONTROLLER_ID_UNDEFINED;467	compressor->base.is_enabled = false;468	compressor->base.funcs = &dce110_compressor_funcs;469 470}471 472