aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/core
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c354
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_debug.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c302
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c28
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c840
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c101
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c193
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_sink.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c125
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_surface.c34
10 files changed, 1374 insertions, 621 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 32f31bf91915..6c797fac189d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -58,21 +58,21 @@
#include "hubp.h"
#include "dc_link_dp.h"
+#include "dc_dmub_srv.h"
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
#include "dsc.h"
-#endif
-#ifdef CONFIG_DRM_AMD_DC_DCN2_0
#include "vm_helper.h"
-#endif
#include "dce/dce_i2c.h"
+#define CTX \
+ dc->ctx
+
#define DC_LOGGER \
dc->ctx->logger
-const static char DC_BUILD_ID[] = "production-build";
+static const char DC_BUILD_ID[] = "production-build";
/**
* DOC: Overview
@@ -287,7 +287,6 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe->stream == stream && pipe->stream_res.tg) {
- pipe->stream->adjust = *adjust;
dc->hwss.set_drr(&pipe,
1,
adjust->v_total_min,
@@ -511,10 +510,10 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream)
return ret;
}
-void dc_stream_set_static_screen_events(struct dc *dc,
+void dc_stream_set_static_screen_params(struct dc *dc,
struct dc_stream_state **streams,
int num_streams,
- const struct dc_static_screen_events *events)
+ const struct dc_static_screen_params *params)
{
int i = 0;
int j = 0;
@@ -533,10 +532,10 @@ void dc_stream_set_static_screen_events(struct dc *dc,
}
}
- dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events);
+ dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, params);
}
-static void destruct(struct dc *dc)
+static void dc_destruct(struct dc *dc)
{
if (dc->current_state) {
dc_release_state(dc->current_state);
@@ -569,7 +568,7 @@ static void destruct(struct dc *dc)
kfree(dc->bw_dceip);
dc->bw_dceip = NULL;
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
+#ifdef CONFIG_DRM_AMD_DC_DCN
kfree(dc->dcn_soc);
dc->dcn_soc = NULL;
@@ -577,28 +576,58 @@ static void destruct(struct dc *dc)
dc->dcn_ip = NULL;
#endif
-#ifdef CONFIG_DRM_AMD_DC_DCN2_0
kfree(dc->vm_helper);
dc->vm_helper = NULL;
-#endif
}
-static bool construct(struct dc *dc,
+static bool dc_construct_ctx(struct dc *dc,
+ const struct dc_init_data *init_params)
+{
+ struct dc_context *dc_ctx;
+ enum dce_version dc_version = DCE_VERSION_UNKNOWN;
+
+ dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL);
+ if (!dc_ctx)
+ return false;
+
+ dc_ctx->cgs_device = init_params->cgs_device;
+ dc_ctx->driver_context = init_params->driver;
+ dc_ctx->dc = dc;
+ dc_ctx->asic_id = init_params->asic_id;
+ dc_ctx->dc_sink_id_count = 0;
+ dc_ctx->dc_stream_id_count = 0;
+ dc_ctx->dce_environment = init_params->dce_environment;
+
+ /* Create logger */
+
+ dc_version = resource_parse_asic_id(init_params->asic_id);
+ dc_ctx->dce_version = dc_version;
+
+ dc_ctx->perf_trace = dc_perf_trace_create();
+ if (!dc_ctx->perf_trace) {
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+
+ dc->ctx = dc_ctx;
+
+ return true;
+}
+
+static bool dc_construct(struct dc *dc,
const struct dc_init_data *init_params)
{
struct dc_context *dc_ctx;
struct bw_calcs_dceip *dc_dceip;
struct bw_calcs_vbios *dc_vbios;
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
+#ifdef CONFIG_DRM_AMD_DC_DCN
struct dcn_soc_bounding_box *dcn_soc;
struct dcn_ip_params *dcn_ip;
#endif
- enum dce_version dc_version = DCE_VERSION_UNKNOWN;
dc->config = init_params->flags;
-#ifdef CONFIG_DRM_AMD_DC_DCN2_0
// Allocate memory for the vm_helper
dc->vm_helper = kzalloc(sizeof(struct vm_helper), GFP_KERNEL);
if (!dc->vm_helper) {
@@ -606,7 +635,6 @@ static bool construct(struct dc *dc,
goto fail;
}
-#endif
memcpy(&dc->bb_overrides, &init_params->bb_overrides, sizeof(dc->bb_overrides));
dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL);
@@ -624,7 +652,7 @@ static bool construct(struct dc *dc,
}
dc->bw_vbios = dc_vbios;
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
+#ifdef CONFIG_DRM_AMD_DC_DCN
dcn_soc = kzalloc(sizeof(*dcn_soc), GFP_KERNEL);
if (!dcn_soc) {
dm_error("%s: failed to create dcn_soc\n", __func__);
@@ -640,31 +668,15 @@ static bool construct(struct dc *dc,
}
dc->dcn_ip = dcn_ip;
-#ifdef CONFIG_DRM_AMD_DC_DCN2_0
dc->soc_bounding_box = init_params->soc_bounding_box;
#endif
-#endif
- dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL);
- if (!dc_ctx) {
+ if (!dc_construct_ctx(dc, init_params)) {
dm_error("%s: failed to create ctx\n", __func__);
goto fail;
}
- dc_ctx->cgs_device = init_params->cgs_device;
- dc_ctx->driver_context = init_params->driver;
- dc_ctx->dc = dc;
- dc_ctx->asic_id = init_params->asic_id;
- dc_ctx->dc_sink_id_count = 0;
- dc_ctx->dc_stream_id_count = 0;
- dc->ctx = dc_ctx;
-
- /* Create logger */
-
- dc_ctx->dce_environment = init_params->dce_environment;
-
- dc_version = resource_parse_asic_id(init_params->asic_id);
- dc_ctx->dce_version = dc_version;
+ dc_ctx = dc->ctx;
/* Resource should construct all asic specific resources.
* This should be the only place where we need to parse the asic id
@@ -679,7 +691,7 @@ static bool construct(struct dc *dc,
bp_init_data.bios = init_params->asic_id.atombios_base_address;
dc_ctx->dc_bios = dal_bios_parser_create(
- &bp_init_data, dc_version);
+ &bp_init_data, dc_ctx->dce_version);
if (!dc_ctx->dc_bios) {
ASSERT_CRITICAL(false);
@@ -687,17 +699,13 @@ static bool construct(struct dc *dc,
}
dc_ctx->created_bios = true;
- }
-
- dc_ctx->perf_trace = dc_perf_trace_create();
- if (!dc_ctx->perf_trace) {
- ASSERT_CRITICAL(false);
- goto fail;
}
+
+
/* Create GPIO service */
dc_ctx->gpio_service = dal_gpio_service_create(
- dc_version,
+ dc_ctx->dce_version,
dc_ctx->dce_environment,
dc_ctx);
@@ -706,7 +714,7 @@ static bool construct(struct dc *dc,
goto fail;
}
- dc->res_pool = dc_create_resource_pool(dc, init_params, dc_version);
+ dc->res_pool = dc_create_resource_pool(dc, init_params, dc_ctx->dce_version);
if (!dc->res_pool)
goto fail;
@@ -714,10 +722,8 @@ static bool construct(struct dc *dc,
if (!dc->clk_mgr)
goto fail;
-#ifdef CONFIG_DRM_AMD_DC_DCN2_1
if (dc->res_pool->funcs->update_bw_bounding_box)
dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
-#endif
/* Creation of current_state must occur after dc->dml
* is initialized in dc_create_resource_pool because
@@ -739,12 +745,9 @@ static bool construct(struct dc *dc,
return true;
fail:
-
- destruct(dc);
return false;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
static bool disable_all_writeback_pipes_for_stream(
const struct dc *dc,
struct dc_stream_state *stream,
@@ -757,7 +760,6 @@ static bool disable_all_writeback_pipes_for_stream(
return true;
}
-#endif
static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
{
@@ -783,16 +785,12 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
}
if (should_disable && old_stream) {
dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
-#endif
if (dc->hwss.apply_ctx_for_surface)
dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (dc->hwss.program_front_end_for_ctx)
dc->hwss.program_front_end_for_ctx(dc, dangling_context);
-#endif
}
current_ctx = dc->current_state;
@@ -800,6 +798,33 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
dc_release_state(current_ctx);
}
+static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
+{
+ int i;
+ int count = 0;
+ struct pipe_ctx *pipe;
+ PERF_TRACE();
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (!pipe->plane_state)
+ continue;
+
+ /* Timeout 100 ms */
+ while (count < 100000) {
+ /* Must set to false to start with, due to OR in update function */
+ pipe->plane_state->status.is_flip_pending = false;
+ dc->hwss.update_pending_status(pipe);
+ if (!pipe->plane_state->status.is_flip_pending)
+ break;
+ udelay(1);
+ count++;
+ }
+ ASSERT(!pipe->plane_state->status.is_flip_pending);
+ }
+ PERF_TRACE();
+}
+
/*******************************************************************************
* Public functions
******************************************************************************/
@@ -812,26 +837,38 @@ struct dc *dc_create(const struct dc_init_data *init_params)
if (NULL == dc)
goto alloc_fail;
- if (false == construct(dc, init_params))
- goto construct_fail;
+ if (init_params->dce_environment == DCE_ENV_VIRTUAL_HW) {
+ if (false == dc_construct_ctx(dc, init_params)) {
+ dc_destruct(dc);
+ goto construct_fail;
+ }
+ } else {
+ if (false == dc_construct(dc, init_params)) {
+ dc_destruct(dc);
+ goto construct_fail;
+ }
+
+ full_pipe_count = dc->res_pool->pipe_count;
+ if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE)
+ full_pipe_count--;
+ dc->caps.max_streams = min(
+ full_pipe_count,
+ dc->res_pool->stream_enc_count);
- full_pipe_count = dc->res_pool->pipe_count;
- if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE)
- full_pipe_count--;
- dc->caps.max_streams = min(
- full_pipe_count,
- dc->res_pool->stream_enc_count);
+ dc->optimize_seamless_boot_streams = 0;
+ dc->caps.max_links = dc->link_count;
+ dc->caps.max_audios = dc->res_pool->audio_count;
+ dc->caps.linear_pitch_alignment = 64;
- dc->caps.max_links = dc->link_count;
- dc->caps.max_audios = dc->res_pool->audio_count;
- dc->caps.linear_pitch_alignment = 64;
+ dc->caps.max_dp_protocol_version = DP_VERSION_1_4;
+
+ if (dc->res_pool->dmcu != NULL)
+ dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version;
+ }
/* Populate versioning information */
dc->versions.dc_ver = DC_VER;
- if (dc->res_pool->dmcu != NULL)
- dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version;
-
dc->build_id = DC_BUILD_ID;
DC_LOG_DC("Display Core initialized\n");
@@ -849,7 +886,8 @@ alloc_fail:
void dc_hardware_init(struct dc *dc)
{
- dc->hwss.init_hw(dc);
+ if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW)
+ dc->hwss.init_hw(dc);
}
void dc_init_callbacks(struct dc *dc,
@@ -869,7 +907,7 @@ void dc_deinit_callbacks(struct dc *dc)
void dc_destroy(struct dc **dc)
{
- destruct(*dc);
+ dc_destruct(*dc);
kfree(*dc);
*dc = NULL;
}
@@ -1163,10 +1201,10 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
for (i = 0; i < context->stream_count; i++) {
if (context->streams[i]->apply_seamless_boot_optimization)
- dc->optimize_seamless_boot = true;
+ dc->optimize_seamless_boot_streams++;
}
- if (!dc->optimize_seamless_boot)
+ if (dc->optimize_seamless_boot_streams == 0)
dc->hwss.prepare_bandwidth(dc, context);
/* re-program planes for existing stream, in case we need to
@@ -1182,10 +1220,6 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
context->stream_status[i].plane_count,
context); /* use new pipe config in new context */
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
- if (dc->hwss.program_front_end_for_ctx)
- dc->hwss.program_front_end_for_ctx(dc, context);
-#endif
/* Program hardware */
for (i = 0; i < dc->res_pool->pipe_count; i++) {
@@ -1204,10 +1238,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
}
/* Program all planes within new context*/
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (dc->hwss.program_front_end_for_ctx)
dc->hwss.program_front_end_for_ctx(dc, context);
-#endif
for (i = 0; i < context->stream_count; i++) {
const struct dc_link *link = context->streams[i]->link;
@@ -1245,6 +1277,13 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc_enable_stereo(dc, context, dc_streams, context->stream_count);
+ if (dc->optimize_seamless_boot_streams == 0) {
+ /* Must wait for no flips to be pending before doing optimize bw */
+ wait_for_no_pipes_pending(dc, context);
+ /* pplib is notified if disp_num changed */
+ dc->hwss.optimize_bandwidth(dc, context);
+ }
+
for (i = 0; i < context->stream_count; i++)
context->streams[i]->mode_changed = false;
@@ -1279,12 +1318,18 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context)
return (result == DC_OK);
}
+bool dc_is_hw_initialized(struct dc *dc)
+{
+ struct dc_bios *dcb = dc->ctx->dc_bios;
+ return dcb->funcs->is_accelerated_mode(dcb);
+}
+
bool dc_post_update_surfaces_to_stream(struct dc *dc)
{
int i;
struct dc_state *context = dc->current_state;
- if (!dc->optimized_required || dc->optimize_seamless_boot)
+ if (!dc->optimized_required || dc->optimize_seamless_boot_streams > 0)
return true;
post_surface_trace(dc);
@@ -1313,7 +1358,7 @@ struct dc_state *dc_create_state(struct dc *dc)
* initialize and obtain IP and SOC the base DML instance from DC is
* initially copied into every context
*/
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
+#ifdef CONFIG_DRM_AMD_DC_DCN
memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
#endif
@@ -1486,11 +1531,6 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
elevate_update_type(&update_type, UPDATE_TYPE_MED);
}
- if (u->plane_info->sdr_white_level != u->surface->sdr_white_level) {
- update_flags->bits.sdr_white_level = 1;
- elevate_update_type(&update_type, UPDATE_TYPE_MED);
- }
-
if (u->plane_info->dcc.enable != u->surface->dcc.enable
|| u->plane_info->dcc.independent_64b_blks != u->surface->dcc.independent_64b_blks
|| u->plane_info->dcc.meta_pitch != u->surface->dcc.meta_pitch) {
@@ -1508,7 +1548,6 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
}
if (u->plane_info->plane_size.surface_pitch != u->surface->plane_size.surface_pitch
- || u->plane_info->plane_size.surface_pitch != u->surface->plane_size.surface_pitch
|| u->plane_info->plane_size.chroma_pitch != u->surface->plane_size.chroma_pitch) {
update_flags->bits.plane_size_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_MED);
@@ -1547,7 +1586,10 @@ static enum surface_update_type get_scaling_info_update_type(
if (u->scaling_info->clip_rect.width != u->surface->clip_rect.width
|| u->scaling_info->clip_rect.height != u->surface->clip_rect.height
|| u->scaling_info->dst_rect.width != u->surface->dst_rect.width
- || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) {
+ || u->scaling_info->dst_rect.height != u->surface->dst_rect.height
+ || u->scaling_info->scaling_quality.integer_scaling !=
+ u->surface->scaling_quality.integer_scaling
+ ) {
update_flags->bits.scaling_change = 1;
if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width
@@ -1563,7 +1605,7 @@ static enum surface_update_type get_scaling_info_update_type(
update_flags->bits.scaling_change = 1;
if (u->scaling_info->src_rect.width > u->surface->src_rect.width
- && u->scaling_info->src_rect.height > u->surface->src_rect.height)
+ || u->scaling_info->src_rect.height > u->surface->src_rect.height)
/* Making src rect bigger requires a bandwidth change */
update_flags->bits.clock_change = 1;
}
@@ -1577,11 +1619,11 @@ static enum surface_update_type get_scaling_info_update_type(
update_flags->bits.position_change = 1;
if (update_flags->bits.clock_change
- || update_flags->bits.bandwidth_change)
+ || update_flags->bits.bandwidth_change
+ || update_flags->bits.scaling_change)
return UPDATE_TYPE_FULL;
- if (update_flags->bits.scaling_change
- || update_flags->bits.position_change)
+ if (update_flags->bits.position_change)
return UPDATE_TYPE_MED;
return UPDATE_TYPE_FAST;
@@ -1635,6 +1677,12 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
update_flags->bits.gamma_change = 1;
}
+ if (u->hdr_mult.value)
+ if (u->hdr_mult.value != u->surface->hdr_mult.value) {
+ update_flags->bits.hdr_mult = 1;
+ elevate_update_type(&overall_type, UPDATE_TYPE_MED);
+ }
+
if (update_flags->bits.in_transfer_func_change) {
type = UPDATE_TYPE_MED;
elevate_update_type(&overall_type, type);
@@ -1668,7 +1716,8 @@ static enum surface_update_type check_update_surfaces_for_stream(
union stream_update_flags *su_flags = &stream_update->stream->update_flags;
if ((stream_update->src.height != 0 && stream_update->src.width != 0) ||
- (stream_update->dst.height != 0 && stream_update->dst.width != 0))
+ (stream_update->dst.height != 0 && stream_update->dst.width != 0) ||
+ stream_update->integer_scaling_update)
su_flags->bits.scaling = 1;
if (stream_update->out_transfer_func)
@@ -1683,15 +1732,16 @@ static enum surface_update_type check_update_surfaces_for_stream(
if (stream_update->gamut_remap)
su_flags->bits.gamut_remap = 1;
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (stream_update->wb_update)
su_flags->bits.wb_update = 1;
-#endif
if (su_flags->raw != 0)
overall_type = UPDATE_TYPE_FULL;
if (stream_update->output_csc_transform || stream_update->output_color_space)
su_flags->bits.out_csc = 1;
+
+ if (stream_update->dsc_config)
+ overall_type = UPDATE_TYPE_FULL;
}
for (i = 0 ; i < surface_count; i++) {
@@ -1817,8 +1867,6 @@ static void copy_surface_update_to_plane(
srf_update->plane_info->global_alpha_value;
surface->dcc =
srf_update->plane_info->dcc;
- surface->sdr_white_level =
- srf_update->plane_info->sdr_white_level;
surface->layer_index =
srf_update->plane_info->layer_index;
}
@@ -1851,7 +1899,6 @@ static void copy_surface_update_to_plane(
sizeof(struct dc_transfer_func_distributed_points));
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (srf_update->func_shaper &&
(surface->in_shaper_func !=
srf_update->func_shaper))
@@ -1864,13 +1911,16 @@ static void copy_surface_update_to_plane(
memcpy(surface->lut3d_func, srf_update->lut3d_func,
sizeof(*surface->lut3d_func));
+ if (srf_update->hdr_mult.value)
+ surface->hdr_mult =
+ srf_update->hdr_mult;
+
if (srf_update->blend_tf &&
(surface->blend_tf !=
srf_update->blend_tf))
memcpy(surface->blend_tf, srf_update->blend_tf,
sizeof(*surface->blend_tf));
-#endif
if (srf_update->input_csc_color_matrix)
surface->input_csc_color_matrix =
*srf_update->input_csc_color_matrix;
@@ -1883,8 +1933,10 @@ static void copy_surface_update_to_plane(
static void copy_stream_update_to_stream(struct dc *dc,
struct dc_state *context,
struct dc_stream_state *stream,
- const struct dc_stream_update *update)
+ struct dc_stream_update *update)
{
+ struct dc_context *dc_ctx = dc->ctx;
+
if (update == NULL || stream == NULL)
return;
@@ -1945,7 +1997,6 @@ static void copy_stream_update_to_stream(struct dc *dc,
if (update->dither_option)
stream->dither_option = *update->dither_option;
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
/* update current stream with writeback info */
if (update->wb_update) {
int i;
@@ -1956,23 +2007,32 @@ static void copy_stream_update_to_stream(struct dc *dc,
stream->writeback_info[i] =
update->wb_update->writeback_info[i];
}
-#endif
-#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
if (update->dsc_config) {
struct dc_dsc_config old_dsc_cfg = stream->timing.dsc_cfg;
uint32_t old_dsc_enabled = stream->timing.flags.DSC;
uint32_t enable_dsc = (update->dsc_config->num_slices_h != 0 &&
update->dsc_config->num_slices_v != 0);
- stream->timing.dsc_cfg = *update->dsc_config;
- stream->timing.flags.DSC = enable_dsc;
- if (!dc->res_pool->funcs->validate_bandwidth(dc, context,
- true)) {
- stream->timing.dsc_cfg = old_dsc_cfg;
- stream->timing.flags.DSC = old_dsc_enabled;
+ /* Use temporarry context for validating new DSC config */
+ struct dc_state *dsc_validate_context = dc_create_state(dc);
+
+ if (dsc_validate_context) {
+ dc_resource_state_copy_construct(dc->current_state, dsc_validate_context);
+
+ stream->timing.dsc_cfg = *update->dsc_config;
+ stream->timing.flags.DSC = enable_dsc;
+ if (!dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true)) {
+ stream->timing.dsc_cfg = old_dsc_cfg;
+ stream->timing.flags.DSC = old_dsc_enabled;
+ update->dsc_config = NULL;
+ }
+
+ dc_release_state(dsc_validate_context);
+ } else {
+ DC_ERROR("Failed to allocate new validate context for DSC change\n");
+ update->dsc_config = NULL;
}
}
-#endif
}
static void commit_planes_do_stream_update(struct dc *dc,
@@ -1992,11 +2052,11 @@ static void commit_planes_do_stream_update(struct dc *dc,
if (stream_update->periodic_interrupt0 &&
dc->hwss.setup_periodic_interrupt)
- dc->hwss.setup_periodic_interrupt(pipe_ctx, VLINE0);
+ dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE0);
if (stream_update->periodic_interrupt1 &&
dc->hwss.setup_periodic_interrupt)
- dc->hwss.setup_periodic_interrupt(pipe_ctx, VLINE1);
+ dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE1);
if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
stream_update->vrr_infopacket ||
@@ -2006,6 +2066,12 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc->hwss.update_info_frame(pipe_ctx);
}
+ if (stream_update->hdr_static_metadata &&
+ stream->use_dynamic_meta &&
+ dc->hwss.set_dmdata_attributes &&
+ pipe_ctx->stream->dmdata_address.quad_part != 0)
+ dc->hwss.set_dmdata_attributes(pipe_ctx);
+
if (stream_update->gamut_remap)
dc_stream_set_gamut_remap(dc, stream);
@@ -2013,31 +2079,25 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc_stream_program_csc_matrix(dc, stream);
if (stream_update->dither_option) {
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
-#endif
resource_build_bit_depth_reduction_params(pipe_ctx->stream,
&pipe_ctx->stream->bit_depth_params);
pipe_ctx->stream_res.opp->funcs->opp_program_fmt(pipe_ctx->stream_res.opp,
&stream->bit_depth_params,
&stream->clamping);
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
while (odm_pipe) {
odm_pipe->stream_res.opp->funcs->opp_program_fmt(odm_pipe->stream_res.opp,
&stream->bit_depth_params,
&stream->clamping);
odm_pipe = odm_pipe->next_odm_pipe;
}
-#endif
}
-#if defined(CONFIG_DRM_AMD_DC_DSC_SUPPORT)
if (stream_update->dsc_config && dc->hwss.pipe_control_lock_global) {
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, true);
dp_update_dsc_config(pipe_ctx);
dc->hwss.pipe_control_lock_global(dc, pipe_ctx, false);
}
-#endif
/* Full fe update*/
if (update_type == UPDATE_TYPE_FAST)
continue;
@@ -2053,7 +2113,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc->hwss.optimize_bandwidth(dc, dc->current_state);
} else {
- if (!dc->optimize_seamless_boot)
+ if (dc->optimize_seamless_boot_streams == 0)
dc->hwss.prepare_bandwidth(dc, dc->current_state);
core_link_enable_stream(dc->current_state, pipe_ctx);
@@ -2094,7 +2154,7 @@ static void commit_planes_for_stream(struct dc *dc,
int i, j;
struct pipe_ctx *top_pipe_to_program = NULL;
- if (dc->optimize_seamless_boot && surface_count > 0) {
+ if (dc->optimize_seamless_boot_streams > 0 && surface_count > 0) {
/* Optimize seamless boot flag keeps clocks and watermarks high until
* first flip. After first flip, optimization is required to lower
* bandwidth. Important to note that it is expected UEFI will
@@ -2103,12 +2163,14 @@ static void commit_planes_for_stream(struct dc *dc,
*/
if (stream->apply_seamless_boot_optimization) {
stream->apply_seamless_boot_optimization = false;
- dc->optimize_seamless_boot = false;
- dc->optimized_required = true;
+ dc->optimize_seamless_boot_streams--;
+
+ if (dc->optimize_seamless_boot_streams == 0)
+ dc->optimized_required = true;
}
}
- if (update_type == UPDATE_TYPE_FULL && !dc->optimize_seamless_boot) {
+ if (update_type == UPDATE_TYPE_FULL && dc->optimize_seamless_boot_streams == 0) {
dc->hwss.prepare_bandwidth(dc, context);
context_clock_trace(dc, context);
}
@@ -2124,15 +2186,12 @@ static void commit_planes_for_stream(struct dc *dc,
*/
if (dc->hwss.apply_ctx_for_surface)
dc->hwss.apply_ctx_for_surface(dc, stream, 0, context);
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (dc->hwss.program_front_end_for_ctx)
dc->hwss.program_front_end_for_ctx(dc, context);
-#endif
return;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *plane_state = srf_updates[i].surface;
@@ -2154,7 +2213,6 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
}
-#endif
// Update Type FULL, Surface updates
for (j = 0; j < dc->res_pool->pipe_count; j++) {
@@ -2175,7 +2233,6 @@ static void commit_planes_for_stream(struct dc *dc,
if (update_type == UPDATE_TYPE_FAST)
continue;
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
if (dc->hwss.program_triplebuffer != NULL &&
@@ -2184,7 +2241,6 @@ static void commit_planes_for_stream(struct dc *dc,
dc->hwss.program_triplebuffer(
dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
}
-#endif
stream_status =
stream_get_status(context, pipe_ctx->stream);
@@ -2193,10 +2249,24 @@ static void commit_planes_for_stream(struct dc *dc,
dc, pipe_ctx->stream, stream_status->plane_count, context);
}
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
- if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST)
+ if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST) {
dc->hwss.program_front_end_for_ctx(dc, context);
+#ifdef CONFIG_DRM_AMD_DC_DCN
+ if (dc->debug.validate_dml_output) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx cur_pipe = context->res_ctx.pipe_ctx[i];
+ if (cur_pipe.stream == NULL)
+ continue;
+
+ cur_pipe.plane_res.hubp->funcs->validate_dml_output(
+ cur_pipe.plane_res.hubp, dc->ctx,
+ &context->res_ctx.pipe_ctx[i].rq_regs,
+ &context->res_ctx.pipe_ctx[i].dlg_regs,
+ &context->res_ctx.pipe_ctx[i].ttu_regs);
+ }
+ }
#endif
+ }
// Update Type FAST, Surface updates
if (update_type == UPDATE_TYPE_FAST) {
@@ -2206,7 +2276,6 @@ static void commit_planes_for_stream(struct dc *dc,
*/
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (dc->hwss.set_flip_control_gsl)
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *plane_state = srf_updates[i].surface;
@@ -2225,7 +2294,6 @@ static void commit_planes_for_stream(struct dc *dc,
plane_state->flip_immediate);
}
}
-#endif
/* Perform requested Updates */
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *plane_state = srf_updates[i].surface;
@@ -2238,7 +2306,6 @@ static void commit_planes_for_stream(struct dc *dc,
if (pipe_ctx->plane_state != plane_state)
continue;
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
/*program triple buffer after lock based on flip type*/
if (dc->hwss.program_triplebuffer != NULL &&
!dc->debug.disable_tri_buf) {
@@ -2246,7 +2313,6 @@ static void commit_planes_for_stream(struct dc *dc,
dc->hwss.program_triplebuffer(
dc, pipe_ctx, plane_state->triplebuffer_flips);
}
-#endif
if (srf_updates[i].flip_addr)
dc->hwss.update_plane_addr(dc, pipe_ctx);
}
@@ -2407,14 +2473,15 @@ void dc_set_power_state(
case DC_ACPI_CM_POWER_STATE_D0:
dc_resource_state_construct(dc, dc->current_state);
+ if (dc->ctx->dmub_srv)
+ dc_dmub_srv_wait_phy_init(dc->ctx->dmub_srv);
+
dc->hwss.init_hw(dc);
-#ifdef CONFIG_DRM_AMD_DC_DCN2_0
if (dc->hwss.init_sys_ctx != NULL &&
dc->vm_pa_config.valid) {
dc->hwss.init_sys_ctx(dc->hwseq, dc, &dc->vm_pa_config);
}
-#endif
break;
default:
@@ -2494,6 +2561,17 @@ bool dc_submit_i2c(
cmd);
}
+bool dc_submit_i2c_oem(
+ struct dc *dc,
+ struct i2c_command *cmd)
+{
+ struct ddc_service *ddc = dc->res_pool->oem_device;
+ return dce_i2c_submit_command(
+ dc->res_pool,
+ ddc->ddc_pin,
+ cmd);
+}
+
static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink)
{
if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
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 b9227d5de3a3..502ed3c7959d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
@@ -33,7 +33,6 @@
#include "core_status.h"
#include "core_types.h"
-#include "hw_sequencer.h"
#include "resource.h"
@@ -310,14 +309,13 @@ void context_timing_trace(
struct resource_context *res_ctx)
{
int i;
- struct dc *core_dc = dc;
int h_pos[MAX_PIPES] = {0}, v_pos[MAX_PIPES] = {0};
struct crtc_position position;
- unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index;
+ unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
DC_LOGGER_INIT(dc->ctx->logger);
- for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
/* get_position() returns CRTC vertical/horizontal counter
* hence not applicable for underlay pipe
@@ -329,7 +327,7 @@ void context_timing_trace(
h_pos[i] = position.horizontal_count;
v_pos[i] = position.vertical_count;
}
- for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
if (pipe_ctx->stream == NULL || pipe_ctx->pipe_idx == underlay_idx)
@@ -347,7 +345,7 @@ void context_clock_trace(
struct dc *dc,
struct dc_state *context)
{
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
DC_LOGGER_INIT(dc->ctx->logger);
CLOCK_TRACE("Current: dispclk_khz:%d max_dppclk_khz:%d dcfclk_khz:%d\n"
"dcfclk_deep_sleep_khz:%d fclk_khz:%d socclk_khz:%d\n",
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 4619f94f0ac7..260c0b62d37d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -45,6 +45,7 @@
#include "dpcd_defs.h"
#include "dmcu.h"
#include "hw/clk_mgr.h"
+#include "../dce/dmub_psr.h"
#define DC_LOGGER_INIT(logger)
@@ -74,7 +75,7 @@ enum {
/*******************************************************************************
* Private functions
******************************************************************************/
-static void destruct(struct dc_link *link)
+static void dc_link_destruct(struct dc_link *link)
{
int i;
@@ -1244,7 +1245,7 @@ static enum transmitter translate_encoder_to_transmitter(
}
}
-static bool construct(
+static bool dc_link_construct(
struct dc_link *link,
const struct link_init_data *init_params)
{
@@ -1446,7 +1447,7 @@ struct dc_link *link_create(const struct link_init_data *init_params)
if (NULL == link)
goto alloc_fail;
- if (false == construct(link, init_params))
+ if (false == dc_link_construct(link, init_params))
goto construct_fail;
return link;
@@ -1460,7 +1461,7 @@ alloc_fail:
void link_destroy(struct dc_link **link)
{
- destruct(*link);
+ dc_link_destruct(*link);
kfree(*link);
*link = NULL;
}
@@ -1495,10 +1496,7 @@ static enum dc_status enable_link_dp(
bool skip_video_pattern;
struct dc_link *link = stream->link;
struct dc_link_settings link_settings = {0};
- enum dp_panel_mode panel_mode;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
bool fec_enable;
-#endif
int i;
bool apply_seamless_boot_optimization = false;
@@ -1514,15 +1512,6 @@ static enum dc_status enable_link_dp(
decide_link_settings(stream, &link_settings);
if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {
- /* If link settings are different than current and link already enabled
- * then need to disable before programming to new rate.
- */
- if (link->link_status.link_active &&
- (link->cur_link_settings.lane_count != link_settings.lane_count ||
- link->cur_link_settings.link_rate != link_settings.link_rate)) {
- dp_disable_link_phy(link, pipe_ctx->stream->signal);
- }
-
/*in case it is not on*/
link->dc->hwss.edp_power_control(link, true);
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
@@ -1533,50 +1522,29 @@ static enum dc_status enable_link_dp(
if (state->clk_mgr && !apply_seamless_boot_optimization)
state->clk_mgr->funcs->update_clocks(state->clk_mgr, state, false);
- dp_enable_link_phy(
- link,
- pipe_ctx->stream->signal,
- pipe_ctx->clock_source->id,
- &link_settings);
-
- if (stream->sink_patches.dppowerup_delay > 0) {
- int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
-
- msleep(delay_dp_power_up_in_ms);
- }
-
- panel_mode = dp_get_panel_mode(link);
- dp_set_panel_mode(link, panel_mode);
-
skip_video_pattern = true;
if (link_settings.link_rate == LINK_RATE_LOW)
skip_video_pattern = false;
- if (link->aux_access_disabled) {
- dc_link_dp_perform_link_training_skip_aux(link, &link_settings);
-
- link->cur_link_settings = link_settings;
- status = DC_OK;
- } else if (perform_link_training_with_retries(
- link,
+ if (perform_link_training_with_retries(
&link_settings,
skip_video_pattern,
- LINK_TRAINING_ATTEMPTS)) {
+ LINK_TRAINING_ATTEMPTS,
+ pipe_ctx,
+ pipe_ctx->stream->signal)) {
link->cur_link_settings = link_settings;
status = DC_OK;
}
else
status = DC_FAIL_DP_LINK_TRAINING;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (link->preferred_training_settings.fec_enable != NULL)
fec_enable = *link->preferred_training_settings.fec_enable;
else
fec_enable = true;
dp_set_fec_enable(link, fec_enable);
-#endif
return status;
}
@@ -2063,6 +2031,45 @@ static void write_i2c_redriver_setting(
ASSERT(i2c_success);
}
+static void disable_link(struct dc_link *link, enum signal_type signal)
+{
+ /*
+ * TODO: implement call for dp_set_hw_test_pattern
+ * it is needed for compliance testing
+ */
+
+ /* Here we need to specify that encoder output settings
+ * need to be calculated as for the set mode,
+ * it will lead to querying dynamic link capabilities
+ * which should be done before enable output
+ */
+
+ if (dc_is_dp_signal(signal)) {
+ /* SST DP, eDP */
+ if (dc_is_dp_sst_signal(signal))
+ dp_disable_link_phy(link, signal);
+ else
+ dp_disable_link_phy_mst(link, signal);
+
+ if (dc_is_dp_sst_signal(signal) ||
+ link->mst_stream_alloc_table.stream_count == 0) {
+ dp_set_fec_enable(link, false);
+ dp_set_fec_ready(link, false);
+ }
+ } else {
+ if (signal != SIGNAL_TYPE_VIRTUAL)
+ link->link_enc->funcs->disable_output(link->link_enc, signal);
+ }
+
+ if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ /* MST disable link only when no stream use the link */
+ if (link->mst_stream_alloc_table.stream_count <= 0)
+ link->link_status.link_active = false;
+ } else {
+ link->link_status.link_active = false;
+ }
+}
+
static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
{
struct dc_stream_state *stream = pipe_ctx->stream;
@@ -2147,6 +2154,19 @@ static enum dc_status enable_link(
struct pipe_ctx *pipe_ctx)
{
enum dc_status status = DC_ERROR_UNEXPECTED;
+ struct dc_stream_state *stream = pipe_ctx->stream;
+ struct dc_link *link = stream->link;
+
+ /* There's some scenarios where driver is unloaded with display
+ * still enabled. When driver is reloaded, it may cause a display
+ * to not light up if there is a mismatch between old and new
+ * link settings. Need to call disable first before enabling at
+ * new link settings.
+ */
+ if (link->link_status.link_active) {
+ disable_link(link, pipe_ctx->stream->signal);
+ }
+
switch (pipe_ctx->stream->signal) {
case SIGNAL_TYPE_DISPLAY_PORT:
status = enable_link_dp(state, pipe_ctx);
@@ -2181,46 +2201,6 @@ static enum dc_status enable_link(
return status;
}
-static void disable_link(struct dc_link *link, enum signal_type signal)
-{
- /*
- * TODO: implement call for dp_set_hw_test_pattern
- * it is needed for compliance testing
- */
-
- /* here we need to specify that encoder output settings
- * need to be calculated as for the set mode,
- * it will lead to querying dynamic link capabilities
- * which should be done before enable output */
-
- if (dc_is_dp_signal(signal)) {
- /* SST DP, eDP */
- if (dc_is_dp_sst_signal(signal))
- dp_disable_link_phy(link, signal);
- else
- dp_disable_link_phy_mst(link, signal);
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-
- if (dc_is_dp_sst_signal(signal) ||
- link->mst_stream_alloc_table.stream_count == 0) {
- dp_set_fec_enable(link, false);
- dp_set_fec_ready(link, false);
- }
-#endif
- } else {
- if (signal != SIGNAL_TYPE_VIRTUAL)
- link->link_enc->funcs->disable_output(link->link_enc, signal);
- }
-
- if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
- /* MST disable link only when no stream use the link */
- if (link->mst_stream_alloc_table.stream_count <= 0)
- link->link_status.link_active = false;
- } else {
- link->link_status.link_active = false;
- }
-}
-
static uint32_t get_timing_pixel_clock_100hz(const struct dc_crtc_timing *timing)
{
@@ -2357,9 +2337,9 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
uint32_t backlight_pwm_u16_16,
uint32_t frame_ramp)
{
- struct dc *core_dc = link->ctx->dc;
- struct abm *abm = core_dc->res_pool->abm;
- struct dmcu *dmcu = core_dc->res_pool->dmcu;
+ struct dc *dc = link->ctx->dc;
+ struct abm *abm = dc->res_pool->abm;
+ struct dmcu *dmcu = dc->res_pool->dmcu;
unsigned int controller_id = 0;
bool use_smooth_brightness = true;
int i;
@@ -2377,22 +2357,22 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
if (dc_is_embedded_signal(link->connector_signal)) {
for (i = 0; i < MAX_PIPES; i++) {
- if (core_dc->current_state->res_ctx.pipe_ctx[i].stream) {
- if (core_dc->current_state->res_ctx.
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream) {
+ if (dc->current_state->res_ctx.
pipe_ctx[i].stream->link
== link) {
/* DMCU -1 for all controller id values,
* therefore +1 here
*/
controller_id =
- core_dc->current_state->
+ dc->current_state->
res_ctx.pipe_ctx[i].stream_res.tg->inst +
1;
/* Disable brightness ramping when the display is blanked
* as it can hang the DMCU
*/
- if (core_dc->current_state->res_ctx.pipe_ctx[i].plane_state == NULL)
+ if (dc->current_state->res_ctx.pipe_ctx[i].plane_state == NULL)
frame_ramp = 0;
}
}
@@ -2410,8 +2390,8 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
bool dc_link_set_abm_disable(const struct dc_link *link)
{
- struct dc *core_dc = link->ctx->dc;
- struct abm *abm = core_dc->res_pool->abm;
+ struct dc *dc = link->ctx->dc;
+ struct abm *abm = dc->res_pool->abm;
if ((abm == NULL) || (abm->funcs->set_backlight_level_pwm == NULL))
return false;
@@ -2423,12 +2403,13 @@ bool dc_link_set_abm_disable(const struct dc_link *link)
bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool wait)
{
- struct dc *core_dc = link->ctx->dc;
- struct dmcu *dmcu = core_dc->res_pool->dmcu;
+ struct dc *dc = link->ctx->dc;
+ struct dmcu *dmcu = dc->res_pool->dmcu;
+ struct dmub_psr *psr = dc->res_pool->psr;
-
-
- if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_feature_enabled)
+ if ((psr != NULL) && link->psr_feature_enabled)
+ psr->funcs->set_psr_enable(psr, allow_active);
+ else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_feature_enabled)
dmcu->funcs->set_psr_enable(dmcu, allow_active, wait);
link->psr_allow_active = allow_active;
@@ -2438,10 +2419,13 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool
bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state)
{
- struct dc *core_dc = link->ctx->dc;
- struct dmcu *dmcu = core_dc->res_pool->dmcu;
+ struct dc *dc = link->ctx->dc;
+ struct dmcu *dmcu = dc->res_pool->dmcu;
+ struct dmub_psr *psr = dc->res_pool->psr;
- if (dmcu != NULL && link->psr_feature_enabled)
+ if (psr != NULL && link->psr_feature_enabled)
+ psr->funcs->get_psr_state(psr_state);
+ else if (dmcu != NULL && link->psr_feature_enabled)
dmcu->funcs->get_psr_state(dmcu, psr_state);
return true;
@@ -2486,8 +2470,9 @@ bool dc_link_setup_psr(struct dc_link *link,
const struct dc_stream_state *stream, struct psr_config *psr_config,
struct psr_context *psr_context)
{
- struct dc *core_dc;
+ struct dc *dc;
struct dmcu *dmcu;
+ struct dmub_psr *psr;
int i;
/* updateSinkPsrDpcdConfig*/
union dpcd_psr_configuration psr_configuration;
@@ -2497,10 +2482,11 @@ bool dc_link_setup_psr(struct dc_link *link,
if (!link)
return false;
- core_dc = link->ctx->dc;
- dmcu = core_dc->res_pool->dmcu;
+ dc = link->ctx->dc;
+ dmcu = dc->res_pool->dmcu;
+ psr = dc->res_pool->psr;
- if (!dmcu)
+ if (!dmcu && !psr)
return false;
@@ -2537,13 +2523,13 @@ bool dc_link_setup_psr(struct dc_link *link,
psr_context->engineId = link->link_enc->preferred_engine;
for (i = 0; i < MAX_PIPES; i++) {
- if (core_dc->current_state->res_ctx.pipe_ctx[i].stream
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream
== stream) {
/* dmcu -1 for all controller id values,
* therefore +1 here
*/
psr_context->controllerId =
- core_dc->current_state->res_ctx.
+ dc->current_state->res_ctx.
pipe_ctx[i].stream_res.tg->inst + 1;
break;
}
@@ -2556,7 +2542,7 @@ bool dc_link_setup_psr(struct dc_link *link,
transmitter_to_phy_id(link->link_enc->transmitter);
psr_context->crtcTimingVerticalTotal = stream->timing.v_total;
- psr_context->vsyncRateHz = div64_u64(div64_u64((stream->
+ psr_context->vsync_rate_hz = div64_u64(div64_u64((stream->
timing.pix_clk_100hz * 100),
stream->timing.v_total),
stream->timing.h_total);
@@ -2586,7 +2572,7 @@ bool dc_link_setup_psr(struct dc_link *link,
psr_context->psr_level.u32all = 0;
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
/*skip power down the single pipe since it blocks the cstate*/
if (ASICREV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev))
psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
@@ -2609,7 +2595,10 @@ bool dc_link_setup_psr(struct dc_link *link,
*/
psr_context->frame_delay = 0;
- link->psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context);
+ if (psr)
+ link->psr_feature_enabled = psr->funcs->setup_psr(psr, link, psr_context);
+ else
+ link->psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context);
/* psr_enabled == 0 indicates setup_psr did not succeed, but this
* should not happen since firmware should be running at this point
@@ -2644,28 +2633,13 @@ static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
return dc_fixpt_div_int(mbytes_per_sec, 54);
}
-static int get_color_depth(enum dc_color_depth color_depth)
-{
- switch (color_depth) {
- case COLOR_DEPTH_666: return 6;
- case COLOR_DEPTH_888: return 8;
- case COLOR_DEPTH_101010: return 10;
- case COLOR_DEPTH_121212: return 12;
- case COLOR_DEPTH_141414: return 14;
- case COLOR_DEPTH_161616: return 16;
- default: return 0;
- }
-}
-
static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
{
- uint32_t bpc;
uint64_t kbps;
struct fixed31_32 peak_kbps;
uint32_t numerator;
uint32_t denominator;
- bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth);
kbps = dc_bandwidth_in_kbps_from_timing(&pipe_ctx->stream->timing);
/*
@@ -2899,6 +2873,39 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
return DC_OK;
}
+
+enum dc_status dc_link_reallocate_mst_payload(struct dc_link *link)
+{
+ int i;
+ struct pipe_ctx *pipe_ctx;
+
+ // Clear all of MST payload then reallocate
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link &&
+ pipe_ctx->stream->dpms_off == false &&
+ pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ deallocate_mst_payload(pipe_ctx);
+ }
+ }
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link &&
+ pipe_ctx->stream->dpms_off == false &&
+ pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ /* enable/disable PHY will clear connection between BE and FE
+ * need to restore it.
+ */
+ link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
+ pipe_ctx->stream_res.stream_enc->id, true);
+ dc_link_allocate_mst_payload(pipe_ctx);
+ }
+ }
+
+ return DC_OK;
+}
+
#if defined(CONFIG_DRM_AMD_DC_HDCP)
static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
{
@@ -2922,12 +2929,12 @@ void core_link_enable_stream(
struct dc_state *state,
struct pipe_ctx *pipe_ctx)
{
- struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+ struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
enum dc_status status;
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
- if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) &&
+ if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) &&
dc_is_virtual_signal(pipe_ctx->stream->signal))
return;
@@ -2946,6 +2953,7 @@ void core_link_enable_stream(
pipe_ctx->stream_res.stream_enc,
&stream->timing,
stream->output_color_space,
+ stream->use_vsc_sdp_for_colorimetry,
stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
@@ -2969,14 +2977,14 @@ void core_link_enable_stream(
pipe_ctx->stream_res.stream_enc,
&stream->timing);
- if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
+ if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
bool apply_edp_fast_boot_optimization =
pipe_ctx->stream->apply_edp_fast_boot_optimization;
pipe_ctx->stream->apply_edp_fast_boot_optimization = false;
resource_build_info_frame(pipe_ctx);
- core_dc->hwss.update_info_frame(pipe_ctx);
+ dc->hwss.update_info_frame(pipe_ctx);
/* Do not touch link on seamless boot optimization. */
if (pipe_ctx->stream->apply_seamless_boot_optimization) {
@@ -3019,7 +3027,7 @@ void core_link_enable_stream(
}
}
- core_dc->hwss.enable_audio_stream(pipe_ctx);
+ dc->hwss.enable_audio_stream(pipe_ctx);
/* turn off otg test pattern if enable */
if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
@@ -3027,28 +3035,24 @@ void core_link_enable_stream(
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
COLOR_DEPTH_UNDEFINED);
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (pipe_ctx->stream->timing.flags.DSC) {
if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
dc_is_virtual_signal(pipe_ctx->stream->signal))
dp_set_dsc_enable(pipe_ctx, true);
}
-#endif
- core_dc->hwss.enable_stream(pipe_ctx);
+ dc->hwss.enable_stream(pipe_ctx);
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
/* Set DPS PPS SDP (AKA "info frames") */
if (pipe_ctx->stream->timing.flags.DSC) {
if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
dc_is_virtual_signal(pipe_ctx->stream->signal))
dp_set_dsc_pps_sdp(pipe_ctx, true);
}
-#endif
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
dc_link_allocate_mst_payload(pipe_ctx);
- core_dc->hwss.unblank_stream(pipe_ctx,
+ dc->hwss.unblank_stream(pipe_ctx,
&pipe_ctx->stream->link->cur_link_settings);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
@@ -3056,24 +3060,21 @@ void core_link_enable_stream(
#if defined(CONFIG_DRM_AMD_DC_HDCP)
update_psp_stream_config(pipe_ctx, false);
#endif
- }
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
- else { // if (IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment))
+ } else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
dc_is_virtual_signal(pipe_ctx->stream->signal))
dp_set_dsc_enable(pipe_ctx, true);
}
-#endif
}
void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
{
- struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+ struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->sink->link;
- if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) &&
+ if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) &&
dc_is_virtual_signal(pipe_ctx->stream->signal))
return;
@@ -3081,7 +3082,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
update_psp_stream_config(pipe_ctx, true);
#endif
- core_dc->hwss.blank_stream(pipe_ctx);
+ dc->hwss.blank_stream(pipe_ctx);
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
deallocate_mst_payload(pipe_ctx);
@@ -3110,25 +3111,23 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
write_i2c_redriver_setting(pipe_ctx, false);
}
}
- core_dc->hwss.disable_stream(pipe_ctx);
+ dc->hwss.disable_stream(pipe_ctx);
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (pipe_ctx->stream->timing.flags.DSC) {
if (dc_is_dp_signal(pipe_ctx->stream->signal))
dp_set_dsc_enable(pipe_ctx, false);
}
-#endif
}
void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
{
- struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+ struct dc *dc = pipe_ctx->stream->ctx->dc;
if (!dc_is_hdmi_signal(pipe_ctx->stream->signal))
return;
- core_dc->hwss.set_avmute(pipe_ctx, enable);
+ dc->hwss.set_avmute(pipe_ctx, enable);
}
/**
@@ -3186,13 +3185,11 @@ uint32_t dc_bandwidth_in_kbps_from_timing(
uint32_t bits_per_channel = 0;
uint32_t kbps;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (timing->flags.DSC) {
kbps = (timing->pix_clk_100hz * timing->dsc_cfg.bits_per_pixel);
kbps = kbps / 160 + ((kbps % 160) ? 1 : 0);
return kbps;
}
-#endif
switch (timing->display_color_depth) {
case COLOR_DEPTH_666:
@@ -3345,6 +3342,7 @@ void dc_link_disable_hpd(const struct dc_link *link)
void dc_link_set_test_pattern(struct dc_link *link,
enum dp_test_pattern test_pattern,
+ enum dp_test_pattern_color_space test_pattern_color_space,
const struct link_training_settings *p_link_settings,
const unsigned char *p_custom_pattern,
unsigned int cust_pattern_size)
@@ -3353,6 +3351,7 @@ void dc_link_set_test_pattern(struct dc_link *link,
dc_link_dp_set_test_pattern(
link,
test_pattern,
+ test_pattern_color_space,
p_link_settings,
p_custom_pattern,
cust_pattern_size);
@@ -3368,7 +3367,6 @@ uint32_t dc_link_bandwidth_kbps(
link_bw_kbps *= 8; /* 8 bits per byte*/
link_bw_kbps *= link_setting->lane_count;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
/* Account for FEC overhead.
* We have to do it based on caps,
@@ -3393,7 +3391,6 @@ uint32_t dc_link_bandwidth_kbps(
link_bw_kbps = mul_u64_u32_shr(BIT_ULL(32) * 970LL / 1000,
link_bw_kbps, 32);
}
-#endif
return link_bw_kbps;
@@ -3407,3 +3404,10 @@ const struct dc_link_settings *dc_link_get_link_cap(
return &link->preferred_link_setting;
return &link->verified_link_cap;
}
+
+void dc_link_overwrite_extended_receiver_cap(
+ struct dc_link *link)
+{
+ dp_overwrite_extended_receiver_cap(link);
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
index 81789191d4ec..a49c10d5df26 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
@@ -187,7 +187,7 @@ void dal_ddc_i2c_payloads_add(
}
-static void construct(
+static void ddc_service_construct(
struct ddc_service *ddc_service,
struct ddc_service_init_data *init_data)
{
@@ -206,7 +206,10 @@ static void construct(
ddc_service->ddc_pin = NULL;
} else {
hw_info.ddc_channel = i2c_info.i2c_line;
- hw_info.hw_supported = i2c_info.i2c_hw_assist;
+ if (ddc_service->link != NULL)
+ hw_info.hw_supported = i2c_info.i2c_hw_assist;
+ else
+ hw_info.hw_supported = false;
ddc_service->ddc_pin = dal_gpio_create_ddc(
gpio_service,
@@ -236,11 +239,11 @@ struct ddc_service *dal_ddc_service_create(
if (!ddc_service)
return NULL;
- construct(ddc_service, init_data);
+ ddc_service_construct(ddc_service, init_data);
return ddc_service;
}
-static void destruct(struct ddc_service *ddc)
+static void ddc_service_destruct(struct ddc_service *ddc)
{
if (ddc->ddc_pin)
dal_gpio_destroy_ddc(&ddc->ddc_pin);
@@ -252,7 +255,7 @@ void dal_ddc_service_destroy(struct ddc_service **ddc)
BREAK_TO_DEBUGGER();
return;
}
- destruct(*ddc);
+ ddc_service_destruct(*ddc);
kfree(*ddc);
*ddc = NULL;
}
@@ -587,7 +590,7 @@ bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
struct aux_payload *payload)
{
uint32_t retrieved = 0;
- bool ret = 0;
+ bool ret = false;
if (!ddc)
return false;
@@ -647,17 +650,16 @@ bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
}
-enum dc_status dc_link_aux_configure_timeout(struct ddc_service *ddc,
+uint32_t dc_link_aux_configure_timeout(struct ddc_service *ddc,
uint32_t timeout)
{
- enum dc_status status = DC_OK;
+ uint32_t prev_timeout = 0;
struct ddc *ddc_pin = ddc->ddc_pin;
- if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout == NULL)
- return DC_ERROR_UNEXPECTED;
- if (!ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout))
- status = DC_ERROR_UNEXPECTED;
- return status;
+ if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout)
+ prev_timeout =
+ ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout);
+ return prev_timeout;
}
/*test only function*/
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 504055fc70e8..6ab298c65247 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -4,12 +4,8 @@
#include "dc_link_dp.h"
#include "dm_helpers.h"
#include "opp.h"
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
#include "dsc.h"
-#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
#include "resource.h"
-#endif
#include "inc/core_types.h"
#include "link_hwss.h"
@@ -21,6 +17,9 @@
#define DC_LOGGER \
link->ctx->logger
+
+#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
+
/* maximum pre emphasis level allowed for each voltage swing level*/
static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = {
PRE_EMPHASIS_LEVEL3,
@@ -221,19 +220,31 @@ static enum dpcd_training_patterns
return dpcd_tr_pattern;
}
+static inline bool is_repeater(struct dc_link *link, uint32_t offset)
+{
+ return (!link->is_lttpr_mode_transparent && offset != 0);
+}
+
static void dpcd_set_lt_pattern_and_lane_settings(
struct dc_link *link,
const struct link_training_settings *lt_settings,
- enum dc_dp_training_pattern pattern)
+ enum dc_dp_training_pattern pattern,
+ uint32_t offset)
{
union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = { { {0} } };
- const uint32_t dpcd_base_lt_offset =
- DP_TRAINING_PATTERN_SET;
+
+ uint32_t dpcd_base_lt_offset;
+
uint8_t dpcd_lt_buffer[5] = {0};
union dpcd_training_pattern dpcd_pattern = { {0} };
uint32_t lane;
uint32_t size_in_bytes;
bool edp_workaround = false; /* TODO link_prop.INTERNAL */
+ dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET;
+
+ if (is_repeater(link, offset))
+ dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
/*****************************************************************
* DpcdAddress_TrainingPatternSet
@@ -241,14 +252,21 @@ static void dpcd_set_lt_pattern_and_lane_settings(
dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
dc_dp_training_pattern_to_dpcd_training_pattern(link, pattern);
- dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
+ dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
= dpcd_pattern.raw;
- DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
- __func__,
- DP_TRAINING_PATTERN_SET,
- dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
-
+ if (is_repeater(link, offset)) {
+ DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
+ __func__,
+ offset,
+ dpcd_base_lt_offset,
+ dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
+ } else {
+ DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",
+ __func__,
+ dpcd_base_lt_offset,
+ dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
+ }
/*****************************************************************
* DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set
*****************************************************************/
@@ -268,24 +286,35 @@ static void dpcd_set_lt_pattern_and_lane_settings(
PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
}
- /* concatinate everything into one buffer*/
+ /* concatenate everything into one buffer*/
size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
// 0x00103 - 0x00102
memmove(
- &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - dpcd_base_lt_offset],
+ &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
dpcd_lane,
size_in_bytes);
- DC_LOG_HW_LINK_TRAINING("%s:\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
- __func__,
- DP_TRAINING_LANE0_SET,
- dpcd_lane[0].bits.VOLTAGE_SWING_SET,
- dpcd_lane[0].bits.PRE_EMPHASIS_SET,
- dpcd_lane[0].bits.MAX_SWING_REACHED,
- dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
-
+ if (is_repeater(link, offset)) {
+ DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
+ " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
+ __func__,
+ offset,
+ dpcd_base_lt_offset,
+ dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+ dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+ dpcd_lane[0].bits.MAX_SWING_REACHED,
+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+ } else {
+ DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
+ __func__,
+ dpcd_base_lt_offset,
+ dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+ dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+ dpcd_lane[0].bits.MAX_SWING_REACHED,
+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+ }
if (edp_workaround) {
/* for eDP write in 2 parts because the 5-byte burst is
* causing issues on some eDP panels (EPR#366724)
@@ -495,8 +524,12 @@ static void get_lane_status_and_drive_settings(
const struct link_training_settings *link_training_setting,
union lane_status *ln_status,
union lane_align_status_updated *ln_status_updated,
- struct link_training_settings *req_settings)
+ struct link_training_settings *req_settings,
+ uint32_t offset)
{
+ unsigned int lane01_status_address = DP_LANE0_1_STATUS;
+ uint8_t lane_adjust_offset = 4;
+ unsigned int lane01_adjust_address;
uint8_t dpcd_buf[6] = {0};
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
struct link_training_settings request_settings = { {0} };
@@ -504,9 +537,16 @@ static void get_lane_status_and_drive_settings(
memset(req_settings, '\0', sizeof(struct link_training_settings));
+ if (is_repeater(link, offset)) {
+ lane01_status_address =
+ DP_LANE0_1_STATUS_PHY_REPEATER1 +
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
+ lane_adjust_offset = 3;
+ }
+
core_link_read_dpcd(
link,
- DP_LANE0_1_STATUS,
+ lane01_status_address,
(uint8_t *)(dpcd_buf),
sizeof(dpcd_buf));
@@ -517,22 +557,47 @@ static void get_lane_status_and_drive_settings(
ln_status[lane].raw =
get_nibble_at_index(&dpcd_buf[0], lane);
dpcd_lane_adjust[lane].raw =
- get_nibble_at_index(&dpcd_buf[4], lane);
+ get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
}
ln_status_updated->raw = dpcd_buf[2];
- DC_LOG_HW_LINK_TRAINING("%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
- __func__,
- DP_LANE0_1_STATUS, dpcd_buf[0],
- DP_LANE2_3_STATUS, dpcd_buf[1]);
-
- DC_LOG_HW_LINK_TRAINING("%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
- __func__,
- DP_ADJUST_REQUEST_LANE0_1,
- dpcd_buf[4],
- DP_ADJUST_REQUEST_LANE2_3,
- dpcd_buf[5]);
+ if (is_repeater(link, offset)) {
+ DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
+ " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
+ __func__,
+ offset,
+ lane01_status_address, dpcd_buf[0],
+ lane01_status_address + 1, dpcd_buf[1]);
+ } else {
+ DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",
+ __func__,
+ lane01_status_address, dpcd_buf[0],
+ lane01_status_address + 1, dpcd_buf[1]);
+ }
+ lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1;
+
+ if (is_repeater(link, offset))
+ lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 +
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
+
+ if (is_repeater(link, offset)) {
+ DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
+ " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
+ __func__,
+ offset,
+ lane01_adjust_address,
+ dpcd_buf[lane_adjust_offset],
+ lane01_adjust_address + 1,
+ dpcd_buf[lane_adjust_offset + 1]);
+ } else {
+ DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",
+ __func__,
+ lane01_adjust_address,
+ dpcd_buf[lane_adjust_offset],
+ lane01_adjust_address + 1,
+ dpcd_buf[lane_adjust_offset + 1]);
+ }
/*copy to req_settings*/
request_settings.link_settings.lane_count =
@@ -571,10 +636,18 @@ static void get_lane_status_and_drive_settings(
static void dpcd_set_lane_settings(
struct dc_link *link,
- const struct link_training_settings *link_training_setting)
+ const struct link_training_settings *link_training_setting,
+ uint32_t offset)
{
union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
uint32_t lane;
+ unsigned int lane0_set_address;
+
+ lane0_set_address = DP_TRAINING_LANE0_SET;
+
+ if (is_repeater(link, offset))
+ lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
for (lane = 0; lane <
(uint32_t)(link_training_setting->
@@ -597,7 +670,7 @@ static void dpcd_set_lane_settings(
}
core_link_write_dpcd(link,
- DP_TRAINING_LANE0_SET,
+ lane0_set_address,
(uint8_t *)(dpcd_lane),
link_training_setting->link_settings.lane_count);
@@ -620,14 +693,26 @@ static void dpcd_set_lane_settings(
}
*/
- DC_LOG_HW_LINK_TRAINING("%s\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
- __func__,
- DP_TRAINING_LANE0_SET,
- dpcd_lane[0].bits.VOLTAGE_SWING_SET,
- dpcd_lane[0].bits.PRE_EMPHASIS_SET,
- dpcd_lane[0].bits.MAX_SWING_REACHED,
- dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+ if (is_repeater(link, offset)) {
+ DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
+ " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
+ __func__,
+ offset,
+ lane0_set_address,
+ dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+ dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+ dpcd_lane[0].bits.MAX_SWING_REACHED,
+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+ } else {
+ DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
+ __func__,
+ lane0_set_address,
+ dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+ dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+ dpcd_lane[0].bits.MAX_SWING_REACHED,
+ dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+ }
link->cur_lane_setting = link_training_setting->lane_settings[0];
}
@@ -647,17 +732,6 @@ static bool is_max_vs_reached(
}
-void dc_link_dp_set_drive_settings(
- struct dc_link *link,
- struct link_training_settings *lt_settings)
-{
- /* program ASIC PHY settings*/
- dp_set_hw_lane_settings(link, lt_settings);
-
- /* Notify DP sink the PHY settings from source */
- dpcd_set_lane_settings(link, lt_settings);
-}
-
static bool perform_post_lt_adj_req_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
@@ -690,7 +764,8 @@ static bool perform_post_lt_adj_req_sequence(
lt_settings,
dpcd_lane_status,
&dpcd_lane_status_updated,
- &req_settings);
+ &req_settings,
+ DPRX);
if (dpcd_lane_status_updated.bits.
POST_LT_ADJ_REQ_IN_PROGRESS == 0)
@@ -747,6 +822,31 @@ static bool perform_post_lt_adj_req_sequence(
}
+/* Only used for channel equalization */
+static uint32_t translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
+{
+ unsigned int aux_rd_interval_us = 400;
+
+ switch (dpcd_aux_read_interval) {
+ case 0x01:
+ aux_rd_interval_us = 400;
+ break;
+ case 0x02:
+ aux_rd_interval_us = 4000;
+ break;
+ case 0x03:
+ aux_rd_interval_us = 8000;
+ break;
+ case 0x04:
+ aux_rd_interval_us = 16000;
+ break;
+ default:
+ break;
+ }
+
+ return aux_rd_interval_us;
+}
+
static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
union lane_status *dpcd_lane_status)
{
@@ -765,37 +865,55 @@ static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
static enum link_training_result perform_channel_equalization_sequence(
struct dc_link *link,
- struct link_training_settings *lt_settings)
+ struct link_training_settings *lt_settings,
+ uint32_t offset)
{
struct link_training_settings req_settings;
enum dc_dp_training_pattern tr_pattern;
uint32_t retries_ch_eq;
+ uint32_t wait_time_microsec;
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
+ /* Note: also check that TPS4 is a supported feature*/
+
tr_pattern = lt_settings->pattern_for_eq;
- dp_set_hw_training_pattern(link, tr_pattern);
+ if (is_repeater(link, offset))
+ tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
+
+ dp_set_hw_training_pattern(link, tr_pattern, offset);
for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
retries_ch_eq++) {
- dp_set_hw_lane_settings(link, lt_settings);
+ dp_set_hw_lane_settings(link, lt_settings, offset);
/* 2. update DPCD*/
if (!retries_ch_eq)
/* EPR #361076 - write as a 5-byte burst,
- * but only for the 1-st iteration*/
+ * but only for the 1-st iteration
+ */
+
dpcd_set_lt_pattern_and_lane_settings(
link,
lt_settings,
- tr_pattern);
+ tr_pattern, offset);
else
- dpcd_set_lane_settings(link, lt_settings);
+ dpcd_set_lane_settings(link, lt_settings, offset);
/* 3. wait for receiver to lock-on*/
- wait_for_training_aux_rd_interval(link, lt_settings->eq_pattern_time);
+ wait_time_microsec = lt_settings->eq_pattern_time;
+
+ if (is_repeater(link, offset))
+ wait_time_microsec =
+ translate_training_aux_read_interval(
+ link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
+
+ wait_for_training_aux_rd_interval(
+ link,
+ wait_time_microsec);
/* 4. Read lane status and requested
* drive settings as set by the sink*/
@@ -805,7 +923,8 @@ static enum link_training_result perform_channel_equalization_sequence(
lt_settings,
dpcd_lane_status,
&dpcd_lane_status_updated,
- &req_settings);
+ &req_settings,
+ offset);
/* 5. check CR done*/
if (!is_cr_done(lane_count, dpcd_lane_status))
@@ -824,13 +943,16 @@ static enum link_training_result perform_channel_equalization_sequence(
return LINK_TRAINING_EQ_FAIL_EQ;
}
+#define TRAINING_AUX_RD_INTERVAL 100 //us
static enum link_training_result perform_clock_recovery_sequence(
struct dc_link *link,
- struct link_training_settings *lt_settings)
+ struct link_training_settings *lt_settings,
+ uint32_t offset)
{
uint32_t retries_cr;
uint32_t retry_count;
+ uint32_t wait_time_microsec;
struct link_training_settings req_settings;
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
enum dc_dp_training_pattern tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_1;
@@ -840,7 +962,7 @@ static enum link_training_result perform_clock_recovery_sequence(
retries_cr = 0;
retry_count = 0;
- dp_set_hw_training_pattern(link, tr_pattern);
+ dp_set_hw_training_pattern(link, tr_pattern, offset);
/* najeeb - The synaptics MST hub can put the LT in
* infinite loop by switching the VS
@@ -857,7 +979,8 @@ static enum link_training_result perform_clock_recovery_sequence(
/* 1. call HWSS to set lane settings*/
dp_set_hw_lane_settings(
link,
- lt_settings);
+ lt_settings,
+ offset);
/* 2. update DPCD of the receiver*/
if (!retries_cr)
@@ -866,16 +989,23 @@ static enum link_training_result perform_clock_recovery_sequence(
dpcd_set_lt_pattern_and_lane_settings(
link,
lt_settings,
- tr_pattern);
+ tr_pattern,
+ offset);
else
dpcd_set_lane_settings(
link,
- lt_settings);
+ lt_settings,
+ offset);
/* 3. wait receiver to lock-on*/
+ wait_time_microsec = lt_settings->cr_pattern_time;
+
+ if (!link->is_lttpr_mode_transparent)
+ wait_time_microsec = TRAINING_AUX_RD_INTERVAL;
+
wait_for_training_aux_rd_interval(
link,
- lt_settings->cr_pattern_time);
+ wait_time_microsec);
/* 4. Read lane status and requested drive
* settings as set by the sink
@@ -885,7 +1015,8 @@ static enum link_training_result perform_clock_recovery_sequence(
lt_settings,
dpcd_lane_status,
&dpcd_lane_status_updated,
- &req_settings);
+ &req_settings,
+ offset);
/* 5. check CR done*/
if (is_cr_done(lane_count, dpcd_lane_status))
@@ -1054,6 +1185,102 @@ static void initialize_training_settings(
lt_settings->enhanced_framing = 1;
}
+static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
+{
+ switch (lttpr_repeater_count) {
+ case 0x80: // 1 lttpr repeater
+ return 1;
+ case 0x40: // 2 lttpr repeaters
+ return 2;
+ case 0x20: // 3 lttpr repeaters
+ return 3;
+ case 0x10: // 4 lttpr repeaters
+ return 4;
+ case 0x08: // 5 lttpr repeaters
+ return 5;
+ case 0x04: // 6 lttpr repeaters
+ return 6;
+ case 0x02: // 7 lttpr repeaters
+ return 7;
+ case 0x01: // 8 lttpr repeaters
+ return 8;
+ default:
+ break;
+ }
+ return 0; // invalid value
+}
+
+static void configure_lttpr_mode(struct dc_link *link)
+{
+ /* aux timeout is already set to extended */
+ /* RESET/SET lttpr mode to enable non transparent mode */
+ uint8_t repeater_cnt;
+ uint32_t aux_interval_address;
+ uint8_t repeater_id;
+ enum dc_status result = DC_ERROR_UNEXPECTED;
+ uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT;
+
+ DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__);
+ result = core_link_write_dpcd(link,
+ DP_PHY_REPEATER_MODE,
+ (uint8_t *)&repeater_mode,
+ sizeof(repeater_mode));
+
+ if (result == DC_OK) {
+ link->dpcd_caps.lttpr_caps.mode = repeater_mode;
+ }
+
+ if (!link->is_lttpr_mode_transparent) {
+
+ DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__);
+
+ repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
+ result = core_link_write_dpcd(link,
+ DP_PHY_REPEATER_MODE,
+ (uint8_t *)&repeater_mode,
+ sizeof(repeater_mode));
+
+ if (result == DC_OK) {
+ link->dpcd_caps.lttpr_caps.mode = repeater_mode;
+ }
+
+ repeater_cnt = convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
+ for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
+ aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 +
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1));
+ core_link_read_dpcd(
+ link,
+ aux_interval_address,
+ (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
+ sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
+ link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
+ }
+ }
+}
+
+static void repeater_training_done(struct dc_link *link, uint32_t offset)
+{
+ union dpcd_training_pattern dpcd_pattern = { {0} };
+
+ const uint32_t dpcd_base_lt_offset =
+ DP_TRAINING_PATTERN_SET_PHY_REPEATER1 +
+ ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
+ /* Set training not in progress*/
+ dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
+
+ core_link_write_dpcd(
+ link,
+ dpcd_base_lt_offset,
+ &dpcd_pattern.raw,
+ 1);
+
+ DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",
+ __func__,
+ offset,
+ dpcd_base_lt_offset,
+ dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
+}
+
static void print_status_message(
struct dc_link *link,
const struct link_training_settings *lt_settings,
@@ -1133,6 +1360,17 @@ static void print_status_message(
lt_spread);
}
+void dc_link_dp_set_drive_settings(
+ struct dc_link *link,
+ struct link_training_settings *lt_settings)
+{
+ /* program ASIC PHY settings*/
+ dp_set_hw_lane_settings(link, lt_settings, DPRX);
+
+ /* Notify DP sink the PHY settings from source */
+ dpcd_set_lane_settings(link, lt_settings, DPRX);
+}
+
bool dc_link_dp_perform_link_training_skip_aux(
struct dc_link *link,
const struct dc_link_settings *link_setting)
@@ -1149,10 +1387,10 @@ bool dc_link_dp_perform_link_training_skip_aux(
/* 1. Perform_clock_recovery_sequence. */
/* transmit training pattern for clock recovery */
- dp_set_hw_training_pattern(link, pattern_for_cr);
+ dp_set_hw_training_pattern(link, pattern_for_cr, DPRX);
/* call HWSS to set lane settings*/
- dp_set_hw_lane_settings(link, &lt_settings);
+ dp_set_hw_lane_settings(link, &lt_settings, DPRX);
/* wait receiver to lock-on*/
wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time);
@@ -1160,10 +1398,10 @@ bool dc_link_dp_perform_link_training_skip_aux(
/* 2. Perform_channel_equalization_sequence. */
/* transmit training pattern for channel equalization. */
- dp_set_hw_training_pattern(link, lt_settings.pattern_for_eq);
+ dp_set_hw_training_pattern(link, lt_settings.pattern_for_eq, DPRX);
/* call HWSS to set lane settings*/
- dp_set_hw_lane_settings(link, &lt_settings);
+ dp_set_hw_lane_settings(link, &lt_settings, DPRX);
/* wait receiver to lock-on. */
wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time);
@@ -1185,9 +1423,10 @@ enum link_training_result dc_link_dp_perform_link_training(
{
enum link_training_result status = LINK_TRAINING_SUCCESS;
struct link_training_settings lt_settings;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+
bool fec_enable;
-#endif
+ uint8_t repeater_cnt;
+ uint8_t repeater_id;
initialize_training_settings(
link,
@@ -1198,23 +1437,47 @@ enum link_training_result dc_link_dp_perform_link_training(
/* 1. set link rate, lane count and spread. */
dpcd_set_link_settings(link, &lt_settings);
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
if (link->preferred_training_settings.fec_enable != NULL)
fec_enable = *link->preferred_training_settings.fec_enable;
else
fec_enable = true;
dp_set_fec_ready(link, fec_enable);
-#endif
+ if (!link->is_lttpr_mode_transparent) {
+ /* Configure lttpr mode */
+ configure_lttpr_mode(link);
+
+ /* 2. perform link training (set link training done
+ * to false is done as well)
+ */
+ repeater_cnt = convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
+
+ for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
+ repeater_id--) {
+ status = perform_clock_recovery_sequence(link, &lt_settings, repeater_id);
+
+ if (status != LINK_TRAINING_SUCCESS)
+ break;
+
+ status = perform_channel_equalization_sequence(link,
+ &lt_settings,
+ repeater_id);
+
+ if (status != LINK_TRAINING_SUCCESS)
+ break;
+
+ repeater_training_done(link, repeater_id);
+ }
+ }
- /* 2. perform link training (set link training done
- * to false is done as well)
- */
- status = perform_clock_recovery_sequence(link, &lt_settings);
+ if (status == LINK_TRAINING_SUCCESS) {
+ status = perform_clock_recovery_sequence(link, &lt_settings, DPRX);
if (status == LINK_TRAINING_SUCCESS) {
status = perform_channel_equalization_sequence(link,
- &lt_settings);
+ &lt_settings,
+ DPRX);
+ }
}
if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
@@ -1233,23 +1496,58 @@ enum link_training_result dc_link_dp_perform_link_training(
}
bool perform_link_training_with_retries(
- struct dc_link *link,
const struct dc_link_settings *link_setting,
bool skip_video_pattern,
- int attempts)
+ int attempts,
+ struct pipe_ctx *pipe_ctx,
+ enum signal_type signal)
{
uint8_t j;
uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
+ struct dc_stream_state *stream = pipe_ctx->stream;
+ struct dc_link *link = stream->link;
+ enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
for (j = 0; j < attempts; ++j) {
- if (dc_link_dp_perform_link_training(
+ dp_enable_link_phy(
+ link,
+ signal,
+ pipe_ctx->clock_source->id,
+ link_setting);
+
+ if (stream->sink_patches.dppowerup_delay > 0) {
+ int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
+
+ msleep(delay_dp_power_up_in_ms);
+ }
+
+ dp_set_panel_mode(link, panel_mode);
+
+ /* We need to do this before the link training to ensure the idle pattern in SST
+ * mode will be sent right after the link training
+ */
+ link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
+ pipe_ctx->stream_res.stream_enc->id, true);
+
+ if (link->aux_access_disabled) {
+ dc_link_dp_perform_link_training_skip_aux(link, link_setting);
+ return true;
+ } else if (dc_link_dp_perform_link_training(
link,
link_setting,
skip_video_pattern) == LINK_TRAINING_SUCCESS)
return true;
+ /* latest link training still fail, skip delay and keep PHY on
+ */
+ if (j == (attempts - 1))
+ break;
+
+ dp_disable_link_phy(link, signal);
+
msleep(delay_between_attempts);
+
delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
}
@@ -1321,9 +1619,7 @@ enum link_training_result dc_link_dp_sync_lt_attempt(
enum link_training_result lt_status = LINK_TRAINING_SUCCESS;
enum dp_panel_mode panel_mode = DP_PANEL_MODE_DEFAULT;
enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
bool fec_enable = false;
-#endif
initialize_training_settings(
link,
@@ -1343,11 +1639,9 @@ enum link_training_result dc_link_dp_sync_lt_attempt(
dp_enable_link_phy(link, link->connector_signal,
dp_cs_id, link_settings);
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
/* Set FEC enable */
fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
dp_set_fec_ready(link, fec_enable);
-#endif
if (lt_overrides->alternate_scrambler_reset) {
if (*lt_overrides->alternate_scrambler_reset)
@@ -1367,10 +1661,11 @@ enum link_training_result dc_link_dp_sync_lt_attempt(
/* 2. perform link training (set link training done
* to false is done as well)
*/
- lt_status = perform_clock_recovery_sequence(link, &lt_settings);
+ lt_status = perform_clock_recovery_sequence(link, &lt_settings, DPRX);
if (lt_status == LINK_TRAINING_SUCCESS) {
lt_status = perform_channel_equalization_sequence(link,
- &lt_settings);
+ &lt_settings,
+ DPRX);
}
/* 3. Sync LT must skip TRAINING_PATTERN_SET:0 (video pattern)*/
@@ -1387,9 +1682,7 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)
*/
if (link_down == true) {
dp_disable_link_phy(link, link->connector_signal);
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
dp_set_fec_ready(link, false);
-#endif
}
link->sync_lt_in_progress = false;
@@ -1423,6 +1716,22 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link)
max_link_cap.link_spread)
max_link_cap.link_spread =
link->reported_link_cap.link_spread;
+ /*
+ * account for lttpr repeaters cap
+ * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
+ */
+ if (!link->is_lttpr_mode_transparent) {
+ if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
+ max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
+
+ if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate)
+ max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
+
+ DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",
+ __func__,
+ max_link_cap.lane_count,
+ max_link_cap.link_rate);
+ }
return max_link_cap;
}
@@ -1568,6 +1877,13 @@ bool dp_verify_link_cap(
max_link_cap = get_max_link_cap(link);
+ /* Grant extended timeout request */
+ if (!link->is_lttpr_mode_transparent && link->dpcd_caps.lttpr_caps.max_ext_timeout > 0) {
+ uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
+
+ core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant));
+ }
+
/* TODO implement override and monitor patch later */
/* try to train the link from high to low to
@@ -1576,6 +1892,16 @@ bool dp_verify_link_cap(
/* disable PHY done possible by BIOS, will be done by driver itself */
dp_disable_link_phy(link, link->connector_signal);
+ /* Temporary Renoir-specific workaround for SWDEV-215184;
+ * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle,
+ * so add extra cycle of enabling and disabling the PHY before first link training.
+ */
+ if (link->link_enc->features.flags.bits.DP_IS_USB_C &&
+ link->dc->debug.usbc_combo_phy_reset_wa) {
+ dp_enable_link_phy(link, link->connector_signal, dp_cs_id, cur);
+ dp_disable_link_phy(link, link->connector_signal);
+ }
+
dp_cs_id = get_clock_source_id(link);
/* link training starts with the maximum common settings
@@ -2280,6 +2606,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
dc_link_dp_set_test_pattern(
link,
test_pattern,
+ DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
&link_training_settings,
test_80_bit_pattern,
(DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
@@ -2291,6 +2618,8 @@ static void dp_test_send_link_test_pattern(struct dc_link *link)
union link_test_pattern dpcd_test_pattern;
union test_misc dpcd_test_params;
enum dp_test_pattern test_pattern;
+ enum dp_test_pattern_color_space test_pattern_color_space =
+ DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
@@ -2325,14 +2654,105 @@ static void dp_test_send_link_test_pattern(struct dc_link *link)
break;
}
+ test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
+ DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
+ DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
+
dc_link_dp_set_test_pattern(
link,
test_pattern,
+ test_pattern_color_space,
NULL,
NULL,
0);
}
+static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
+{
+ union audio_test_mode dpcd_test_mode = {0};
+ struct audio_test_pattern_type dpcd_pattern_type = {0};
+ union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
+ enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
+
+ struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
+ struct pipe_ctx *pipe_ctx = &pipes[0];
+ unsigned int channel_count;
+ unsigned int channel = 0;
+ unsigned int modes = 0;
+ unsigned int sampling_rate_in_hz = 0;
+
+ // get audio test mode and test pattern parameters
+ core_link_read_dpcd(
+ link,
+ DP_TEST_AUDIO_MODE,
+ &dpcd_test_mode.raw,
+ sizeof(dpcd_test_mode));
+
+ core_link_read_dpcd(
+ link,
+ DP_TEST_AUDIO_PATTERN_TYPE,
+ &dpcd_pattern_type.value,
+ sizeof(dpcd_pattern_type));
+
+ channel_count = dpcd_test_mode.bits.channel_count + 1;
+
+ // read pattern periods for requested channels when sawTooth pattern is requested
+ if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
+ dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
+
+ test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
+ DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
+ // read period for each channel
+ for (channel = 0; channel < channel_count; channel++) {
+ core_link_read_dpcd(
+ link,
+ DP_TEST_AUDIO_PERIOD_CH1 + channel,
+ &dpcd_pattern_period[channel].raw,
+ sizeof(dpcd_pattern_period[channel]));
+ }
+ }
+
+ // translate sampling rate
+ switch (dpcd_test_mode.bits.sampling_rate) {
+ case AUDIO_SAMPLING_RATE_32KHZ:
+ sampling_rate_in_hz = 32000;
+ break;
+ case AUDIO_SAMPLING_RATE_44_1KHZ:
+ sampling_rate_in_hz = 44100;
+ break;
+ case AUDIO_SAMPLING_RATE_48KHZ:
+ sampling_rate_in_hz = 48000;
+ break;
+ case AUDIO_SAMPLING_RATE_88_2KHZ:
+ sampling_rate_in_hz = 88200;
+ break;
+ case AUDIO_SAMPLING_RATE_96KHZ:
+ sampling_rate_in_hz = 96000;
+ break;
+ case AUDIO_SAMPLING_RATE_176_4KHZ:
+ sampling_rate_in_hz = 176400;
+ break;
+ case AUDIO_SAMPLING_RATE_192KHZ:
+ sampling_rate_in_hz = 192000;
+ break;
+ default:
+ sampling_rate_in_hz = 0;
+ break;
+ }
+
+ link->audio_test_data.flags.test_requested = 1;
+ link->audio_test_data.flags.disable_video = disable_video;
+ link->audio_test_data.sampling_rate = sampling_rate_in_hz;
+ link->audio_test_data.channel_count = channel_count;
+ link->audio_test_data.pattern_type = test_pattern;
+
+ if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
+ for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
+ link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
+ }
+ }
+}
+
static void handle_automated_test(struct dc_link *link)
{
union test_request test_request;
@@ -2362,6 +2782,12 @@ static void handle_automated_test(struct dc_link *link)
dp_test_send_link_test_pattern(link);
test_response.bits.ACK = 1;
}
+
+ if (test_request.bits.AUDIO_TEST_PATTERN) {
+ dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
+ test_response.bits.ACK = 1;
+ }
+
if (test_request.bits.PHY_TEST_PATTERN) {
dp_test_send_phy_test_pattern(link);
test_response.bits.ACK = 1;
@@ -2381,9 +2807,9 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } };
union device_service_irq device_service_clear = { { 0 } };
enum dc_status result;
-
bool status = false;
struct pipe_ctx *pipe_ctx;
+ struct dc_link_settings previous_link_settings;
int i;
if (out_link_loss)
@@ -2447,29 +2873,37 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
/* For now we only handle 'Downstream port status' case.
* If we got sink count changed it means
* Downstream port status changed,
- * then DM should call DC to do the detection. */
- if (hpd_rx_irq_check_link_loss_status(
- link,
- &hpd_irq_dpcd_data)) {
+ * then DM should call DC to do the detection.
+ * NOTE: Do not handle link loss on eDP since it is internal link*/
+ if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
+ hpd_rx_irq_check_link_loss_status(
+ link,
+ &hpd_irq_dpcd_data)) {
/* Connectivity log: link loss */
CONN_DATA_LINK_LOSS(link,
hpd_irq_dpcd_data.raw,
sizeof(hpd_irq_dpcd_data),
"Status: ");
- perform_link_training_with_retries(link,
- &link->cur_link_settings,
- true, LINK_TRAINING_ATTEMPTS);
-
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link &&
- pipe_ctx->stream->dpms_off == false &&
- pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
- dc_link_allocate_mst_payload(pipe_ctx);
- }
+ if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
+ break;
}
+ if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
+ return false;
+
+ previous_link_settings = link->cur_link_settings;
+
+ perform_link_training_with_retries(&previous_link_settings,
+ true, LINK_TRAINING_ATTEMPTS,
+ pipe_ctx,
+ pipe_ctx->stream->signal);
+
+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+ dc_link_reallocate_mst_payload(link);
+
status = false;
if (out_link_loss)
*out_link_loss = true;
@@ -2697,7 +3131,6 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
int length)
{
int retry = 0;
- union dp_downstream_port_present ds_port = { 0 };
if (!link->dpcd_caps.dpcd_rev.raw) {
do {
@@ -2710,9 +3143,6 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
} while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
}
- ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
- DP_DPCD_REV];
-
if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
switch (link->dpcd_caps.branch_dev_id) {
/* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down
@@ -2737,7 +3167,11 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
static bool retrieve_link_cap(struct dc_link *link)
{
- uint8_t dpcd_data[DP_ADAPTER_CAP - DP_DPCD_REV + 1];
+ /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
+ * which means size 16 will be good for both of those DPCD register block reads
+ */
+ uint8_t dpcd_data[16];
+ uint8_t lttpr_dpcd_data[6];
/*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
*/
@@ -2753,7 +3187,19 @@ static bool retrieve_link_cap(struct dc_link *link)
int i;
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
+ /* Set default timeout to 3.2ms and read LTTPR capabilities */
+ bool ext_timeout_support = link->dc->caps.extended_aux_timeout_support &&
+ !link->dc->config.disable_extended_timeout_support;
+
+ link->is_lttpr_mode_transparent = true;
+
+ if (ext_timeout_support) {
+ dc_link_aux_configure_timeout(link->ddc,
+ LINK_AUX_DEFAULT_EXTENDED_TIMEOUT_PERIOD);
+ }
+
memset(dpcd_data, '\0', sizeof(dpcd_data));
+ memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
memset(&down_strm_port_count,
'\0', sizeof(union down_stream_port_count));
memset(&edp_config_cap, '\0',
@@ -2785,6 +3231,52 @@ static bool retrieve_link_cap(struct dc_link *link)
return false;
}
+ if (ext_timeout_support) {
+
+ status = core_link_read_dpcd(
+ link,
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
+ lttpr_dpcd_data,
+ sizeof(lttpr_dpcd_data));
+
+ link->dpcd_caps.lttpr_caps.revision.raw =
+ lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV -
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+
+ link->dpcd_caps.lttpr_caps.max_link_rate =
+ lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER -
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+
+ link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
+ lttpr_dpcd_data[DP_PHY_REPEATER_CNT -
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+
+ link->dpcd_caps.lttpr_caps.max_lane_count =
+ lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER -
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+
+ link->dpcd_caps.lttpr_caps.mode =
+ lttpr_dpcd_data[DP_PHY_REPEATER_MODE -
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+
+ link->dpcd_caps.lttpr_caps.max_ext_timeout =
+ lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT -
+ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+
+ if (link->dpcd_caps.lttpr_caps.phy_repeater_cnt > 0 &&
+ link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
+ link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
+ link->dpcd_caps.lttpr_caps.revision.raw >= 0x14) {
+ link->is_lttpr_mode_transparent = false;
+ } else {
+ /*No lttpr reset timeout to its default value*/
+ link->is_lttpr_mode_transparent = true;
+ dc_link_aux_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
+ }
+
+ CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
+ }
+
{
union training_aux_rd_interval aux_rd_interval;
@@ -2792,7 +3284,7 @@ static bool retrieve_link_cap(struct dc_link *link)
dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
link->dpcd_caps.ext_receiver_cap_field_present =
- aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1 ? true:false;
+ aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1;
if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) {
uint8_t ext_cap_data[16];
@@ -2923,7 +3415,6 @@ static bool retrieve_link_cap(struct dc_link *link)
dp_hw_fw_revision.ieee_fw_rev,
sizeof(dp_hw_fw_revision.ieee_fw_rev));
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
memset(&link->dpcd_caps.dsc_caps, '\0',
sizeof(link->dpcd_caps.dsc_caps));
memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap));
@@ -2945,7 +3436,6 @@ static bool retrieve_link_cap(struct dc_link *link)
link->dpcd_caps.dsc_caps.dsc_ext_caps.raw,
sizeof(link->dpcd_caps.dsc_caps.dsc_ext_caps.raw));
}
-#endif
/* Connectivity log: detection */
CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
@@ -2953,6 +3443,68 @@ static bool retrieve_link_cap(struct dc_link *link)
return true;
}
+bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
+{
+ uint8_t dpcd_data[16];
+ uint32_t read_dpcd_retry_cnt = 3;
+ enum dc_status status = DC_ERROR_UNEXPECTED;
+ union dp_downstream_port_present ds_port = { 0 };
+ union down_stream_port_count down_strm_port_count;
+ union edp_configuration_cap edp_config_cap;
+
+ int i;
+
+ for (i = 0; i < read_dpcd_retry_cnt; i++) {
+ status = core_link_read_dpcd(
+ link,
+ DP_DPCD_REV,
+ dpcd_data,
+ sizeof(dpcd_data));
+ if (status == DC_OK)
+ break;
+ }
+
+ link->dpcd_caps.dpcd_rev.raw =
+ dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
+
+ if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0)
+ return false;
+
+ ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
+ DP_DPCD_REV];
+
+ get_active_converter_info(ds_port.byte, link);
+
+ down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT -
+ DP_DPCD_REV];
+
+ link->dpcd_caps.allow_invalid_MSA_timing_param =
+ down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
+
+ link->dpcd_caps.max_ln_count.raw = dpcd_data[
+ DP_MAX_LANE_COUNT - DP_DPCD_REV];
+
+ link->dpcd_caps.max_down_spread.raw = dpcd_data[
+ DP_MAX_DOWNSPREAD - DP_DPCD_REV];
+
+ link->reported_link_cap.lane_count =
+ link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
+ link->reported_link_cap.link_rate = dpcd_data[
+ DP_MAX_LINK_RATE - DP_DPCD_REV];
+ link->reported_link_cap.link_spread =
+ link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
+ LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
+
+ edp_config_cap.raw = dpcd_data[
+ DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
+ link->dpcd_caps.panel_mode_edp =
+ edp_config_cap.bits.ALT_SCRAMBLER_RESET;
+ link->dpcd_caps.dpcd_display_control_capable =
+ edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
+
+ return true;
+}
+
bool detect_dp_sink_caps(struct dc_link *link)
{
return retrieve_link_cap(link);
@@ -3067,21 +3619,20 @@ static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
static void set_crtc_test_pattern(struct dc_link *link,
struct pipe_ctx *pipe_ctx,
- enum dp_test_pattern test_pattern)
+ enum dp_test_pattern test_pattern,
+ enum dp_test_pattern_color_space test_pattern_color_space)
{
enum controller_dp_test_pattern controller_test_pattern;
enum dc_color_depth color_depth = pipe_ctx->
stream->timing.display_color_depth;
struct bit_depth_reduction_params params;
struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
int width = pipe_ctx->stream->timing.h_addressable +
pipe_ctx->stream->timing.h_border_left +
pipe_ctx->stream->timing.h_border_right;
int height = pipe_ctx->stream->timing.v_addressable +
pipe_ctx->stream->timing.v_border_bottom +
pipe_ctx->stream->timing.v_border_top;
-#endif
memset(&params, 0, sizeof(params));
@@ -3125,10 +3676,29 @@ static void set_crtc_test_pattern(struct dc_link *link,
if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
controller_test_pattern, color_depth);
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
else if (opp->funcs->opp_set_disp_pattern_generator) {
struct pipe_ctx *odm_pipe;
+ enum controller_dp_color_space controller_color_space;
int opp_cnt = 1;
+ uint8_t count = 0;
+
+ switch (test_pattern_color_space) {
+ case DP_TEST_PATTERN_COLOR_SPACE_RGB:
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
+ break;
+ case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
+ break;
+ case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
+ break;
+ case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
+ default:
+ controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
+ DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__);
+ ASSERT(0);
+ break;
+ }
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
opp_cnt++;
@@ -3141,6 +3711,7 @@ static void set_crtc_test_pattern(struct dc_link *link,
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
odm_opp->funcs->opp_set_disp_pattern_generator(odm_opp,
controller_test_pattern,
+ controller_color_space,
color_depth,
NULL,
width,
@@ -3148,12 +3719,18 @@ static void set_crtc_test_pattern(struct dc_link *link,
}
opp->funcs->opp_set_disp_pattern_generator(opp,
controller_test_pattern,
+ controller_color_space,
color_depth,
NULL,
width,
height);
+ /* wait for dpg to blank pixel data with test pattern */
+ for (count = 0; count < 1000; count++)
+ if (opp->funcs->dpg_is_blanked(opp))
+ break;
+ else
+ udelay(100);
}
-#endif
}
break;
case DP_TEST_PATTERN_VIDEO_MODE:
@@ -3166,7 +3743,6 @@ static void set_crtc_test_pattern(struct dc_link *link,
pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
color_depth);
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
else if (opp->funcs->opp_set_disp_pattern_generator) {
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
@@ -3181,6 +3757,7 @@ static void set_crtc_test_pattern(struct dc_link *link,
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
odm_opp->funcs->opp_set_disp_pattern_generator(odm_opp,
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+ CONTROLLER_DP_COLOR_SPACE_UDEFINED,
color_depth,
NULL,
width,
@@ -3188,12 +3765,12 @@ static void set_crtc_test_pattern(struct dc_link *link,
}
opp->funcs->opp_set_disp_pattern_generator(opp,
CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+ CONTROLLER_DP_COLOR_SPACE_UDEFINED,
color_depth,
NULL,
width,
height);
}
-#endif
}
break;
@@ -3205,6 +3782,7 @@ static void set_crtc_test_pattern(struct dc_link *link,
bool dc_link_dp_set_test_pattern(
struct dc_link *link,
enum dp_test_pattern test_pattern,
+ enum dp_test_pattern_color_space test_pattern_color_space,
const struct link_training_settings *p_link_settings,
const unsigned char *p_custom_pattern,
unsigned int cust_pattern_size)
@@ -3233,7 +3811,7 @@ bool dc_link_dp_set_test_pattern(
if (link->test_pattern_enabled && test_pattern ==
DP_TEST_PATTERN_VIDEO_MODE) {
/* Set CRTC Test Pattern */
- set_crtc_test_pattern(link, pipe_ctx, test_pattern);
+ set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
dp_set_hw_test_pattern(link, test_pattern,
(uint8_t *)p_custom_pattern,
(uint32_t)cust_pattern_size);
@@ -3256,8 +3834,8 @@ bool dc_link_dp_set_test_pattern(
if (is_dp_phy_pattern(test_pattern)) {
/* Set DPCD Lane Settings before running test pattern */
if (p_link_settings != NULL) {
- dp_set_hw_lane_settings(link, p_link_settings);
- dpcd_set_lane_settings(link, p_link_settings);
+ dp_set_hw_lane_settings(link, p_link_settings, DPRX);
+ dpcd_set_lane_settings(link, p_link_settings, DPRX);
}
/* Blank stream if running test pattern */
@@ -3348,7 +3926,7 @@ bool dc_link_dp_set_test_pattern(
}
} else {
/* CRTC Patterns */
- set_crtc_test_pattern(link, pipe_ctx, test_pattern);
+ set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
/* Set Test Pattern state */
link->test_pattern_enabled = true;
}
@@ -3468,7 +4046,6 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
return DP_PANEL_MODE_DEFAULT;
}
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
void dp_set_fec_ready(struct dc_link *link, bool ready)
{
/* FEC has to be "set ready" before the link training.
@@ -3538,5 +4115,4 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
}
}
}
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index a519dbc5ecb6..ddb855045767 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -12,12 +12,38 @@
#include "dc_link_ddc.h"
#include "dm_helpers.h"
#include "dpcd_defs.h"
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
#include "dsc.h"
-#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
#include "resource.h"
-#endif
+
+static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
+{
+ switch (lttpr_repeater_count) {
+ case 0x80: // 1 lttpr repeater
+ return 1;
+ case 0x40: // 2 lttpr repeaters
+ return 2;
+ case 0x20: // 3 lttpr repeaters
+ return 3;
+ case 0x10: // 4 lttpr repeaters
+ return 4;
+ case 0x08: // 5 lttpr repeaters
+ return 5;
+ case 0x04: // 6 lttpr repeaters
+ return 6;
+ case 0x02: // 7 lttpr repeaters
+ return 7;
+ case 0x01: // 8 lttpr repeaters
+ return 8;
+ default:
+ break;
+ }
+ return 0; // invalid value
+}
+
+static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset)
+{
+ return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset);
+}
enum dc_status core_link_read_dpcd(
struct dc_link *link,
@@ -69,8 +95,8 @@ void dp_enable_link_phy(
const struct dc_link_settings *link_settings)
{
struct link_encoder *link_enc = link->link_enc;
- struct dc *core_dc = link->ctx->dc;
- struct dmcu *dmcu = core_dc->res_pool->dmcu;
+ struct dc *dc = link->ctx->dc;
+ struct dmcu *dmcu = dc->res_pool->dmcu;
struct pipe_ctx *pipes =
link->dc->current_state->res_ctx.pipe_ctx;
@@ -147,15 +173,20 @@ bool edp_receiver_ready_T9(struct dc_link *link)
}
bool edp_receiver_ready_T7(struct dc_link *link)
{
- unsigned int tries = 0;
unsigned char sinkstatus = 0;
unsigned char edpRev = 0;
enum dc_status result = DC_OK;
+ /* use absolute time stamp to constrain max T7*/
+ unsigned long long enter_timestamp = 0;
+ unsigned long long finish_timestamp = 0;
+ unsigned long long time_taken_in_ns = 0;
+
result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
if (result == DC_OK && edpRev < DP_EDP_12)
return true;
/* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
+ enter_timestamp = dm_get_timestamp(link->ctx);
do {
sinkstatus = 0;
result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
@@ -163,8 +194,10 @@ bool edp_receiver_ready_T7(struct dc_link *link)
break;
if (result != DC_OK)
break;
- udelay(25); //MAx T7 is 50ms
- } while (++tries < 300);
+ udelay(25);
+ finish_timestamp = dm_get_timestamp(link->ctx);
+ time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
+ } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
if (link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0)
udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000);
@@ -174,8 +207,8 @@ bool edp_receiver_ready_T7(struct dc_link *link)
void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
{
- struct dc *core_dc = link->ctx->dc;
- struct dmcu *dmcu = core_dc->res_pool->dmcu;
+ struct dc *dc = link->ctx->dc;
+ struct dmcu *dmcu = dc->res_pool->dmcu;
if (!link->wa_flags.dp_keep_receiver_powered)
dp_receiver_power_ctrl(link, false);
@@ -212,7 +245,8 @@ void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
bool dp_set_hw_training_pattern(
struct dc_link *link,
- enum dc_dp_training_pattern pattern)
+ enum dc_dp_training_pattern pattern,
+ uint32_t offset)
{
enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
@@ -240,10 +274,14 @@ bool dp_set_hw_training_pattern(
void dp_set_hw_lane_settings(
struct dc_link *link,
- const struct link_training_settings *link_settings)
+ const struct link_training_settings *link_settings,
+ uint32_t offset)
{
struct link_encoder *encoder = link->link_enc;
+ if (!link->is_lttpr_mode_transparent && !is_immediate_downstream(link, offset))
+ return;
+
/* call Encoder to set lane settings */
encoder->funcs->dp_set_lane_settings(encoder, link_settings);
}
@@ -302,20 +340,12 @@ void dp_retrain_link_dp_test(struct dc_link *link,
memset(&link->cur_link_settings, 0,
sizeof(link->cur_link_settings));
- link->link_enc->funcs->enable_dp_output(
- link->link_enc,
- link_setting,
- pipes[i].clock_source->id);
- link->cur_link_settings = *link_setting;
-
- dp_receiver_power_ctrl(link, true);
-
perform_link_training_with_retries(
- link,
link_setting,
skip_video_pattern,
- LINK_TRAINING_ATTEMPTS);
-
+ LINK_TRAINING_ATTEMPTS,
+ &pipes[i],
+ SIGNAL_TYPE_DISPLAY_PORT);
link->dc->hwss.enable_stream(&pipes[i]);
@@ -339,7 +369,6 @@ void dp_retrain_link_dp_test(struct dc_link *link,
}
}
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
#define DC_LOGGER \
dsc->ctx->logger
static void dsc_optc_config_log(struct display_stream_compressor *dsc,
@@ -365,14 +394,14 @@ static void dsc_optc_config_log(struct display_stream_compressor *dsc,
static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
{
- struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+ struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
bool result = false;
- if (IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment))
+ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
result = true;
else
- result = dm_helpers_dp_write_dsc_enable(core_dc->ctx, stream, enable);
+ result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable);
return result;
}
@@ -382,7 +411,7 @@ static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
{
struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
- struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+ struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
@@ -418,7 +447,7 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
/* Enable DSC in encoder */
- if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
+ if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id);
dsc_optc_config_log(dsc, &dsc_optc_cfg);
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc,
@@ -443,7 +472,7 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
OPTC_DSC_DISABLED, 0, 0);
/* disable DSC in stream encoder */
- if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
+ if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(
pipe_ctx->stream_res.stream_enc,
OPTC_DSC_DISABLED, 0, 0);
@@ -486,7 +515,7 @@ out:
bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
{
struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
- struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+ struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
if (!pipe_ctx->stream->timing.flags.DSC || !dsc)
@@ -496,6 +525,9 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
struct dsc_config dsc_cfg;
uint8_t dsc_packed_pps[128];
+ memset(&dsc_cfg, 0, sizeof(dsc_cfg));
+ memset(dsc_packed_pps, 0, 128);
+
/* Enable DSC hw block */
dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
@@ -505,7 +537,7 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
DC_LOG_DSC(" ");
dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]);
- if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
+ if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id);
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.stream_enc,
@@ -514,7 +546,7 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable)
}
} else {
/* disable DSC PPS in stream encoder */
- if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
+ if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet(
pipe_ctx->stream_res.stream_enc, false, NULL);
}
@@ -537,5 +569,4 @@ bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx)
dp_set_dsc_pps_sdp(pipe_ctx, true);
return true;
}
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 37698305a2dc..a0eb9e533a61 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -46,15 +46,11 @@
#include "dce100/dce100_resource.h"
#include "dce110/dce110_resource.h"
#include "dce112/dce112_resource.h"
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
#include "dcn10/dcn10_resource.h"
#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
#include "dcn20/dcn20_resource.h"
-#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
#include "dcn21/dcn21_resource.h"
-#endif
#include "dce120/dce120_resource.h"
#define DC_LOGGER_INIT(logger)
@@ -99,23 +95,19 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
else
dc_version = DCE_VERSION_12_0;
break;
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
case FAMILY_RV:
dc_version = DCN_VERSION_1_0;
if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev))
dc_version = DCN_VERSION_1_01;
-#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev))
dc_version = DCN_VERSION_2_1;
-#endif
break;
#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
case FAMILY_NV:
dc_version = DCN_VERSION_2_0;
break;
-#endif
default:
dc_version = DCE_VERSION_UNKNOWN;
break;
@@ -162,20 +154,16 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc,
init_data->num_virtual_links, dc);
break;
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
case DCN_VERSION_1_0:
case DCN_VERSION_1_01:
res_pool = dcn10_create_resource_pool(init_data, dc);
break;
-#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
case DCN_VERSION_2_0:
res_pool = dcn20_create_resource_pool(init_data, dc);
break;
-#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
case DCN_VERSION_2_1:
res_pool = dcn21_create_resource_pool(init_data, dc);
break;
@@ -951,44 +939,44 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c);
}
-static bool are_rects_integer_multiples(struct rect src, struct rect dest)
-{
- if (dest.width >= src.width && dest.width % src.width == 0 &&
- dest.height >= src.height && dest.height % src.height == 0)
- return true;
-
- return false;
-}
-static void calculate_integer_scaling(struct pipe_ctx *pipe_ctx)
+/*
+ * When handling 270 rotation in mixed SLS mode, we have
+ * stream->timing.h_border_left that is non zero. If we are doing
+ * pipe-splitting, this h_border_left value gets added to recout.x and when it
+ * calls calculate_inits_and_adj_vp() and
+ * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a
+ * pipe to be incorrect.
+ *
+ * To fix this, instead of using stream->timing.h_border_left, we can use
+ * stream->dst.x to represent the border instead. So we will set h_border_left
+ * to 0 and shift the appropriate amount in stream->dst.x. We will then
+ * perform all calculations in resource_build_scaling_params() based on this
+ * and then restore the h_border_left and stream->dst.x to their original
+ * values.
+ *
+ * shift_border_left_to_dst() will shift the amount of h_border_left to
+ * stream->dst.x and set h_border_left to 0. restore_border_left_from_dst()
+ * will restore h_border_left and stream->dst.x back to their original values
+ * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the
+ * original h_border_left value in its calculation.
+ */
+int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
{
- if (!pipe_ctx->plane_state->scaling_quality.integer_scaling)
- return;
-
- //for Centered Mode
- if (pipe_ctx->stream->dst.width == pipe_ctx->stream->src.width &&
- pipe_ctx->stream->dst.height == pipe_ctx->stream->src.height) {
- // calculate maximum # of replication of src onto addressable
- unsigned int integer_multiple = min(
- pipe_ctx->stream->timing.h_addressable / pipe_ctx->stream->src.width,
- pipe_ctx->stream->timing.v_addressable / pipe_ctx->stream->src.height);
-
- //scale dst
- pipe_ctx->stream->dst.width = integer_multiple * pipe_ctx->stream->src.width;
- pipe_ctx->stream->dst.height = integer_multiple * pipe_ctx->stream->src.height;
+ int store_h_border_left = pipe_ctx->stream->timing.h_border_left;
- //center dst onto addressable
- pipe_ctx->stream->dst.x = (pipe_ctx->stream->timing.h_addressable - pipe_ctx->stream->dst.width)/2;
- pipe_ctx->stream->dst.y = (pipe_ctx->stream->timing.v_addressable - pipe_ctx->stream->dst.height)/2;
+ if (store_h_border_left) {
+ pipe_ctx->stream->timing.h_border_left = 0;
+ pipe_ctx->stream->dst.x += store_h_border_left;
}
+ return store_h_border_left;
+}
- //disable taps if src & dst are integer ratio
- if (are_rects_integer_multiples(pipe_ctx->stream->src, pipe_ctx->stream->dst)) {
- pipe_ctx->plane_state->scaling_quality.v_taps = 1;
- pipe_ctx->plane_state->scaling_quality.h_taps = 1;
- pipe_ctx->plane_state->scaling_quality.v_taps_c = 1;
- pipe_ctx->plane_state->scaling_quality.h_taps_c = 1;
- }
+void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx,
+ int store_h_border_left)
+{
+ pipe_ctx->stream->dst.x -= store_h_border_left;
+ pipe_ctx->stream->timing.h_border_left = store_h_border_left;
}
bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
@@ -996,6 +984,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
bool res = false;
+ int store_h_border_left = shift_border_left_to_dst(pipe_ctx);
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
/* Important: scaling ratio calculation requires pixel format,
* lb depth calculation requires recout and taps require scaling ratios.
@@ -1004,14 +993,18 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
pipe_ctx->plane_state->format);
- calculate_integer_scaling(pipe_ctx);
-
calculate_scaling_ratios(pipe_ctx);
calculate_viewport(pipe_ctx);
- if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16)
+ if (pipe_ctx->plane_res.scl_data.viewport.height < 16 ||
+ pipe_ctx->plane_res.scl_data.viewport.width < 16) {
+ if (store_h_border_left) {
+ restore_border_left_from_dst(pipe_ctx,
+ store_h_border_left);
+ }
return false;
+ }
calculate_recout(pipe_ctx);
@@ -1024,8 +1017,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top;
- pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right;
- pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
+ pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable +
+ store_h_border_left + timing->h_border_right;
+ pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable +
+ timing->v_border_top + timing->v_border_bottom;
/* Taps calculations */
if (pipe_ctx->plane_res.xfm != NULL)
@@ -1072,6 +1067,9 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
plane_state->dst_rect.x,
plane_state->dst_rect.y);
+ if (store_h_border_left)
+ restore_border_left_from_dst(pipe_ctx, store_h_border_left);
+
return res;
}
@@ -1217,7 +1215,7 @@ static struct pipe_ctx *acquire_free_pipe_for_head(
return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream);
}
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
static int acquire_first_split_pipe(
struct resource_context *res_ctx,
const struct resource_pool *pool,
@@ -1298,7 +1296,7 @@ bool dc_add_plane_to_context(
free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe);
- #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+ #if defined(CONFIG_DRM_AMD_DC_DCN)
if (!free_pipe) {
int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
if (pipe_idx >= 0)
@@ -1891,7 +1889,7 @@ static int acquire_resource_from_hw_enabled_state(
inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
if (inst == ENGINE_ID_UNKNOWN)
- return false;
+ return -1;
for (i = 0; i < pool->stream_enc_count; i++) {
if (pool->stream_enc[i]->id == inst) {
@@ -1903,10 +1901,10 @@ static int acquire_resource_from_hw_enabled_state(
// tg_inst not found
if (i == pool->stream_enc_count)
- return false;
+ return -1;
if (tg_inst >= pool->timing_generator_count)
- return false;
+ return -1;
if (!res_ctx->pipe_ctx[tg_inst].stream) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst];
@@ -1919,8 +1917,26 @@ static int acquire_resource_from_hw_enabled_state(
pipe_ctx->plane_res.dpp = pool->dpps[tg_inst];
pipe_ctx->stream_res.opp = pool->opps[tg_inst];
- if (pool->dpps[tg_inst])
+ if (pool->dpps[tg_inst]) {
pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst;
+
+ // Read DPP->MPCC->OPP Pipe from HW State
+ if (pool->mpc->funcs->read_mpcc_state) {
+ struct mpcc_state s = {0};
+
+ pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s);
+
+ if (s.dpp_id < MAX_MPCC)
+ pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id;
+
+ if (s.bot_mpcc_id < MAX_MPCC)
+ pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot =
+ &pool->mpc->mpcc_array[s.bot_mpcc_id];
+
+ if (s.opp_id < MAX_OPP)
+ pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id;
+ }
+ }
pipe_ctx->pipe_idx = tg_inst;
pipe_ctx->stream = stream;
@@ -1972,7 +1988,7 @@ enum dc_status resource_map_pool_resources(
/* acquire new resources */
pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
+#ifdef CONFIG_DRM_AMD_DC_DCN
if (pipe_idx < 0)
pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
#endif
@@ -2050,6 +2066,13 @@ void dc_resource_state_construct(
dst_ctx->clk_mgr = dc->clk_mgr;
}
+
+bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
+{
+ return dc->res_pool->res_cap->num_dsc > 0;
+}
+
+
/**
* dc_validate_global_state() - Determine if HW can support a given state
* Checks HW resource availability and bandwidth requirement.
@@ -2306,7 +2329,7 @@ static void set_avi_info_frame(
if (color_space == COLOR_SPACE_SRGB ||
color_space == COLOR_SPACE_2020_RGB_FULLRANGE) {
hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE;
- hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE;
+ hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
} else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) {
hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE;
@@ -2772,9 +2795,8 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
{
- struct dc *core_dc = dc;
struct dc_link *link = stream->link;
- struct timing_generator *tg = core_dc->res_pool->timing_generators[0];
+ struct timing_generator *tg = dc->res_pool->timing_generators[0];
enum dc_status res = DC_OK;
calculate_phy_pix_clks(stream);
@@ -2837,3 +2859,48 @@ unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
return -1;
}
}
+static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
+{
+ if (modes) {
+ if (modes->sample_rates.rate.RATE_192)
+ return 192000;
+ if (modes->sample_rates.rate.RATE_176_4)
+ return 176400;
+ if (modes->sample_rates.rate.RATE_96)
+ return 96000;
+ if (modes->sample_rates.rate.RATE_88_2)
+ return 88200;
+ if (modes->sample_rates.rate.RATE_48)
+ return 48000;
+ if (modes->sample_rates.rate.RATE_44_1)
+ return 44100;
+ if (modes->sample_rates.rate.RATE_32)
+ return 32000;
+ }
+ /*original logic when no audio info*/
+ return 441000;
+}
+
+void get_audio_check(struct audio_info *aud_modes,
+ struct audio_check *audio_chk)
+{
+ unsigned int i;
+ unsigned int max_sample_rate = 0;
+
+ if (aud_modes) {
+ audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/
+
+ audio_chk->max_audiosample_rate = 0;
+ for (i = 0; i < aud_modes->mode_count; i++) {
+ max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]);
+ if (audio_chk->max_audiosample_rate < max_sample_rate)
+ audio_chk->max_audiosample_rate = max_sample_rate;
+ /*dts takes the same as type 2: AP = 0.25*/
+ }
+ /*check which one take more bandwidth*/
+ if (audio_chk->max_audiosample_rate > 192000)
+ audio_chk->audio_packet_type = 0x9;/*AP =1*/
+ audio_chk->acat = 0;/*not support*/
+ }
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c
index 5cbfdf1c4b11..a249a0e5edd0 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c
@@ -33,7 +33,7 @@
* Private functions
******************************************************************************/
-static void destruct(struct dc_sink *sink)
+static void dc_sink_destruct(struct dc_sink *sink)
{
if (sink->dc_container_id) {
kfree(sink->dc_container_id);
@@ -41,7 +41,7 @@ static void destruct(struct dc_sink *sink)
}
}
-static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init_params)
+static bool dc_sink_construct(struct dc_sink *sink, const struct dc_sink_init_data *init_params)
{
struct dc_link *link = init_params->link;
@@ -75,7 +75,7 @@ void dc_sink_retain(struct dc_sink *sink)
static void dc_sink_free(struct kref *kref)
{
struct dc_sink *sink = container_of(kref, struct dc_sink, refcount);
- destruct(sink);
+ dc_sink_destruct(sink);
kfree(sink);
}
@@ -91,7 +91,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params)
if (NULL == sink)
goto alloc_fail;
- if (false == construct(sink, init_params))
+ if (false == dc_sink_construct(sink, init_params))
goto construct_fail;
kref_init(&sink->refcount);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index bb09243758fe..6ddbb00ed37a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -27,14 +27,12 @@
#include <linux/slab.h>
#include "dm_services.h"
+#include "basics/dc_common.h"
#include "dc.h"
#include "core_types.h"
#include "resource.h"
#include "ipp.h"
#include "timing_generator.h"
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-#include "dcn10/dcn10_hw_sequencer.h"
-#endif
#define DC_LOGGER dc->ctx->logger
@@ -58,7 +56,7 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink)
}
}
-static void construct(struct dc_stream_state *stream,
+static void dc_stream_construct(struct dc_stream_state *stream,
struct dc_sink *dc_sink_data)
{
uint32_t i = 0;
@@ -108,7 +106,6 @@ static void construct(struct dc_stream_state *stream,
/* EDID CAP translation for HDMI 2.0 */
stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
memset(&stream->timing.dsc_cfg, 0, sizeof(stream->timing.dsc_cfg));
stream->timing.dsc_cfg.num_slices_h = 0;
stream->timing.dsc_cfg.num_slices_v = 0;
@@ -117,7 +114,6 @@ static void construct(struct dc_stream_state *stream,
stream->timing.dsc_cfg.linebuf_depth = 9;
stream->timing.dsc_cfg.version_minor = 2;
stream->timing.dsc_cfg.ycbcr422_simple = 0;
-#endif
update_stream_signal(stream, dc_sink_data);
@@ -129,7 +125,7 @@ static void construct(struct dc_stream_state *stream,
stream->ctx->dc_stream_id_count++;
}
-static void destruct(struct dc_stream_state *stream)
+static void dc_stream_destruct(struct dc_stream_state *stream)
{
dc_sink_release(stream->sink);
if (stream->out_transfer_func != NULL) {
@@ -147,7 +143,7 @@ static void dc_stream_free(struct kref *kref)
{
struct dc_stream_state *stream = container_of(kref, struct dc_stream_state, refcount);
- destruct(stream);
+ dc_stream_destruct(stream);
kfree(stream);
}
@@ -170,7 +166,7 @@ struct dc_stream_state *dc_create_stream_for_sink(
if (stream == NULL)
return NULL;
- construct(stream, sink);
+ dc_stream_construct(stream, sink);
kref_init(&stream->refcount);
@@ -237,7 +233,7 @@ struct dc_stream_status *dc_stream_get_status(
static void delay_cursor_until_vupdate(struct pipe_ctx *pipe_ctx, struct dc *dc)
{
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
unsigned int vupdate_line;
unsigned int lines_to_vupdate, us_to_vupdate, vpos, nvpos;
struct dc_stream_state *stream = pipe_ctx->stream;
@@ -246,7 +242,7 @@ static void delay_cursor_until_vupdate(struct pipe_ctx *pipe_ctx, struct dc *dc)
if (stream->ctx->asic_id.chip_family == FAMILY_RV &&
ASICREV_IS_RAVEN(stream->ctx->asic_id.hw_internal_rev)) {
- vupdate_line = get_vupdate_offset_from_vsync(pipe_ctx);
+ vupdate_line = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
if (!dc_stream_get_crtc_position(dc, &stream, 1, &vpos, &nvpos))
return;
@@ -272,7 +268,7 @@ bool dc_stream_set_cursor_attributes(
const struct dc_cursor_attributes *attributes)
{
int i;
- struct dc *core_dc;
+ struct dc *dc;
struct resource_context *res_ctx;
struct pipe_ctx *pipe_to_program = NULL;
@@ -290,8 +286,8 @@ bool dc_stream_set_cursor_attributes(
return false;
}
- core_dc = stream->ctx->dc;
- res_ctx = &core_dc->current_state->res_ctx;
+ dc = stream->ctx->dc;
+ res_ctx = &dc->current_state->res_ctx;
stream->cursor_attributes = *attributes;
for (i = 0; i < MAX_PIPES; i++) {
@@ -303,17 +299,17 @@ bool dc_stream_set_cursor_attributes(
if (!pipe_to_program) {
pipe_to_program = pipe_ctx;
- delay_cursor_until_vupdate(pipe_ctx, core_dc);
- core_dc->hwss.pipe_control_lock(core_dc, pipe_to_program, true);
+ delay_cursor_until_vupdate(pipe_ctx, dc);
+ dc->hwss.pipe_control_lock(dc, pipe_to_program, true);
}
- core_dc->hwss.set_cursor_attribute(pipe_ctx);
- if (core_dc->hwss.set_cursor_sdr_white_level)
- core_dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
+ dc->hwss.set_cursor_attribute(pipe_ctx);
+ if (dc->hwss.set_cursor_sdr_white_level)
+ dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
}
if (pipe_to_program)
- core_dc->hwss.pipe_control_lock(core_dc, pipe_to_program, false);
+ dc->hwss.pipe_control_lock(dc, pipe_to_program, false);
return true;
}
@@ -323,7 +319,7 @@ bool dc_stream_set_cursor_position(
const struct dc_cursor_position *position)
{
int i;
- struct dc *core_dc;
+ struct dc *dc;
struct resource_context *res_ctx;
struct pipe_ctx *pipe_to_program = NULL;
@@ -337,8 +333,8 @@ bool dc_stream_set_cursor_position(
return false;
}
- core_dc = stream->ctx->dc;
- res_ctx = &core_dc->current_state->res_ctx;
+ dc = stream->ctx->dc;
+ res_ctx = &dc->current_state->res_ctx;
stream->cursor_position = *position;
for (i = 0; i < MAX_PIPES; i++) {
@@ -354,20 +350,19 @@ bool dc_stream_set_cursor_position(
if (!pipe_to_program) {
pipe_to_program = pipe_ctx;
- delay_cursor_until_vupdate(pipe_ctx, core_dc);
- core_dc->hwss.pipe_control_lock(core_dc, pipe_to_program, true);
+ delay_cursor_until_vupdate(pipe_ctx, dc);
+ dc->hwss.pipe_control_lock(dc, pipe_to_program, true);
}
- core_dc->hwss.set_cursor_position(pipe_ctx);
+ dc->hwss.set_cursor_position(pipe_ctx);
}
if (pipe_to_program)
- core_dc->hwss.pipe_control_lock(core_dc, pipe_to_program, false);
+ dc->hwss.pipe_control_lock(dc, pipe_to_program, false);
return true;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
bool dc_stream_add_writeback(struct dc *dc,
struct dc_stream_state *stream,
struct dc_writeback_info *wb_info)
@@ -411,25 +406,30 @@ bool dc_stream_add_writeback(struct dc *dc,
stream->writeback_info[stream->num_wb_info++] = *wb_info;
}
- if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
- dm_error("DC: update_bandwidth failed!\n");
- return false;
- }
-
- /* enable writeback */
if (dc->hwss.enable_writeback) {
struct dc_stream_status *stream_status = dc_stream_get_status(stream);
struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
+ dwb->otg_inst = stream_status->primary_otg_inst;
+ }
+ if (IS_DIAG_DC(dc->ctx->dce_environment)) {
+ if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
+ dm_error("DC: update_bandwidth failed!\n");
+ return false;
+ }
- if (dwb->funcs->is_enabled(dwb)) {
- /* writeback pipe already enabled, only need to update */
- dc->hwss.update_writeback(dc, stream_status, wb_info, dc->current_state);
- } else {
- /* Enable writeback pipe from scratch*/
- dc->hwss.enable_writeback(dc, stream_status, wb_info, dc->current_state);
+ /* enable writeback */
+ if (dc->hwss.enable_writeback) {
+ struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
+
+ if (dwb->funcs->is_enabled(dwb)) {
+ /* writeback pipe already enabled, only need to update */
+ dc->hwss.update_writeback(dc, wb_info, dc->current_state);
+ } else {
+ /* Enable writeback pipe from scratch*/
+ dc->hwss.enable_writeback(dc, wb_info, dc->current_state);
+ }
}
}
-
return true;
}
@@ -468,26 +468,35 @@ bool dc_stream_remove_writeback(struct dc *dc,
}
stream->num_wb_info = j;
- /* recalculate and apply DML parameters */
- if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
- dm_error("DC: update_bandwidth failed!\n");
- return false;
- }
-
- /* disable writeback */
- if (dc->hwss.disable_writeback)
- dc->hwss.disable_writeback(dc, dwb_pipe_inst);
+ if (IS_DIAG_DC(dc->ctx->dce_environment)) {
+ /* recalculate and apply DML parameters */
+ if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
+ dm_error("DC: update_bandwidth failed!\n");
+ return false;
+ }
+ /* disable writeback */
+ if (dc->hwss.disable_writeback)
+ dc->hwss.disable_writeback(dc, dwb_pipe_inst);
+ }
return true;
}
-#endif
+bool dc_stream_warmup_writeback(struct dc *dc,
+ int num_dwb,
+ struct dc_writeback_info *wb_info)
+{
+ if (dc->hwss.mmhubbub_warmup)
+ return dc->hwss.mmhubbub_warmup(dc, num_dwb, wb_info);
+ else
+ return false;
+}
uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
{
uint8_t i;
- struct dc *core_dc = stream->ctx->dc;
+ struct dc *dc = stream->ctx->dc;
struct resource_context *res_ctx =
- &core_dc->current_state->res_ctx;
+ &dc->current_state->res_ctx;
for (i = 0; i < MAX_PIPES; i++) {
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
@@ -544,9 +553,9 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
{
uint8_t i;
bool ret = false;
- struct dc *core_dc = stream->ctx->dc;
+ struct dc *dc = stream->ctx->dc;
struct resource_context *res_ctx =
- &core_dc->current_state->res_ctx;
+ &dc->current_state->res_ctx;
for (i = 0; i < MAX_PIPES; i++) {
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
@@ -567,10 +576,8 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
return ret;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream)
{
- bool status = true;
struct pipe_ctx *pipe = NULL;
int i;
@@ -586,8 +593,7 @@ bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream)
if (i == MAX_PIPES)
return true;
- status = dc->hwss.dmdata_status_done(pipe);
- return status;
+ return dc->hwss.dmdata_status_done(pipe);
}
bool dc_stream_set_dynamic_metadata(struct dc *dc,
@@ -630,7 +636,6 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc,
return true;
}
-#endif
void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
{
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
index b9d6a5bd8522..ea1229a3e2b2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
@@ -37,7 +37,7 @@
/*******************************************************************************
* Private functions
******************************************************************************/
-static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state)
+static void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state)
{
plane_state->ctx = ctx;
@@ -50,7 +50,6 @@ static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state
plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
plane_state->in_transfer_func->ctx = ctx;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
plane_state->in_shaper_func = dc_create_transfer_func();
if (plane_state->in_shaper_func != NULL) {
plane_state->in_shaper_func->type = TF_TYPE_BYPASS;
@@ -67,10 +66,9 @@ static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state
plane_state->blend_tf->ctx = ctx;
}
-#endif
}
-static void destruct(struct dc_plane_state *plane_state)
+static void dc_plane_destruct(struct dc_plane_state *plane_state)
{
if (plane_state->gamma_correction != NULL) {
dc_gamma_release(&plane_state->gamma_correction);
@@ -80,7 +78,6 @@ static void destruct(struct dc_plane_state *plane_state)
plane_state->in_transfer_func);
plane_state->in_transfer_func = NULL;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
if (plane_state->in_shaper_func != NULL) {
dc_transfer_func_release(
plane_state->in_shaper_func);
@@ -97,7 +94,6 @@ static void destruct(struct dc_plane_state *plane_state)
plane_state->blend_tf = NULL;
}
-#endif
}
/*******************************************************************************
@@ -112,16 +108,14 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state,
struct dc_plane_state *dc_create_plane_state(struct dc *dc)
{
- struct dc *core_dc = dc;
-
struct dc_plane_state *plane_state = kvzalloc(sizeof(*plane_state),
- GFP_KERNEL);
+ GFP_KERNEL);
if (NULL == plane_state)
return NULL;
kref_init(&plane_state->refcount);
- construct(core_dc->ctx, plane_state);
+ dc_plane_construct(dc->ctx, plane_state);
return plane_state;
}
@@ -141,7 +135,7 @@ const struct dc_plane_status *dc_plane_get_status(
const struct dc_plane_state *plane_state)
{
const struct dc_plane_status *plane_status;
- struct dc *core_dc;
+ struct dc *dc;
int i;
if (!plane_state ||
@@ -152,15 +146,15 @@ const struct dc_plane_status *dc_plane_get_status(
}
plane_status = &plane_state->status;
- core_dc = plane_state->ctx->dc;
+ dc = plane_state->ctx->dc;
- if (core_dc->current_state == NULL)
+ if (dc->current_state == NULL)
return NULL;
/* Find the current plane state and set its pending bit to false */
- for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx =
- &core_dc->current_state->res_ctx.pipe_ctx[i];
+ &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx->plane_state != plane_state)
continue;
@@ -170,14 +164,14 @@ const struct dc_plane_status *dc_plane_get_status(
break;
}
- for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx =
- &core_dc->current_state->res_ctx.pipe_ctx[i];
+ &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx->plane_state != plane_state)
continue;
- core_dc->hwss.update_pending_status(pipe_ctx);
+ dc->hwss.update_pending_status(pipe_ctx);
}
return plane_status;
@@ -191,7 +185,7 @@ void dc_plane_state_retain(struct dc_plane_state *plane_state)
static void dc_plane_state_free(struct kref *kref)
{
struct dc_plane_state *plane_state = container_of(kref, struct dc_plane_state, refcount);
- destruct(plane_state);
+ dc_plane_destruct(plane_state);
kvfree(plane_state);
}
@@ -262,7 +256,6 @@ alloc_fail:
return NULL;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
static void dc_3dlut_func_free(struct kref *kref)
{
struct dc_3dlut *lut = container_of(kref, struct dc_3dlut, refcount);
@@ -296,6 +289,5 @@ void dc_3dlut_func_retain(struct dc_3dlut *lut)
{
kref_get(&lut->refcount);
}
-#endif