summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/dcn10
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c324
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c1
7 files changed, 313 insertions, 54 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 9ba5c624770d..7c939c0a977b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -53,6 +53,7 @@
#include "dsc.h"
#include "dce/dmub_hw_lock_mgr.h"
#include "dc_trace.h"
+#include "dce/dmub_outbox.h"
#define DC_LOGGER_INIT(logger)
@@ -1355,6 +1356,10 @@ void dcn10_init_hw(struct dc *dc)
hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
}
+ /* Enable outbox notification feature of dmub */
+ if (dc->debug.enable_dmub_aux_for_legacy_ddc)
+ dmub_enable_outbox_notification(dc);
+
/* we want to turn off all dp displays before doing detection */
if (dc->config.power_down_display_on_boot) {
uint8_t dpcd_power_state = '\0';
@@ -1457,19 +1462,26 @@ void dcn10_init_hw(struct dc *dc)
*/
void dcn10_power_down_on_boot(struct dc *dc)
{
- int i = 0;
+ struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link;
+ int edp_num;
+ int i = 0;
- edp_link = get_edp_link(dc);
- if (edp_link &&
- edp_link->link_enc->funcs->is_dig_enabled &&
- edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
- dc->hwseq->funcs.edp_backlight_control &&
- dc->hwss.power_down &&
- dc->hwss.edp_power_control) {
- dc->hwseq->funcs.edp_backlight_control(edp_link, false);
- dc->hwss.power_down(dc);
- dc->hwss.edp_power_control(edp_link, false);
+ get_edp_links(dc, edp_links, &edp_num);
+
+ if (edp_num) {
+ for (i = 0; i < edp_num; i++) {
+ edp_link = edp_links[i];
+ if (edp_link->link_enc->funcs->is_dig_enabled &&
+ edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
+ dc->hwseq->funcs.edp_backlight_control &&
+ dc->hwss.power_down &&
+ dc->hwss.edp_power_control) {
+ dc->hwseq->funcs.edp_backlight_control(edp_link, false);
+ dc->hwss.power_down(dc);
+ dc->hwss.edp_power_control(edp_link, false);
+ }
+ }
} else {
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
@@ -1851,6 +1863,230 @@ static bool wait_for_reset_trigger_to_occur(
return rc;
}
+uint64_t reduceSizeAndFraction(
+ uint64_t *numerator,
+ uint64_t *denominator,
+ bool checkUint32Bounary)
+{
+ int i;
+ bool ret = checkUint32Bounary == false;
+ uint64_t max_int32 = 0xffffffff;
+ uint64_t num, denom;
+ static const uint16_t prime_numbers[] = {
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
+ 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
+ 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
+ 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
+ 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
+ 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
+ 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,
+ 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
+ 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
+ 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
+ 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,
+ 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
+ 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
+ 941, 947, 953, 967, 971, 977, 983, 991, 997};
+ int count = ARRAY_SIZE(prime_numbers);
+
+ num = *numerator;
+ denom = *denominator;
+ for (i = 0; i < count; i++) {
+ uint32_t num_remainder, denom_remainder;
+ uint64_t num_result, denom_result;
+ if (checkUint32Bounary &&
+ num <= max_int32 && denom <= max_int32) {
+ ret = true;
+ break;
+ }
+ do {
+ num_result = div_u64_rem(num, prime_numbers[i], &num_remainder);
+ denom_result = div_u64_rem(denom, prime_numbers[i], &denom_remainder);
+ if (num_remainder == 0 && denom_remainder == 0) {
+ num = num_result;
+ denom = denom_result;
+ }
+ } while (num_remainder == 0 && denom_remainder == 0);
+ }
+ *numerator = num;
+ *denominator = denom;
+ return ret;
+}
+
+bool is_low_refresh_rate(struct pipe_ctx *pipe)
+{
+ uint32_t master_pipe_refresh_rate =
+ pipe->stream->timing.pix_clk_100hz * 100 /
+ pipe->stream->timing.h_total /
+ pipe->stream->timing.v_total;
+ return master_pipe_refresh_rate <= 30;
+}
+
+uint8_t get_clock_divider(struct pipe_ctx *pipe, bool account_low_refresh_rate)
+{
+ uint32_t clock_divider = 1;
+ uint32_t numpipes = 1;
+
+ if (account_low_refresh_rate && is_low_refresh_rate(pipe))
+ clock_divider *= 2;
+
+ if (pipe->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420)
+ clock_divider *= 2;
+
+ while (pipe->next_odm_pipe) {
+ pipe = pipe->next_odm_pipe;
+ numpipes++;
+ }
+ clock_divider *= numpipes;
+
+ return clock_divider;
+}
+
+int dcn10_align_pixel_clocks(
+ struct dc *dc,
+ int group_size,
+ struct pipe_ctx *grouped_pipes[])
+{
+ struct dc_context *dc_ctx = dc->ctx;
+ int i, master = -1, embedded = -1;
+ struct dc_crtc_timing hw_crtc_timing[MAX_PIPES] = {0};
+ uint64_t phase[MAX_PIPES];
+ uint64_t modulo[MAX_PIPES];
+ unsigned int pclk;
+
+ uint32_t embedded_pix_clk_100hz;
+ uint16_t embedded_h_total;
+ uint16_t embedded_v_total;
+ bool clamshell_closed = false;
+ uint32_t dp_ref_clk_100hz =
+ dc->res_pool->dp_clock_source->ctx->dc->clk_mgr->dprefclk_khz*10;
+
+ if (dc->config.vblank_alignment_dto_params &&
+ dc->res_pool->dp_clock_source->funcs->override_dp_pix_clk) {
+ clamshell_closed =
+ (dc->config.vblank_alignment_dto_params >> 63);
+ embedded_h_total =
+ (dc->config.vblank_alignment_dto_params >> 32) & 0x7FFF;
+ embedded_v_total =
+ (dc->config.vblank_alignment_dto_params >> 48) & 0x7FFF;
+ embedded_pix_clk_100hz =
+ dc->config.vblank_alignment_dto_params & 0xFFFFFFFF;
+
+ for (i = 0; i < group_size; i++) {
+ grouped_pipes[i]->stream_res.tg->funcs->get_hw_timing(
+ grouped_pipes[i]->stream_res.tg,
+ &hw_crtc_timing[i]);
+ dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
+ dc->res_pool->dp_clock_source,
+ grouped_pipes[i]->stream_res.tg->inst,
+ &pclk);
+ hw_crtc_timing[i].pix_clk_100hz = pclk;
+ if (dc_is_embedded_signal(
+ grouped_pipes[i]->stream->signal)) {
+ embedded = i;
+ master = i;
+ phase[i] = embedded_pix_clk_100hz*100;
+ modulo[i] = dp_ref_clk_100hz*100;
+ } else {
+
+ phase[i] = (uint64_t)embedded_pix_clk_100hz*
+ hw_crtc_timing[i].h_total*
+ hw_crtc_timing[i].v_total;
+ phase[i] = div_u64(phase[i], get_clock_divider(grouped_pipes[i], true));
+ modulo[i] = (uint64_t)dp_ref_clk_100hz*
+ embedded_h_total*
+ embedded_v_total;
+
+ if (reduceSizeAndFraction(&phase[i],
+ &modulo[i], true) == false) {
+ /*
+ * this will help to stop reporting
+ * this timing synchronizable
+ */
+ DC_SYNC_INFO("Failed to reduce DTO parameters\n");
+ grouped_pipes[i]->stream->has_non_synchronizable_pclk = true;
+ }
+ }
+ }
+
+ for (i = 0; i < group_size; i++) {
+ if (i != embedded && !grouped_pipes[i]->stream->has_non_synchronizable_pclk) {
+ dc->res_pool->dp_clock_source->funcs->override_dp_pix_clk(
+ dc->res_pool->dp_clock_source,
+ grouped_pipes[i]->stream_res.tg->inst,
+ phase[i], modulo[i]);
+ dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
+ dc->res_pool->dp_clock_source,
+ grouped_pipes[i]->stream_res.tg->inst, &pclk);
+ grouped_pipes[i]->stream->timing.pix_clk_100hz =
+ pclk*get_clock_divider(grouped_pipes[i], false);
+ if (master == -1)
+ master = i;
+ }
+ }
+
+ }
+ return master;
+}
+
+void dcn10_enable_vblanks_synchronization(
+ struct dc *dc,
+ int group_index,
+ int group_size,
+ struct pipe_ctx *grouped_pipes[])
+{
+ struct dc_context *dc_ctx = dc->ctx;
+ struct output_pixel_processor *opp;
+ struct timing_generator *tg;
+ int i, width, height, master;
+
+ for (i = 1; i < group_size; i++) {
+ opp = grouped_pipes[i]->stream_res.opp;
+ tg = grouped_pipes[i]->stream_res.tg;
+ tg->funcs->get_otg_active_size(tg, &width, &height);
+ if (opp->funcs->opp_program_dpg_dimensions)
+ opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
+ }
+
+ for (i = 0; i < group_size; i++) {
+ if (grouped_pipes[i]->stream == NULL)
+ continue;
+ grouped_pipes[i]->stream->vblank_synchronized = false;
+ grouped_pipes[i]->stream->has_non_synchronizable_pclk = false;
+ }
+
+ DC_SYNC_INFO("Aligning DP DTOs\n");
+
+ master = dcn10_align_pixel_clocks(dc, group_size, grouped_pipes);
+
+ DC_SYNC_INFO("Synchronizing VBlanks\n");
+
+ if (master >= 0) {
+ for (i = 0; i < group_size; i++) {
+ if (i != master && !grouped_pipes[i]->stream->has_non_synchronizable_pclk)
+ grouped_pipes[i]->stream_res.tg->funcs->align_vblanks(
+ grouped_pipes[master]->stream_res.tg,
+ grouped_pipes[i]->stream_res.tg,
+ grouped_pipes[master]->stream->timing.pix_clk_100hz,
+ grouped_pipes[i]->stream->timing.pix_clk_100hz,
+ get_clock_divider(grouped_pipes[master], false),
+ get_clock_divider(grouped_pipes[i], false));
+ grouped_pipes[i]->stream->vblank_synchronized = true;
+ }
+ grouped_pipes[master]->stream->vblank_synchronized = true;
+ DC_SYNC_INFO("Sync complete\n");
+ }
+
+ for (i = 1; i < group_size; i++) {
+ opp = grouped_pipes[i]->stream_res.opp;
+ tg = grouped_pipes[i]->stream_res.tg;
+ tg->funcs->get_otg_active_size(tg, &width, &height);
+ if (opp->funcs->opp_program_dpg_dimensions)
+ opp->funcs->opp_program_dpg_dimensions(opp, width, height);
+ }
+}
+
void dcn10_enable_timing_synchronization(
struct dc *dc,
int group_index,
@@ -1872,6 +2108,12 @@ void dcn10_enable_timing_synchronization(
opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
}
+ for (i = 0; i < group_size; i++) {
+ if (grouped_pipes[i]->stream == NULL)
+ continue;
+ grouped_pipes[i]->stream->vblank_synchronized = false;
+ }
+
for (i = 1; i < group_size; i++)
grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
grouped_pipes[i]->stream_res.tg,
@@ -2642,7 +2884,7 @@ static void dcn10_update_dchubp_dpp(
hws->funcs.update_plane_addr(dc, pipe_ctx);
if (is_pipe_tree_visible(pipe_ctx))
- dc->hwss.set_hubp_blank(dc, pipe_ctx, false);
+ hubp->funcs->set_blank(hubp, false);
}
void dcn10_blank_pixel_data(
@@ -3029,8 +3271,7 @@ void dcn10_optimize_bandwidth(
}
void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
- int num_pipes, unsigned int vmin, unsigned int vmax,
- unsigned int vmid, unsigned int vmid_frame_number)
+ int num_pipes, struct dc_crtc_timing_adjust adjust)
{
int i = 0;
struct drr_params params = {0};
@@ -3039,11 +3280,10 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
// Note DRR trigger events are generated regardless of whether num frames met.
unsigned int num_frames = 2;
- params.vertical_total_max = vmax;
- params.vertical_total_min = vmin;
- params.vertical_total_mid = vmid;
- params.vertical_total_mid_frame_num = vmid_frame_number;
-
+ params.vertical_total_max = adjust.v_total_max;
+ params.vertical_total_min = adjust.v_total_min;
+ params.vertical_total_mid = adjust.v_total_mid;
+ params.vertical_total_mid_frame_num = adjust.v_total_mid_frame_num;
/* TODO: If multiple pipes are to be supported, you need
* some GSL stuff. Static screen triggers may be programmed differently
* as well.
@@ -3051,7 +3291,7 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
for (i = 0; i < num_pipes; i++) {
pipe_ctx[i]->stream_res.tg->funcs->set_drr(
pipe_ctx[i]->stream_res.tg, &params);
- if (vmax != 0 && vmin != 0)
+ if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
pipe_ctx[i]->stream_res.tg,
event_triggers, num_frames);
@@ -3153,16 +3393,13 @@ void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
return;
}
-static struct pipe_ctx *get_pipe_ctx_by_hubp_inst(struct dc_state *context, int mpcc_inst)
+static struct hubp *get_hubp_by_inst(struct resource_pool *res_pool, int mpcc_inst)
{
int i;
- for (i = 0; i < MAX_PIPES; i++) {
- if (context->res_ctx.pipe_ctx[i].plane_res.hubp
- && context->res_ctx.pipe_ctx[i].plane_res.hubp->inst == mpcc_inst) {
- return &context->res_ctx.pipe_ctx[i];
- }
-
+ for (i = 0; i < res_pool->pipe_count; i++) {
+ if (res_pool->hubps[i]->inst == mpcc_inst)
+ return res_pool->hubps[i];
}
ASSERT(false);
return NULL;
@@ -3185,23 +3422,11 @@ void dcn10_wait_for_mpcc_disconnect(
for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) {
if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
- struct pipe_ctx *restore_bottom_pipe;
- struct pipe_ctx *restore_top_pipe;
- struct pipe_ctx *inst_pipe_ctx = get_pipe_ctx_by_hubp_inst(dc->current_state, mpcc_inst);
+ struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
- ASSERT(inst_pipe_ctx);
res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
- /*
- * Set top and bottom pipes NULL, as we don't want
- * to blank those pipes when disconnecting from MPCC
- */
- restore_bottom_pipe = inst_pipe_ctx->bottom_pipe;
- restore_top_pipe = inst_pipe_ctx->top_pipe;
- inst_pipe_ctx->top_pipe = inst_pipe_ctx->bottom_pipe = NULL;
- dc->hwss.set_hubp_blank(dc, inst_pipe_ctx, true);
- inst_pipe_ctx->top_pipe = restore_top_pipe;
- inst_pipe_ctx->bottom_pipe = restore_bottom_pipe;
+ hubp->funcs->set_blank(hubp, true);
}
}
@@ -3755,9 +3980,18 @@ void dcn10_get_clock(struct dc *dc,
}
-void dcn10_set_hubp_blank(const struct dc *dc,
- struct pipe_ctx *pipe_ctx,
- bool blank_enable)
+void dcn10_get_dcc_en_bits(struct dc *dc, int *dcc_en_bits)
{
- pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, blank_enable);
+ struct resource_pool *pool = dc->res_pool;
+ int i;
+
+ for (i = 0; i < pool->pipe_count; i++) {
+ struct hubp *hubp = pool->hubps[i];
+ struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
+
+ hubp->funcs->hubp_read_state(hubp);
+
+ if (!s->blank_en)
+ dcc_en_bits[i] = s->dcc_en ? 1 : 0;
+ }
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
index 89e6dfb63da0..37bec421fde8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
@@ -1,5 +1,5 @@
/*
-* Copyright 2016 Advanced Micro Devices, Inc.
+* Copyright 2016-2020 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -123,6 +123,11 @@ void dcn10_enable_timing_synchronization(
int group_index,
int group_size,
struct pipe_ctx *grouped_pipes[]);
+void dcn10_enable_vblanks_synchronization(
+ struct dc *dc,
+ int group_index,
+ int group_size,
+ struct pipe_ctx *grouped_pipes[]);
void dcn10_enable_per_frame_crtc_position_reset(
struct dc *dc,
int group_size,
@@ -140,8 +145,7 @@ bool dcn10_dummy_display_power_gating(
struct dc_bios *dcb,
enum pipe_gating_control power_gating);
void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
- int num_pipes, unsigned int vmin, unsigned int vmax,
- unsigned int vmid, unsigned int vmid_frame_number);
+ int num_pipes, struct dc_crtc_timing_adjust adjust);
void dcn10_get_position(struct pipe_ctx **pipe_ctx,
int num_pipes,
struct crtc_position *position);
@@ -204,8 +208,7 @@ void dcn10_wait_for_pending_cleared(struct dc *dc,
struct dc_state *context);
void dcn10_set_hdr_multiplier(struct pipe_ctx *pipe_ctx);
void dcn10_verify_allow_pstate_change_high(struct dc *dc);
-void dcn10_set_hubp_blank(const struct dc *dc,
- struct pipe_ctx *pipe_ctx,
- bool blank_enable);
+
+void dcn10_get_dcc_en_bits(struct dc *dc, int *dcc_en_bits);
#endif /* __DC_HWSS_DCN10_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
index 2f1b802e66a1..d532c78ee764 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Advanced Micro Devices, Inc.
+ * Copyright 2016-2020 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -79,7 +79,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
.set_backlight_level = dce110_set_backlight_level,
.set_abm_immediate_disable = dce110_set_abm_immediate_disable,
.set_pipe = dce110_set_pipe,
- .set_hubp_blank = dcn10_set_hubp_blank,
+ .get_dcc_en_bits = dcn10_get_dcc_en_bits,
};
static const struct hwseq_private_funcs dcn10_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
index 6138f4887de7..677663cc7bff 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
@@ -132,6 +132,22 @@ void optc1_setup_vertical_interrupt2(
}
/**
+ * Vupdate keepout can be set to a window to block the update lock for that pipe from changing.
+ * Start offset begins with vstartup and goes for x number of clocks,
+ * end offset starts from end of vupdate to x number of clocks.
+ */
+void optc1_set_vupdate_keepout(struct timing_generator *optc,
+ struct vupdate_keepout_params *params)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ REG_SET_3(OTG_VUPDATE_KEEPOUT, 0,
+ MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, params->start_offset,
+ MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, params->end_offset,
+ OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, params->enable);
+}
+
+/**
* program_timing_generator used by mode timing set
* Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition.
* Including SYNC. Call BIOS command table to program Timings.
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
index b222c67973d4..cabfe83fd634 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
@@ -194,6 +194,9 @@ struct dcn_optc_registers {
SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\
SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\
SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\
+ SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \
+ SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \
+ SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \
SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\
SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\
SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\
@@ -212,6 +215,7 @@ struct dcn_optc_registers {
SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\
SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\
SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\
+ SF(OTG0_OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, mask_sh),\
SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\
SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\
SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\
@@ -352,6 +356,7 @@ struct dcn_optc_registers {
type OTG_START_POINT_CNTL;\
type OTG_DISABLE_POINT_CNTL;\
type OTG_FIELD_NUMBER_CNTL;\
+ type OTG_CURRENT_MASTER_EN_STATE;\
type OTG_STEREO_EN;\
type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\
type OTG_STEREO_SYNC_OUTPUT_POLARITY;\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
index 90e912fef2b3..f962b905e79e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -1420,6 +1420,8 @@ static bool dcn10_resource_construct(
dc->caps.max_cursor_size = 256;
dc->caps.min_horizontal_blanking_period = 80;
dc->caps.max_slave_planes = 1;
+ dc->caps.max_slave_yuv_planes = 1;
+ dc->caps.max_slave_rgb_planes = 0;
dc->caps.is_apu = true;
dc->caps.post_blend_color_processing = false;
dc->caps.extended_aux_timeout_support = false;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
index 73ac78b16bd4..f1a08a7736ac 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
@@ -738,7 +738,6 @@ void enc1_stream_encoder_update_dp_info_packets(
REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid);
REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid);
-
/* This bit is the master enable bit.
* When enabling secondary stream engine,
* this master bit must also be set.