/**
* Function:
* void program_overscan
*
* Purpose: Programs overscan border
* Input:   overscan
*
* Output:
   void
*/
static void program_overscan(
		struct dce110_transform *xfm110,
		const struct overscan_info *overscan)
{
	uint32_t overscan_left_right = 0;
	uint32_t overscan_top_bottom = 0;

	set_reg_field_value(overscan_left_right, overscan->left,
		SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);

	set_reg_field_value(overscan_left_right, overscan->right,
		SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);

	set_reg_field_value(overscan_top_bottom, overscan->top,
		SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);

	set_reg_field_value(overscan_top_bottom, overscan->bottom,
		SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);

	dm_write_reg(xfm110->base.ctx,
			mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
			overscan_left_right);

	dm_write_reg(xfm110->base.ctx,
			mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
			overscan_top_bottom);
}
/*
 * Function:
 * void setup_scaling_configuration
 *
 * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
 * Input:   data
 *
 * Output:
 *  void
 */
static bool setup_scaling_configuration(
	struct dce110_transform *xfm110,
	const struct scaler_data *data)
{
	bool is_scaling_needed = false;
	struct dc_context *ctx = xfm110->base.ctx;
	uint32_t value = 0;

	if (data->taps.h_taps + data->taps.v_taps > 2) {
		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
		is_scaling_needed = true;
	} else {
		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
	}

	if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
		is_scaling_needed = true;
	} else if (data->format != PIXEL_FORMAT_420BPP12) {
		set_reg_field_value(
			value,
			get_reg_field_value(value, SCLV_MODE, SCL_MODE),
			SCLV_MODE,
			SCL_MODE_C);
		set_reg_field_value(
			value,
			get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
			SCLV_MODE,
			SCL_PSCL_EN_C);
	} else {
		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
	}
	dm_write_reg(ctx, mmSCLV_MODE, value);

	value = 0;
	set_reg_field_value(value, data->taps.h_taps - 1,
			SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
	set_reg_field_value(value, data->taps.v_taps - 1,
			SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
	set_reg_field_value(value, data->taps.h_taps_c - 1,
			SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
	set_reg_field_value(value, data->taps.v_taps_c - 1,
			SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
	dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);

	value = 0;
	/*
	 * 0 - Replaced out of bound pixels with black pixel
	 * (or any other required color)
	 * 1 - Replaced out of bound pixels with the edge pixel
	 */
	set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
	dm_write_reg(ctx, mmSCLV_CONTROL, value);

	return is_scaling_needed;
}
/**
 *	set_truncation
 *	1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
 *	2) enable truncation
 *	3) HW remove 12bit FMT support for DCE8 power saving reason.
 */
static void set_truncation(
		struct dce80_opp *opp80,
		const struct bit_depth_reduction_params *params)
{
	uint32_t value = 0;
	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);

	/*Disable truncation*/
	value = dm_read_reg(opp80->base.ctx, addr);
	set_reg_field_value(value, 0,
		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
	set_reg_field_value(value, 0,
		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
	set_reg_field_value(value, 0,
		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);

	dm_write_reg(opp80->base.ctx, addr, value);

	/* no 10bpc trunc on DCE8*/
	if (params->flags.TRUNCATE_ENABLED == 0 ||
		params->flags.TRUNCATE_DEPTH == 2)
		return;

	/*Set truncation depth and Enable truncation*/
	set_reg_field_value(value, 1,
		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
	set_reg_field_value(value, params->flags.TRUNCATE_MODE,
		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
	set_reg_field_value(value, params->flags.TRUNCATE_DEPTH,
		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);

	dm_write_reg(opp80->base.ctx, addr, value);

}
/* luma part */
static void program_pri_addr_l(
	struct dce_mem_input *mem_input110,
	PHYSICAL_ADDRESS_LOC address)
{
	uint32_t value = 0;
	uint32_t temp = 0;

	/*high register MUST be programmed first*/
	temp = address.high_part &
UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK;

	set_reg_field_value(value, temp,
		UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L,
		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L);

	dm_write_reg(
		mem_input110->base.ctx,
		mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L,
		value);

	temp = 0;
	value = 0;
	temp = address.low_part >>
	UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT;

	set_reg_field_value(value, temp,
		UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L,
		GRPH_PRIMARY_SURFACE_ADDRESS_L);

	dm_write_reg(
		mem_input110->base.ctx,
		mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L,
		value);
}
static void dce110_tg_v_program_blank_color(struct timing_generator *tg,
		const struct tg_color *black_color)
{
	uint32_t addr = mmCRTCV_BLACK_COLOR;
	uint32_t value = dm_read_reg(tg->ctx, addr);

	set_reg_field_value(
		value,
		black_color->color_b_cb,
		CRTCV_BLACK_COLOR,
		CRTC_BLACK_COLOR_B_CB);
	set_reg_field_value(
		value,
		black_color->color_g_y,
		CRTCV_BLACK_COLOR,
		CRTC_BLACK_COLOR_G_Y);
	set_reg_field_value(
		value,
		black_color->color_r_cr,
		CRTCV_BLACK_COLOR,
		CRTC_BLACK_COLOR_R_CR);

	dm_write_reg(tg->ctx, addr, value);

	addr = mmCRTCV_BLANK_DATA_COLOR;
	dm_write_reg(tg->ctx, addr, value);
}
static bool dce110_timing_generator_v_enable_crtc(struct timing_generator *tg)
{
/*
* Set MASTER_UPDATE_MODE to 0
* This is needed for DRR, and also suggested to be default value by Syed.
*/

	uint32_t value;

	value = 0;
	set_reg_field_value(value, 0,
			CRTCV_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE);
	dm_write_reg(tg->ctx,
			mmCRTCV_MASTER_UPDATE_MODE, value);

	/* TODO: may want this on for looking for underflow */
	value = 0;
	dm_write_reg(tg->ctx, mmCRTCV_MASTER_UPDATE_MODE, value);

	value = 0;
	set_reg_field_value(value, 1,
			CRTCV_MASTER_EN, CRTC_MASTER_EN);
	dm_write_reg(tg->ctx,
			mmCRTCV_MASTER_EN, value);

	return true;
}
/* enable DP audio */
static void enable_dp_audio(
	const struct hw_ctx_audio *hw_ctx,
	enum engine_id engine_id)
{
	const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id];

	uint32_t value;

	/* Enable Audio packets */
	value = dm_read_reg(hw_ctx->ctx, addr);
	set_reg_field_value(value, 1,
		DP_SEC_CNTL,
		DP_SEC_ASP_ENABLE);

	dm_write_reg(hw_ctx->ctx, addr, value);

	/* Program the ATP and AIP next */
	set_reg_field_value(value, 1,
		DP_SEC_CNTL,
		DP_SEC_ATP_ENABLE);

	set_reg_field_value(value, 1,
		DP_SEC_CNTL,
		DP_SEC_AIP_ENABLE);

	dm_write_reg(hw_ctx->ctx, addr, value);

	/* Program STREAM_ENABLE after all the other enables. */
	set_reg_field_value(value, 1,
		DP_SEC_CNTL,
		DP_SEC_STREAM_ENABLE);

	dm_write_reg(hw_ctx->ctx, addr, value);
}
Beispiel #8
0
void generic_write_indirect_reg(const struct dc_context *ctx,
		uint32_t addr_index, uint32_t addr_data,
		uint32_t index, uint32_t data)
{
	dm_write_reg(ctx, addr_index, index);
	dm_write_reg(ctx, addr_data, data);
}
Beispiel #9
0
void dce110_compressor_set_fbc_invalidation_triggers(
	struct compressor *compressor,
	uint32_t fbc_trigger)
{
	/* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)
	 * for DCE 11 regions cannot be used - does not work with S/G
	 */
	uint32_t addr = mmFBC_CLIENT_REGION_MASK;
	uint32_t value = dm_read_reg(compressor->ctx, addr);

	set_reg_field_value(
		value,
		0,
		FBC_CLIENT_REGION_MASK,
		FBC_MEMORY_REGION_MASK);
	dm_write_reg(compressor->ctx, addr, value);

	/* Setup events when to clear all CSM entries (effectively marking
	 * current compressed data invalid)
	 * For DCE 11 CSM metadata 11111 means - "Not Compressed"
	 * Used as the initial value of the metadata sent to the compressor
	 * after invalidation, to indicate that the compressor should attempt
	 * to compress all chunks on the current pass.  Also used when the chunk
	 * is not successfully written to memory.
	 * When this CSM value is detected, FBC reads from the uncompressed
	 * buffer. Set events according to passed in value, these events are
	 * valid for DCE11:
	 *     - bit  0 - display register updated
	 *     - bit 28 - memory write from any client except from MCIF
	 *     - bit 29 - CG static screen signal is inactive
	 * In addition, DCE11.1 also needs to set new DCE11.1 specific events
	 * that are used to trigger invalidation on certain register changes,
	 * for example enabling of Alpha Compression may trigger invalidation of
	 * FBC once bit is set. These events are as follows:
	 *      - Bit 2 - FBC_GRPH_COMP_EN register updated
	 *      - Bit 3 - FBC_SRC_SEL register updated
	 *      - Bit 4 - FBC_MIN_COMPRESSION register updated
	 *      - Bit 5 - FBC_ALPHA_COMP_EN register updated
	 *      - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated
	 *      - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated
	 */
	addr = mmFBC_IDLE_FORCE_CLEAR_MASK;
	value = dm_read_reg(compressor->ctx, addr);
	set_reg_field_value(
		value,
		fbc_trigger |
		FBC_IDLE_FORCE_GRPH_COMP_EN |
		FBC_IDLE_FORCE_SRC_SEL_CHANGE |
		FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE |
		FBC_IDLE_FORCE_ALPHA_COMP_EN |
		FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN |
		FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF,
		FBC_IDLE_FORCE_CLEAR_MASK,
		FBC_IDLE_FORCE_CLEAR_MASK);
	dm_write_reg(compressor->ctx, addr, value);
}
static void program_urgency_watermark(
	const struct dc_context *ctx,
	const uint32_t urgency_addr,
	const uint32_t wm_addr,
	struct dce_watermarks marks_low,
	uint32_t total_dest_line_time_ns)
{
	/* register value */
	uint32_t urgency_cntl = 0;
	uint32_t wm_mask_cntl = 0;

	/*Write mask to enable reading/writing of watermark set A*/
	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
	set_reg_field_value(wm_mask_cntl,
			1,
			DPGV0_WATERMARK_MASK_CONTROL,
			URGENCY_WATERMARK_MASK);
	dm_write_reg(ctx, wm_addr, wm_mask_cntl);

	urgency_cntl = dm_read_reg(ctx, urgency_addr);

	set_reg_field_value(
		urgency_cntl,
		marks_low.a_mark,
		DPGV0_PIPE_URGENCY_CONTROL,
		URGENCY_LOW_WATERMARK);

	set_reg_field_value(
		urgency_cntl,
		total_dest_line_time_ns,
		DPGV0_PIPE_URGENCY_CONTROL,
		URGENCY_HIGH_WATERMARK);
	dm_write_reg(ctx, urgency_addr, urgency_cntl);

	/*Write mask to enable reading/writing of watermark set B*/
	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
	set_reg_field_value(wm_mask_cntl,
			2,
			DPGV0_WATERMARK_MASK_CONTROL,
			URGENCY_WATERMARK_MASK);
	dm_write_reg(ctx, wm_addr, wm_mask_cntl);

	urgency_cntl = dm_read_reg(ctx, urgency_addr);

	set_reg_field_value(urgency_cntl,
		marks_low.b_mark,
		DPGV0_PIPE_URGENCY_CONTROL,
		URGENCY_LOW_WATERMARK);

	set_reg_field_value(urgency_cntl,
		total_dest_line_time_ns,
		DPGV0_PIPE_URGENCY_CONTROL,
		URGENCY_HIGH_WATERMARK);

	dm_write_reg(ctx, urgency_addr, urgency_cntl);
}
/* setup Azalia HW block */
static void setup_azalia(
	const struct hw_ctx_audio *hw_ctx,
	enum engine_id engine_id,
	enum signal_type signal,
	const struct audio_crtc_info *crtc_info,
	const struct audio_pll_info *pll_info,
	const struct audio_info *audio_info)
{
	uint32_t speakers = 0;
	uint32_t channels = 0;

	if (audio_info == NULL)
		/* This should not happen.it does so we don't get BSOD*/
		return;

	speakers = audio_info->flags.info.ALLSPEAKERS;
	channels = dal_audio_hw_ctx_speakers_to_channels(
		hw_ctx,
		audio_info->flags.speaker_flags).all;

	/* setup the audio stream source select (audio -> dig mapping) */
	{
		const uint32_t addr =
			mmAFMT_AUDIO_SRC_CONTROL + engine_offset[engine_id];

		uint32_t value = 0;
		/*convert one-based index to zero-based */
		set_reg_field_value(value,
			FROM_BASE(hw_ctx)->azalia_stream_id - 1,
			AFMT_AUDIO_SRC_CONTROL,
			AFMT_AUDIO_SRC_SELECT);

		dm_write_reg(hw_ctx->ctx, addr, value);
	}

	/* Channel allocation */
	{
		const uint32_t addr =
			mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
		uint32_t value = dm_read_reg(hw_ctx->ctx, addr);

		set_reg_field_value(value,
			channels,
			AFMT_AUDIO_PACKET_CONTROL2,
			AFMT_AUDIO_CHANNEL_ENABLE);

		dm_write_reg(hw_ctx->ctx, addr, value);
	}

	configure_azalia(hw_ctx, signal, crtc_info, audio_info);
}
Beispiel #12
0
void dce110_compressor_enable_fbc(
	struct compressor *compressor,
	struct compr_addr_and_pitch_params *params)
{
	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);

	if (compressor->options.bits.FBC_SUPPORT &&
		(!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL))) {

		uint32_t addr;
		uint32_t value, misc_value;


		addr = mmFBC_CNTL;
		value = dm_read_reg(compressor->ctx, addr);
		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
		set_reg_field_value(
			value,
			params->inst,
			FBC_CNTL, FBC_SRC_SEL);
		dm_write_reg(compressor->ctx, addr, value);

		/* Keep track of enum controller_id FBC is attached to */
		compressor->is_enabled = true;
		compressor->attached_inst = params->inst;
		cp110->offsets = reg_offsets[params->inst];

		/* Toggle it as there is bug in HW */
		set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
		dm_write_reg(compressor->ctx, addr, value);

		/* FBC usage with scatter & gather for dce110 */
		misc_value = dm_read_reg(compressor->ctx, mmFBC_MISC);

		set_reg_field_value(misc_value, 1,
				FBC_MISC, FBC_INVALIDATE_ON_ERROR);
		set_reg_field_value(misc_value, 1,
				FBC_MISC, FBC_DECOMPRESS_ERROR_CLEAR);
		set_reg_field_value(misc_value, 0x14,
				FBC_MISC, FBC_SLOW_REQ_INTERVAL);

		dm_write_reg(compressor->ctx, mmFBC_MISC, misc_value);

		/* Enable FBC */
		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
		dm_write_reg(compressor->ctx, addr, value);

		wait_for_fbc_state_changed(cp110, true);
	}
}
static bool hpd_ack(
	struct irq_service *irq_service,
	const struct irq_source_info *info)
{
	uint32_t addr = info->status_reg;
	uint32_t value = dm_read_reg(irq_service->ctx, addr);
	uint32_t current_status =
		get_reg_field_value(
			value,
			HPD0_DC_HPD_INT_STATUS,
			DC_HPD_SENSE_DELAYED);

	dal_irq_service_ack_generic(irq_service, info);

	value = dm_read_reg(irq_service->ctx, info->enable_reg);

	set_reg_field_value(
		value,
		current_status ? 0 : 1,
		HPD0_DC_HPD_INT_CONTROL,
		DC_HPD_INT_POLARITY);

	dm_write_reg(irq_service->ctx, info->enable_reg, value);

	return true;
}
void dce110_opp_power_on_regamma_lut_v(
	struct transform *xfm,
	bool power_on)
{
	uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);

	set_reg_field_value(
		value,
		0,
		DCFEV_MEM_PWR_CTRL,
		COL_MAN_GAMMA_CORR_MEM_PWR_FORCE);

	set_reg_field_value(
		value,
		power_on,
		DCFEV_MEM_PWR_CTRL,
		COL_MAN_GAMMA_CORR_MEM_PWR_DIS);

	set_reg_field_value(
		value,
		0,
		DCFEV_MEM_PWR_CTRL,
		COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE);

	set_reg_field_value(
		value,
		power_on,
		DCFEV_MEM_PWR_CTRL,
		COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);

	dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value);
}
static void enable_afmt_clock(
	const struct hw_ctx_audio *hw_ctx,
	enum engine_id engine_id,
	bool enable_flag)
{
	uint32_t engine_offs = engine_offset[engine_id];
	uint32_t value;
	uint32_t count = 0;
	uint32_t enable = enable_flag ? 1:0;

	/* Enable Audio packets*/
	value = dm_read_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs);

	/*enable AFMT clock*/
	set_reg_field_value(value, enable,
		AFMT_CNTL, AFMT_AUDIO_CLOCK_EN);
	dm_write_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs, value);

	/*wait for AFMT clock to turn on,
	 * the expectation is that this
	 * should complete in 1-2 reads)
	 */
	do {
		/* Wait for 1us between subsequent register reads.*/
		udelay(1);
		value = dm_read_reg(hw_ctx->ctx,
				mmAFMT_CNTL + engine_offs);
	} while (get_reg_field_value(value,
				AFMT_CNTL, AFMT_AUDIO_CLOCK_ON) !=
						enable && count++ < 10);
}
void dce80_stream_encoder_stop_dp_info_packets(
	struct stream_encoder *enc)
{
	/* stop generic packets on DP */
	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
	struct dc_context *ctx = enc110->base.ctx;
	uint32_t addr = LINK_REG(DP_SEC_CNTL);
	uint32_t value = dm_read_reg(ctx, addr);

	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP0_ENABLE);
	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP1_ENABLE);
	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP2_ENABLE);
	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP3_ENABLE);
	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_AVI_ENABLE);
	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_MPG_ENABLE);
	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_STREAM_ENABLE);

	/* this register shared with audio info frame.
	* therefore we need to keep master enabled
	* if at least one of the fields is not 0
	*/

	if (value)
		set_reg_field_value(
			value,
			1,
			DP_SEC_CNTL,
			DP_SEC_STREAM_ENABLE);

	dm_write_reg(ctx, addr, value);
}
static void dce110_timing_generator_v_set_overscan_color(struct timing_generator *tg,
	const struct tg_color *overscan_color)
{
	struct dc_context *ctx = tg->ctx;
	uint32_t value = 0;
	uint32_t addr;

	set_reg_field_value(
		value,
		overscan_color->color_b_cb,
		CRTCV_OVERSCAN_COLOR,
		CRTC_OVERSCAN_COLOR_BLUE);

	set_reg_field_value(
		value,
		overscan_color->color_g_y,
		CRTCV_OVERSCAN_COLOR,
		CRTC_OVERSCAN_COLOR_GREEN);

	set_reg_field_value(
		value,
		overscan_color->color_r_cr,
		CRTCV_OVERSCAN_COLOR,
		CRTC_OVERSCAN_COLOR_RED);

	addr = mmCRTCV_OVERSCAN_COLOR;
	dm_write_reg(ctx, addr, value);
}
static void setup_i2c_polling(
	struct dc_context *ctx,
	const uint32_t addr,
	bool enable_detect,
	bool detect_mode)
{
	uint32_t value;

	value = dm_read_reg(ctx, addr);

	set_reg_field_value(
		value,
		enable_detect,
		DC_I2C_DDC1_SETUP,
		DC_I2C_DDC1_ENABLE);

	set_reg_field_value(
		value,
		enable_detect,
		DC_I2C_DDC1_SETUP,
		DC_I2C_DDC1_EDID_DETECT_ENABLE);

	if (enable_detect)
		set_reg_field_value(
			value,
			detect_mode,
			DC_I2C_DDC1_SETUP,
			DC_I2C_DDC1_EDID_DETECT_MODE);

	dm_write_reg(ctx, addr, value);
}
/* initialize HW state */
static void hw_initialize(
	const struct hw_ctx_audio *hw_ctx)
{
	uint32_t stream_id = FROM_BASE(hw_ctx)->azalia_stream_id;
	uint32_t addr;

	/* we only need to program the following registers once, so we only do
	it for the first audio stream.*/
	if (stream_id != FIRST_AUDIO_STREAM_ID)
		return;

	/* Suport R5 - 32khz
	 * Suport R6 - 44.1khz
	 * Suport R7 - 48khz
	 */
	addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES;
	{
		uint32_t value;

		value = dm_read_reg(hw_ctx->ctx, addr);

		set_reg_field_value(value, 0x70,
		AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES,
		AUDIO_RATE_CAPABILITIES);

		dm_write_reg(hw_ctx->ctx, addr, value);
	}

	/*Keep alive bit to verify HW block in BU. */
	addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES;
	{
		uint32_t value;

		value = dm_read_reg(hw_ctx->ctx, addr);

		set_reg_field_value(value, 1,
		AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
		CLKSTOP);

		set_reg_field_value(value, 1,
		AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
		EPSS);
		dm_write_reg(hw_ctx->ctx, addr, value);
	}
}
static void dce110_timing_generator_v_set_overscan_color_black(
	struct timing_generator *tg,
	const struct tg_color *color)
{
	struct dc_context *ctx = tg->ctx;
	uint32_t addr;
	uint32_t value = 0;

	set_reg_field_value(
			value,
			color->color_b_cb,
			CRTC_OVERSCAN_COLOR,
			CRTC_OVERSCAN_COLOR_BLUE);

	set_reg_field_value(
			value,
			color->color_r_cr,
			CRTC_OVERSCAN_COLOR,
			CRTC_OVERSCAN_COLOR_RED);

	set_reg_field_value(
			value,
			color->color_g_y,
			CRTC_OVERSCAN_COLOR,
			CRTC_OVERSCAN_COLOR_GREEN);

	addr = mmCRTCV_OVERSCAN_COLOR;
	dm_write_reg(ctx, addr, value);
	addr = mmCRTCV_BLACK_COLOR;
	dm_write_reg(ctx, addr, value);
	/* This is desirable to have a constant DAC output voltage during the
	 * blank time that is higher than the 0 volt reference level that the
	 * DAC outputs when the NBLANK signal
	 * is asserted low, such as for output to an analog TV. */
	addr = mmCRTCV_BLANK_DATA_COLOR;
	dm_write_reg(ctx, addr, value);

	/* TO DO we have to program EXT registers and we need to know LB DATA
	 * format because it is used when more 10 , i.e. 12 bits per color
	 *
	 * m_mmDxCRTC_OVERSCAN_COLOR_EXT
	 * m_mmDxCRTC_BLACK_COLOR_EXT
	 * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
	 */
}
/* setup stream encoder in dvi mode */
void dce80_stream_encoder_dvi_set_stream_attribute(
	struct stream_encoder *enc,
	struct dc_crtc_timing *crtc_timing,
	bool is_dual_link)
{
	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
	struct dc_context *ctx = enc110->base.ctx;
	uint32_t addr = LINK_REG(TMDS_CNTL);
	uint32_t value = dm_read_reg(ctx, addr);
	struct bp_encoder_control cntl = {0};

	cntl.action = ENCODER_CONTROL_SETUP;
	cntl.engine_id = enc110->base.id;
	cntl.signal = is_dual_link ?
		SIGNAL_TYPE_DVI_DUAL_LINK :
		SIGNAL_TYPE_DVI_SINGLE_LINK;
	cntl.enable_dp_audio = false;
	cntl.pixel_clock = crtc_timing->pix_clk_khz;
	cntl.lanes_number = (is_dual_link) ?
				LANE_COUNT_EIGHT : LANE_COUNT_FOUR;
	cntl.color_depth = crtc_timing->display_color_depth;

	if (enc110->base.bp->funcs->encoder_control(
			enc110->base.bp, &cntl) != BP_RESULT_OK)
		return;

	switch (crtc_timing->pixel_encoding) {
	case PIXEL_ENCODING_YCBCR422:
		set_reg_field_value(value, 1, TMDS_CNTL, TMDS_PIXEL_ENCODING);
		break;
	default:
		set_reg_field_value(value, 0, TMDS_CNTL, TMDS_PIXEL_ENCODING);
		break;
	}

	switch (crtc_timing->pixel_encoding) {
	case COLOR_DEPTH_101010:
		if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
			set_reg_field_value(
				value,
				2,
				TMDS_CNTL,
				TMDS_COLOR_FORMAT);
		else
			set_reg_field_value(
				value,
				0,
				TMDS_CNTL,
				TMDS_COLOR_FORMAT);
		break;
	default:
		set_reg_field_value(value, 0, TMDS_CNTL, TMDS_COLOR_FORMAT);
		break;
	}
	dm_write_reg(ctx, addr, value);
}
static void enable(struct dce_mem_input *mem_input110)
{
	uint32_t value = 0;

	value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_ENABLE);
	set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE);
	dm_write_reg(mem_input110->base.ctx,
		mmUNP_GRPH_ENABLE,
		value);
}
static void dce110_transform_v_set_scalerv_bypass(struct transform *xfm)
{
	uint32_t addr = mmSCLV_MODE;
	uint32_t value = dm_read_reg(xfm->ctx, addr);

	set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
	set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
	set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
	set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
	dm_write_reg(xfm->ctx, addr, value);
}
Beispiel #24
0
uint32_t generic_read_indirect_reg(const struct dc_context *ctx,
		uint32_t addr_index, uint32_t addr_data,
		uint32_t index)
{
	uint32_t value = 0;

	dm_write_reg(ctx, addr_index, index);
	value = dm_read_reg(ctx, addr_data);

	return value;
}
void dce110_allocate_mem_input_v(
	struct mem_input *mi,
	uint32_t h_total,/* for current stream */
	uint32_t v_total,/* for current stream */
	uint32_t pix_clk_khz,/* for current stream */
	uint32_t total_stream_num)
{
	uint32_t addr;
	uint32_t value;
	uint32_t pix_dur;
	if (pix_clk_khz != 0) {
		addr = mmDPGV0_PIPE_ARBITRATION_CONTROL1;
		value = dm_read_reg(mi->ctx, addr);
		pix_dur = 1000000000ULL / pix_clk_khz;
		set_reg_field_value(
			value,
			pix_dur,
			DPGV0_PIPE_ARBITRATION_CONTROL1,
			PIXEL_DURATION);
		dm_write_reg(mi->ctx, addr, value);

		addr = mmDPGV1_PIPE_ARBITRATION_CONTROL1;
		value = dm_read_reg(mi->ctx, addr);
		pix_dur = 1000000000ULL / pix_clk_khz;
		set_reg_field_value(
			value,
			pix_dur,
			DPGV1_PIPE_ARBITRATION_CONTROL1,
			PIXEL_DURATION);
		dm_write_reg(mi->ctx, addr, value);

		addr = mmDPGV0_PIPE_ARBITRATION_CONTROL2;
		value = 0x4000800;
		dm_write_reg(mi->ctx, addr, value);

		addr = mmDPGV1_PIPE_ARBITRATION_CONTROL2;
		value = 0x4000800;
		dm_write_reg(mi->ctx, addr, value);
	}

}
static void dce110_timing_generator_v_set_early_control(
		struct timing_generator *tg,
		uint32_t early_cntl)
{
	uint32_t regval;
	uint32_t address = mmCRTC_CONTROL;

	regval = dm_read_reg(tg->ctx, address);
	set_reg_field_value(regval, early_cntl,
			CRTCV_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
	dm_write_reg(tg->ctx, address, regval);
}
static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode)
{
	uint32_t value = 0;

	set_reg_field_value(
				value,
				mode,
				GAMMA_CORR_CONTROL,
				GAMMA_CORR_MODE);

	dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0);
}
/* ---  helpers --- */
static void write_indirect_azalia_reg(
	const struct hw_ctx_audio *hw_ctx,
	uint32_t reg_index,
	uint32_t reg_data)
{
	uint32_t addr = 0;
	uint32_t value = 0;
	/* AZALIA_F0_CODEC_ENDPOINT_INDEX  endpoint index  */
	{
		addr =
			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
			azf0endpointx_azalia_f0_codec_endpoint_index;

		set_reg_field_value(value, reg_index,
			AZALIA_F0_CODEC_ENDPOINT_INDEX,
			AZALIA_ENDPOINT_REG_INDEX);

		dm_write_reg(hw_ctx->ctx, addr, value);
	}

	/* AZALIA_F0_CODEC_ENDPOINT_DATA  endpoint data  */
	{
		addr =
			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
			azf0endpointx_azalia_f0_codec_endpoint_data;

		value = 0;
		set_reg_field_value(value, reg_data,
			AZALIA_F0_CODEC_ENDPOINT_DATA,
			AZALIA_ENDPOINT_REG_DATA);
		dm_write_reg(hw_ctx->ctx, addr, value);
	}

	dal_logger_write(
		hw_ctx->ctx->logger,
		LOG_MAJOR_HW_TRACE,
		LOG_MINOR_HW_TRACE_AUDIO,
		"AUDIO:write_indirect_azalia_reg: index: %u  data: %u\n",
		reg_index, reg_data);
}
static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
{
	int ret, i;

	mutex_lock(&dev->phy_mutex);

	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4);

	for (i = 0; i < DM_TIMEOUT; i++) {
		u8 tmp;

		udelay(1);
		ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
		if (ret < 0)
			goto out;

		
		if ((tmp & 1) == 0)
			break;
	}

	if (i == DM_TIMEOUT) {
		netdev_err(dev->net, "%s read timed out!\n", phy ? "phy" : "eeprom");
		ret = -EIO;
		goto out;
	}

	dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
	ret = dm_read(dev, DM_SHARED_DATA, 2, value);

	netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
		   phy, reg, *value, ret);

 out:
	mutex_unlock(&dev->phy_mutex);
	return ret;
}
Beispiel #30
0
static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 value)
{
	int ret, i;

	mutex_lock(&dev->phy_mutex);

	ret = dm_write(dev, DM_SHARED_DATA, 2, &value);
	if (ret < 0)
		goto out;

	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12);

	for (i = 0; i < DM_TIMEOUT; i++) {
		u8 tmp;

		udelay(1);
		ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
		if (ret < 0)
			goto out;

		/* ready */
		if ((tmp & 1) == 0)
			break;
	}

	if (i == DM_TIMEOUT) {
		netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom");
		ret = -EIO;
		goto out;
	}

	dm_write_reg(dev, DM_SHARED_CTRL, 0x0);

out:
	mutex_unlock(&dev->phy_mutex);
	return ret;
}