Commit 81c50963 authored by Sylvia Tsai's avatar Sylvia Tsai Committed by Alex Deucher
Browse files

drm/amd/display: Parse scanline registers



They could differ between ASIC generations

Signed-off-by: default avatarSylvia Tsai <sylvia.tsai@amd.com>
Signed-off-by: default avatarHarry Wentland <harry.wentland@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 1ce71fcd
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -103,6 +103,8 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
					u32 *vbl, u32 *position)
{
	uint32_t v_blank_start, v_blank_end, h_position, v_position;

	if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
		return -EINVAL;
	else {
@@ -113,7 +115,18 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
			return 0;
		}

		return dc_stream_get_scanoutpos(acrtc->stream, vbl, position);
		/*
		 * TODO rework base driver to use values directly.
		 * for now parse it back into reg-format
		 */
		dc_stream_get_scanoutpos(acrtc->stream,
					 &v_blank_start,
					 &v_blank_end,
					 &h_position,
					 &v_position);

		*position = (v_position) || (h_position << 16);
		*vbl = (v_blank_start) || (v_blank_end << 16);
	}

	return 0;
+15 −6
Original line number Diff line number Diff line
@@ -282,12 +282,14 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream)
	return 0;
}

uint32_t dc_stream_get_scanoutpos(
		const struct dc_stream *dc_stream,
		uint32_t *vbl,
		uint32_t *position)
bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream,
				  uint32_t *v_blank_start,
				  uint32_t *v_blank_end,
				  uint32_t *h_position,
				  uint32_t *v_position)
{
	uint8_t i;
	bool ret = false;
	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
	struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc);
	struct resource_context *res_ctx =
@@ -299,10 +301,17 @@ uint32_t dc_stream_get_scanoutpos(
		if (res_ctx->pipe_ctx[i].stream != stream)
			continue;

		return tg->funcs->get_scanoutpos(tg, vbl, position);
		tg->funcs->get_scanoutpos(tg,
					  v_blank_start,
					  v_blank_end,
					  h_position,
					  v_position);

		ret = true;
		break;
	}

	return 0;
	return ret;
}


+5 −2
Original line number Diff line number Diff line
@@ -484,8 +484,11 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream);
 * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos)
 * being refactored properly to be dce-specific
 */
uint32_t dc_stream_get_scanoutpos(
		const struct dc_stream *stream, uint32_t *vbl, uint32_t *position);
bool dc_stream_get_scanoutpos(const struct dc_stream *stream,
				  uint32_t *v_blank_start,
				  uint32_t *v_blank_end,
				  uint32_t *h_position,
				  uint32_t *v_position);

/*
 * Structure to store surface/stream associations for validation
+24 −30
Original line number Diff line number Diff line
@@ -574,29 +574,26 @@ void dce110_timing_generator_get_crtc_positions(
 *  @param [out] vpos, hpos
 *****************************************************************************
 */
uint32_t dce110_timing_generator_get_crtc_scanoutpos(
void dce110_timing_generator_get_crtc_scanoutpos(
	struct timing_generator *tg,
	uint32_t *vbl,
	uint32_t *position)
	uint32_t *v_blank_start,
	uint32_t *v_blank_end,
	uint32_t *h_position,
	uint32_t *v_position)
{
	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
	/* TODO 1: Update the implementation once caller is updated
	 * WARNING!! This function is returning the whole register value
	 * because the caller is expecting it instead of proper vertical and
	 * horizontal position. This should be a temporary implementation
	 * until the caller is updated. */

	/* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */

	*vbl = dm_read_reg(tg->ctx,
	uint32_t v_blank_start_end  = dm_read_reg(tg->ctx,
			CRTC_REG(mmCRTC_V_BLANK_START_END));

	*position = dm_read_reg(tg->ctx,
			CRTC_REG(mmCRTC_STATUS_POSITION));
	*v_blank_start = get_reg_field_value(v_blank_start_end,
					     CRTC_V_BLANK_START_END,
					     CRTC_V_BLANK_START);
	*v_blank_end = get_reg_field_value(v_blank_start_end,
					   CRTC_V_BLANK_START_END,
					   CRTC_V_BLANK_END);

	/* @TODO: return value should indicate if current
	 * crtc is inside vblank*/
	return 0;
	dce110_timing_generator_get_crtc_positions(tg, h_position, v_position);
}

/* TODO: is it safe to assume that mask/shift of Primary and Underlay
@@ -1875,34 +1872,31 @@ void dce110_tg_set_colors(struct timing_generator *tg,
bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
{
	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
	uint32_t vbl = 0;
	uint32_t v_blank_start = 0;
	uint32_t v_blank_end = 0;
	uint32_t val = 0;
	uint32_t position, vbl_start;
	uint32_t h_position, v_position;

	tg->funcs->get_scanoutpos(
			tg,
			&vbl,
			&position);
			&v_blank_start,
			&v_blank_end,
			&h_position,
			&v_position);

	if (vbl == 0)
	if (v_blank_start == 0 || v_blank_end == 0)
		return false;

	vbl_start =
		get_reg_field_value(
		vbl,
		CRTC_V_BLANK_START_END,
		CRTC_V_BLANK_START);

	set_reg_field_value(
		val,
		vbl_start,
		v_blank_start,
		CRTC_VERTICAL_INTERRUPT0_POSITION,
		CRTC_VERTICAL_INTERRUPT0_LINE_START);

	/* Set interaval width for interrupt to fire to 1 scanline */
	/* Set interval width for interrupt to fire to 1 scanline */
	set_reg_field_value(
		val,
		vbl_start + width,
		v_blank_start + width,
		CRTC_VERTICAL_INTERRUPT0_POSITION,
		CRTC_VERTICAL_INTERRUPT0_LINE_END);

+5 −3
Original line number Diff line number Diff line
@@ -230,10 +230,12 @@ void dce110_timing_generator_set_static_screen_control(
	struct timing_generator *tg,
	uint32_t value);

uint32_t dce110_timing_generator_get_crtc_scanoutpos(
void dce110_timing_generator_get_crtc_scanoutpos(
	struct timing_generator *tg,
	uint32_t *vbl,
	uint32_t *position);
	uint32_t *v_blank_start,
	uint32_t *v_blank_end,
	uint32_t *h_position,
	uint32_t *v_position);

void dce110_timing_generator_enable_advanced_request(
	struct timing_generator *tg,
Loading