aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc
diff options
context:
space:
mode:
authorEric Cook <Eric.Cook@amd.com>2017-04-18 15:24:50 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-09-26 18:06:40 -0400
commit72ada5f76939ed00c07c584be7691a29d3c2c3da (patch)
tree007e160c3693837ee540670548c4478391630380 /drivers/gpu/drm/amd/display/dc
parentdrm/amd/display: no need for return value from ipp_program_degamma_pwl (diff)
downloadlinux-72ada5f76939ed00c07c584be7691a29d3c2c3da.tar.gz
linux-72ada5f76939ed00c07c584be7691a29d3c2c3da.zip
drm/amd/display: FreeSync Auto Sweep Support
Implement core support to allow for FreeSync Auto Sweep to work Signed-off-by: Eric Cook <Eric.Cook@amd.com> Acked-by: Harry Wentland <Harry.Wentland@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c28
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_debug.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c61
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c73
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h3
11 files changed, 159 insertions, 74 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 93c936d92f5a..2e74faef68e7 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -175,6 +175,31 @@ static bool stream_adjust_vmin_vmax(struct dc *dc,
return ret;
}
+static bool stream_get_crtc_position(struct dc *dc,
+ const struct dc_stream **stream, int num_streams,
+ unsigned int *v_pos, unsigned int *nom_v_pos)
+{
+ /* TODO: Support multiple streams */
+ struct core_dc *core_dc = DC_TO_CORE(dc);
+ struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]);
+ int i = 0;
+ bool ret = false;
+ struct crtc_position position;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe =
+ &core_dc->current_context->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream == core_stream && pipe->stream_enc) {
+ core_dc->hwss.get_position(&pipe, 1, &position);
+
+ *v_pos = position.vertical_count;
+ *nom_v_pos = position.nominal_vcount;
+ ret = true;
+ }
+ }
+ return ret;
+}
static bool set_gamut_remap(struct dc *dc,
const struct dc_stream **stream, int num_streams)
@@ -349,6 +374,9 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc)
core_dc->public.stream_funcs.set_static_screen_events =
set_static_screen_events;
+ core_dc->public.stream_funcs.get_crtc_position =
+ stream_get_crtc_position;
+
core_dc->public.stream_funcs.set_gamut_remap =
set_gamut_remap;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
index fb48b8909e7f..ee840e75ee1f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
@@ -287,6 +287,7 @@ void context_timing_trace(
struct core_dc *core_dc = DC_TO_CORE(dc);
struct dal_logger *logger = core_dc->ctx->logger;
int h_pos[MAX_PIPES], v_pos[MAX_PIPES];
+ struct crtc_position position;
for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
@@ -294,7 +295,9 @@ void context_timing_trace(
if (pipe_ctx->stream == NULL)
continue;
- pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos[i], &v_pos[i]);
+ pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &position);
+ h_pos[i] = position.horizontal_count;
+ v_pos[i] = position.vertical_count;
}
for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index d12aa726164e..647c095e0ae9 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -103,6 +103,12 @@ struct dc_stream_funcs {
int num_streams,
int vmin,
int vmax);
+ bool (*get_crtc_position)(struct dc *dc,
+ const struct dc_stream **stream,
+ int num_streams,
+ unsigned int *v_pos,
+ unsigned int *nom_v_pos);
+
void (*stream_update_scaling)(const struct dc *dc,
const struct dc_stream *dc_stream,
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 6a93c96b9b26..0e69aceb0bad 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -1362,6 +1362,18 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
}
}
+static void get_position(struct pipe_ctx **pipe_ctx,
+ int num_pipes,
+ struct crtc_position *position)
+{
+ int i = 0;
+
+ /* TODO: handle pipes > 1
+ */
+ for (i = 0; i < num_pipes; i++)
+ pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position);
+}
+
static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
int num_pipes, const struct dc_static_screen_events *events)
{
@@ -2486,6 +2498,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
.pipe_control_lock = dce_pipe_control_lock,
.set_bandwidth = dce110_set_bandwidth,
.set_drr = set_drr,
+ .get_position = get_position,
.set_static_screen_control = set_static_screen_control,
.reset_hw_ctx_wrap = reset_hw_ctx_wrap,
.prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg,
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
index 23760727f000..ec599276ed2e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
@@ -518,34 +518,38 @@ uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)
/**
*****************************************************************************
- * Function: dce110_get_crtc_positions
+ * Function: dce110_timing_generator_get_position
*
* @brief
* Returns CRTC vertical/horizontal counters
*
- * @param [out] v_position, h_position
+ * @param [out] position
*****************************************************************************
*/
-
-void dce110_timing_generator_get_crtc_positions(
- struct timing_generator *tg,
- int32_t *h_position,
- int32_t *v_position)
+void dce110_timing_generator_get_position(struct timing_generator *tg,
+ struct crtc_position *position)
{
uint32_t value;
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION));
- *h_position = get_reg_field_value(
+ position->horizontal_count = get_reg_field_value(
value,
CRTC_STATUS_POSITION,
CRTC_HORZ_COUNT);
- *v_position = get_reg_field_value(
+ position->vertical_count = get_reg_field_value(
value,
CRTC_STATUS_POSITION,
CRTC_VERT_COUNT);
+
+ value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION));
+
+ position->nominal_vcount = get_reg_field_value(
+ value,
+ CRTC_NOM_VERT_POSITION,
+ CRTC_VERT_COUNT_NOM);
}
/**
@@ -566,18 +570,23 @@ void dce110_timing_generator_get_crtc_scanoutpos(
uint32_t *v_position)
{
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+ struct crtc_position position;
- uint32_t v_blank_start_end = dm_read_reg(tg->ctx,
+ uint32_t value = dm_read_reg(tg->ctx,
CRTC_REG(mmCRTC_V_BLANK_START_END));
- *v_blank_start = get_reg_field_value(v_blank_start_end,
+ *v_blank_start = get_reg_field_value(value,
CRTC_V_BLANK_START_END,
CRTC_V_BLANK_START);
- *v_blank_end = get_reg_field_value(v_blank_start_end,
+ *v_blank_end = get_reg_field_value(value,
CRTC_V_BLANK_START_END,
CRTC_V_BLANK_END);
- dce110_timing_generator_get_crtc_positions(tg, h_position, v_position);
+ dce110_timing_generator_get_position(
+ tg, &position);
+
+ *h_position = position.horizontal_count;
+ *v_position = position.vertical_count;
}
/* TODO: is it safe to assume that mask/shift of Primary and Underlay
@@ -1344,15 +1353,13 @@ void dce110_timing_generator_tear_down_global_swap_lock(
*/
bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
{
- uint32_t h1 = 0;
- uint32_t h2 = 0;
- uint32_t v1 = 0;
- uint32_t v2 = 0;
+ struct crtc_position position1, position2;
- tg->funcs->get_position(tg, &h1, &v1);
- tg->funcs->get_position(tg, &h2, &v2);
+ tg->funcs->get_position(tg, &position1);
+ tg->funcs->get_position(tg, &position2);
- if (h1 == h2 && v1 == v2)
+ if (position1.horizontal_count == position2.horizontal_count &&
+ position1.vertical_count == position2.vertical_count)
return false;
else
return true;
@@ -1750,18 +1757,6 @@ void dce110_tg_set_overscan_color(struct timing_generator *tg,
dm_write_reg(ctx, addr, value);
}
-void dce110_tg_get_position(struct timing_generator *tg,
- struct crtc_position *position)
-{
- int32_t h_position;
- int32_t v_position;
-
- dce110_timing_generator_get_crtc_positions(tg, &h_position, &v_position);
-
- position->horizontal_count = (uint32_t)h_position;
- position->vertical_count = (uint32_t)v_position;
-}
-
void dce110_tg_program_timing(struct timing_generator *tg,
const struct dc_crtc_timing *timing,
bool use_vbios)
@@ -1895,7 +1890,7 @@ static const struct timing_generator_funcs dce110_tg_funcs = {
.enable_crtc = dce110_timing_generator_enable_crtc,
.disable_crtc = dce110_timing_generator_disable_crtc,
.is_counter_moving = dce110_timing_generator_is_counter_moving,
- .get_position = dce110_timing_generator_get_crtc_positions,
+ .get_position = dce110_timing_generator_get_position,
.get_frame_count = dce110_timing_generator_get_vblank_counter,
.get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
.set_early_control = dce110_timing_generator_set_early_control,
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
index f14a4d91cd8e..a5d63c626ada 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
@@ -151,11 +151,9 @@ void dce110_timing_generator_set_early_control(
uint32_t dce110_timing_generator_get_vblank_counter(
struct timing_generator *tg);
-/* Get current H and V position */
-void dce110_timing_generator_get_crtc_positions(
+void dce110_timing_generator_get_position(
struct timing_generator *tg,
- int32_t *h_position,
- int32_t *v_position);
+ struct crtc_position *position);
/* return true if TG counter is moving. false if TG is stopped */
bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg);
@@ -251,9 +249,6 @@ void dce110_tg_program_blank_color(struct timing_generator *tg,
void dce110_tg_set_overscan_color(struct timing_generator *tg,
const struct tg_color *overscan_color);
-void dce110_tg_get_position(struct timing_generator *tg,
- struct crtc_position *position);
-
void dce110_tg_program_timing(struct timing_generator *tg,
const struct dc_crtc_timing *timing,
bool use_vbios);
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
index c95b69446ced..759c55bb4d15 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
@@ -570,24 +570,11 @@ static void dce110_timing_generator_v_set_early_control(
dm_write_reg(tg->ctx, address, regval);
}
-static void dce110_timing_generator_v_get_crtc_positions(
- struct timing_generator *tg,
- int32_t *h_position,
- int32_t *v_position)
+static void dce110_timing_generator_get_underlay_position(struct timing_generator *tg,
+ struct crtc_position *position)
{
- uint32_t value;
-
- value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION);
-
- *h_position = get_reg_field_value(
- value,
- CRTCV_STATUS_POSITION,
- CRTC_HORZ_COUNT);
-
- *v_position = get_reg_field_value(
- value,
- CRTCV_STATUS_POSITION,
- CRTC_VERT_COUNT);
+ //Should never hit this case
+ ASSERT(false);
}
static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg)
@@ -665,7 +652,7 @@ static const struct timing_generator_funcs dce110_tg_v_funcs = {
.enable_crtc = dce110_timing_generator_v_enable_crtc,
.disable_crtc = dce110_timing_generator_v_disable_crtc,
.is_counter_moving = dce110_timing_generator_v_is_counter_moving,
- .get_position = dce110_timing_generator_v_get_crtc_positions,
+ .get_position = dce110_timing_generator_get_underlay_position,
.get_frame_count = dce110_timing_generator_v_get_vblank_counter,
.set_early_control = dce110_timing_generator_v_set_early_control,
.wait_for_state = dce110_timing_generator_v_wait_for_state,
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
index 1318df7ed47e..245356e72b36 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
@@ -180,10 +180,9 @@ uint32_t dce120_timing_generator_get_vblank_counter(
}
/* Get current H and V position */
-void dce120_timing_generator_get_crtc_positions(
+void dce120_timing_generator_get_crtc_position(
struct timing_generator *tg,
- int32_t *h_position,
- int32_t *v_position)
+ struct crtc_position *position)
{
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
uint32_t value = dm_read_reg_soc15(
@@ -191,11 +190,19 @@ void dce120_timing_generator_get_crtc_positions(
mmCRTC0_CRTC_STATUS_POSITION,
tg110->offsets.crtc);
- *h_position = get_reg_field_value(
- value, CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT);
+ position->horizontal_count = get_reg_field_value(value,
+ CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT);
- *v_position = get_reg_field_value(
- value, CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT);
+ position->vertical_count = get_reg_field_value(value,
+ CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT);
+
+ value = dm_read_reg_soc15(
+ tg->ctx,
+ mmCRTC0_CRTC_NOM_VERT_POSITION,
+ tg110->offsets.crtc);
+
+ position->nominal_vcount = get_reg_field_value(value,
+ CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM);
}
/* wait until TG is in beginning of vertical blank region */
@@ -576,6 +583,49 @@ void dce120_timing_generator_set_drr(
}
}
+/**
+ *****************************************************************************
+ * Function: dce120_timing_generator_get_position
+ *
+ * @brief
+ * Returns CRTC vertical/horizontal counters
+ *
+ * @param [out] position
+ *****************************************************************************
+ */
+void dce120_timing_generator_get_position(struct timing_generator *tg,
+ struct crtc_position *position)
+{
+ uint32_t value;
+ struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+ value = dm_read_reg_soc15(
+ tg->ctx,
+ mmCRTC0_CRTC_STATUS_POSITION,
+ tg110->offsets.crtc);
+
+ position->horizontal_count = get_reg_field_value(
+ value,
+ CRTC0_CRTC_STATUS_POSITION,
+ CRTC_HORZ_COUNT);
+
+ position->vertical_count = get_reg_field_value(
+ value,
+ CRTC0_CRTC_STATUS_POSITION,
+ CRTC_VERT_COUNT);
+
+ value = dm_read_reg_soc15(
+ tg->ctx,
+ mmCRTC0_CRTC_NOM_VERT_POSITION,
+ tg110->offsets.crtc);
+
+ position->nominal_vcount = get_reg_field_value(
+ value,
+ CRTC0_CRTC_NOM_VERT_POSITION,
+ CRTC_VERT_COUNT_NOM);
+}
+
+
void dce120_timing_generator_get_crtc_scanoutpos(
struct timing_generator *tg,
uint32_t *v_blank_start,
@@ -584,6 +634,7 @@ void dce120_timing_generator_get_crtc_scanoutpos(
uint32_t *v_position)
{
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+ struct crtc_position position;
uint32_t v_blank_start_end = dm_read_reg_soc15(
tg->ctx,
@@ -597,7 +648,11 @@ void dce120_timing_generator_get_crtc_scanoutpos(
CRTC0_CRTC_V_BLANK_START_END,
CRTC_V_BLANK_END);
- dce120_timing_generator_get_crtc_positions(tg, h_position, v_position);
+ dce120_timing_generator_get_crtc_position(
+ tg, &position);
+
+ *h_position = position.horizontal_count;
+ *v_position = position.vertical_count;
}
void dce120_timing_generator_enable_advanced_request(
@@ -1076,7 +1131,7 @@ static struct timing_generator_funcs dce120_tg_funcs = {
/* used by enable_timing_synchronization. Not need for FPGA */
.is_counter_moving = dce110_timing_generator_is_counter_moving,
/* never be called */
- .get_position = dce120_timing_generator_get_crtc_positions,
+ .get_position = dce120_timing_generator_get_crtc_position,
.get_frame_count = dce120_timing_generator_get_vblank_counter,
.get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
.set_early_control = dce120_timing_generator_set_early_control,
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
index 1198f2fbf9c7..179a6d604838 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
@@ -121,7 +121,7 @@ static const struct timing_generator_funcs dce80_tg_funcs = {
.enable_crtc = dce110_timing_generator_enable_crtc,
.disable_crtc = dce110_timing_generator_disable_crtc,
.is_counter_moving = dce110_timing_generator_is_counter_moving,
- .get_position = dce110_timing_generator_get_crtc_positions,
+ .get_position = dce110_timing_generator_get_position,
.get_frame_count = dce110_timing_generator_get_vblank_counter,
.get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
.set_early_control = dce110_timing_generator_set_early_control,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 235cfe8d1ad4..2c4a9d02b3c1 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -30,9 +30,9 @@ struct dc_bios;
/* Contains CRTC vertical/horizontal pixel counters */
struct crtc_position {
- uint32_t vertical_count;
- uint32_t horizontal_count;
- uint32_t nominal_vcount;
+ int32_t vertical_count;
+ int32_t horizontal_count;
+ int32_t nominal_vcount;
};
struct dcp_gsl_params {
@@ -105,8 +105,8 @@ struct timing_generator_funcs {
bool (*disable_crtc)(struct timing_generator *tg);
bool (*is_counter_moving)(struct timing_generator *tg);
void (*get_position)(struct timing_generator *tg,
- int32_t *h_position,
- int32_t *v_position);
+ struct crtc_position *position);
+
uint32_t (*get_frame_count)(struct timing_generator *tg);
void (*get_scanoutpos)(
struct timing_generator *tg,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
index b42e4a0ef18a..afdb8605a30f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -131,6 +131,9 @@ struct hw_sequencer_funcs {
void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes,
int vmin, int vmax);
+ void (*get_position)(struct pipe_ctx **pipe_ctx, int num_pipes,
+ struct crtc_position *position);
+
void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx,
int num_pipes, const struct dc_static_screen_events *events);