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

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
...@@ -103,6 +103,8 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) ...@@ -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, static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
u32 *vbl, u32 *position) 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)) if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
return -EINVAL; return -EINVAL;
else { else {
...@@ -113,7 +115,18 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, ...@@ -113,7 +115,18 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
return 0; 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; return 0;
......
...@@ -282,12 +282,14 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) ...@@ -282,12 +282,14 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream)
return 0; return 0;
} }
uint32_t dc_stream_get_scanoutpos( bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream,
const struct dc_stream *dc_stream, uint32_t *v_blank_start,
uint32_t *vbl, uint32_t *v_blank_end,
uint32_t *position) uint32_t *h_position,
uint32_t *v_position)
{ {
uint8_t i; uint8_t i;
bool ret = false;
struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc);
struct resource_context *res_ctx = struct resource_context *res_ctx =
...@@ -299,10 +301,17 @@ uint32_t dc_stream_get_scanoutpos( ...@@ -299,10 +301,17 @@ uint32_t dc_stream_get_scanoutpos(
if (res_ctx->pipe_ctx[i].stream != stream) if (res_ctx->pipe_ctx[i].stream != stream)
continue; 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;
} }
......
...@@ -484,8 +484,11 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream); ...@@ -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) * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos)
* being refactored properly to be dce-specific * being refactored properly to be dce-specific
*/ */
uint32_t dc_stream_get_scanoutpos( bool dc_stream_get_scanoutpos(const struct dc_stream *stream,
const struct dc_stream *stream, uint32_t *vbl, uint32_t *position); 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 * Structure to store surface/stream associations for validation
......
...@@ -574,29 +574,26 @@ void dce110_timing_generator_get_crtc_positions( ...@@ -574,29 +574,26 @@ void dce110_timing_generator_get_crtc_positions(
* @param [out] vpos, hpos * @param [out] vpos, hpos
***************************************************************************** *****************************************************************************
*/ */
uint32_t dce110_timing_generator_get_crtc_scanoutpos( void dce110_timing_generator_get_crtc_scanoutpos(
struct timing_generator *tg, struct timing_generator *tg,
uint32_t *vbl, uint32_t *v_blank_start,
uint32_t *position) uint32_t *v_blank_end,
uint32_t *h_position,
uint32_t *v_position)
{ {
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 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() */ uint32_t v_blank_start_end = dm_read_reg(tg->ctx,
*vbl = dm_read_reg(tg->ctx,
CRTC_REG(mmCRTC_V_BLANK_START_END)); CRTC_REG(mmCRTC_V_BLANK_START_END));
*position = dm_read_reg(tg->ctx, *v_blank_start = get_reg_field_value(v_blank_start_end,
CRTC_REG(mmCRTC_STATUS_POSITION)); 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 dce110_timing_generator_get_crtc_positions(tg, h_position, v_position);
* crtc is inside vblank*/
return 0;
} }
/* TODO: is it safe to assume that mask/shift of Primary and Underlay /* 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, ...@@ -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) bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
{ {
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 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 val = 0;
uint32_t position, vbl_start; uint32_t h_position, v_position;
tg->funcs->get_scanoutpos( tg->funcs->get_scanoutpos(
tg, tg,
&vbl, &v_blank_start,
&position); &v_blank_end,
&h_position,
&v_position);
if (vbl == 0) if (v_blank_start == 0 || v_blank_end == 0)
return false; return false;
vbl_start =
get_reg_field_value(
vbl,
CRTC_V_BLANK_START_END,
CRTC_V_BLANK_START);
set_reg_field_value( set_reg_field_value(
val, val,
vbl_start, v_blank_start,
CRTC_VERTICAL_INTERRUPT0_POSITION, CRTC_VERTICAL_INTERRUPT0_POSITION,
CRTC_VERTICAL_INTERRUPT0_LINE_START); 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( set_reg_field_value(
val, val,
vbl_start + width, v_blank_start + width,
CRTC_VERTICAL_INTERRUPT0_POSITION, CRTC_VERTICAL_INTERRUPT0_POSITION,
CRTC_VERTICAL_INTERRUPT0_LINE_END); CRTC_VERTICAL_INTERRUPT0_LINE_END);
......
...@@ -230,10 +230,12 @@ void dce110_timing_generator_set_static_screen_control( ...@@ -230,10 +230,12 @@ void dce110_timing_generator_set_static_screen_control(
struct timing_generator *tg, struct timing_generator *tg,
uint32_t value); uint32_t value);
uint32_t dce110_timing_generator_get_crtc_scanoutpos( void dce110_timing_generator_get_crtc_scanoutpos(
struct timing_generator *tg, struct timing_generator *tg,
uint32_t *vbl, uint32_t *v_blank_start,
uint32_t *position); uint32_t *v_blank_end,
uint32_t *h_position,
uint32_t *v_position);
void dce110_timing_generator_enable_advanced_request( void dce110_timing_generator_enable_advanced_request(
struct timing_generator *tg, struct timing_generator *tg,
......
...@@ -576,24 +576,28 @@ void dce120_timing_generator_set_drr( ...@@ -576,24 +576,28 @@ void dce120_timing_generator_set_drr(
} }
} }
uint32_t dce120_timing_generator_get_crtc_scanoutpos( void dce120_timing_generator_get_crtc_scanoutpos(
struct timing_generator *tg, struct timing_generator *tg,
uint32_t *vbl, uint32_t *v_blank_start,
uint32_t *position) uint32_t *v_blank_end,
uint32_t *h_position,
uint32_t *v_position)
{ {
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
*vbl = dm_read_reg_soc15( uint32_t v_blank_start_end = dm_read_reg_soc15(
tg->ctx, tg->ctx,
mmCRTC0_CRTC_V_BLANK_START_END, mmCRTC0_CRTC_V_BLANK_START_END,
tg110->offsets.crtc); tg110->offsets.crtc);
*position = dm_read_reg_soc15( *v_blank_start = get_reg_field_value(v_blank_start_end,
tg->ctx, CRTC0_CRTC_V_BLANK_START_END,
mmCRTC0_CRTC_STATUS_POSITION, CRTC_V_BLANK_START);
tg110->offsets.crtc); *v_blank_end = get_reg_field_value(v_blank_start_end,
CRTC0_CRTC_V_BLANK_START_END,
CRTC_V_BLANK_END);
return 0; dce120_timing_generator_get_crtc_positions(tg, h_position, v_position);
} }
void dce120_timing_generator_enable_advanced_request( void dce120_timing_generator_enable_advanced_request(
...@@ -1044,26 +1048,22 @@ static bool dce120_arm_vert_intr( ...@@ -1044,26 +1048,22 @@ static bool dce120_arm_vert_intr(
uint8_t width) uint8_t width)
{ {
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
uint32_t vbl, position, vbl_start; uint32_t v_blank_start, v_blank_end, h_position, v_position;
tg->funcs->get_scanoutpos( tg->funcs->get_scanoutpos(
tg, tg,
&vbl, &v_blank_start,
&position); &v_blank_end,
&h_position,
&v_position);
if (vbl == 0) if (v_blank_start == 0 || v_blank_end == 0)
return false; return false;
vbl_start =
get_reg_field_value(
vbl,
CRTC0_CRTC_V_BLANK_START_END,
CRTC_V_BLANK_START);
CRTC_REG_SET_2( CRTC_REG_SET_2(
CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION, CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
CRTC_VERTICAL_INTERRUPT0_LINE_START, vbl_start, CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
CRTC_VERTICAL_INTERRUPT0_LINE_END, vbl_start + width); CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
return true; return true;
} }
......
...@@ -120,10 +120,12 @@ struct timing_generator_funcs { ...@@ -120,10 +120,12 @@ struct timing_generator_funcs {
int32_t *h_position, int32_t *h_position,
int32_t *v_position); int32_t *v_position);
uint32_t (*get_frame_count)(struct timing_generator *tg); uint32_t (*get_frame_count)(struct timing_generator *tg);
uint32_t (*get_scanoutpos)( void (*get_scanoutpos)(
struct timing_generator *tg, struct timing_generator *tg,
uint32_t *vbl, uint32_t *v_blank_start,
uint32_t *position); uint32_t *v_blank_end,
uint32_t *h_position,
uint32_t *v_position);
void (*set_early_control)(struct timing_generator *tg, void (*set_early_control)(struct timing_generator *tg,
uint32_t early_cntl); uint32_t early_cntl);
void (*wait_for_state)(struct timing_generator *tg, void (*wait_for_state)(struct timing_generator *tg,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment