summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c247
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_debug.c35
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c159
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c179
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c26
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c33
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c81
8 files changed, 509 insertions, 258 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 35e84ed031de..63a3d468939a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -29,6 +29,7 @@
#include "core_status.h"
#include "core_types.h"
#include "hw_sequencer.h"
+#include "dce/dce_hwseq.h"
#include "resource.h"
@@ -38,8 +39,10 @@
#include "bios_parser_interface.h"
#include "include/irq_service_interface.h"
#include "transform.h"
+#include "dmcu.h"
#include "dpp.h"
#include "timing_generator.h"
+#include "abm.h"
#include "virtual/virtual_link_encoder.h"
#include "link_hwss.h"
@@ -49,6 +52,8 @@
#include "dm_helpers.h"
#include "mem_input.h"
#include "hubp.h"
+#define DC_LOGGER \
+ dc->ctx->logger
/*******************************************************************************
@@ -214,6 +219,130 @@ bool dc_stream_get_crtc_position(struct dc *dc,
return ret;
}
+/**
+ * dc_stream_configure_crc: Configure CRC capture for the given stream.
+ * @dc: DC Object
+ * @stream: The stream to configure CRC on.
+ * @enable: Enable CRC if true, disable otherwise.
+ * @continuous: Capture CRC on every frame if true. Otherwise, only capture
+ * once.
+ *
+ * By default, only CRC0 is configured, and the entire frame is used to
+ * calculate the crc.
+ */
+bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
+ bool enable, bool continuous)
+{
+ int i;
+ struct pipe_ctx *pipe;
+ struct crc_params param;
+ struct timing_generator *tg;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe->stream == stream)
+ break;
+ }
+ /* Stream not found */
+ if (i == MAX_PIPES)
+ return false;
+
+ /* Always capture the full frame */
+ param.windowa_x_start = 0;
+ param.windowa_y_start = 0;
+ param.windowa_x_end = pipe->stream->timing.h_addressable;
+ param.windowa_y_end = pipe->stream->timing.v_addressable;
+ param.windowb_x_start = 0;
+ param.windowb_y_start = 0;
+ param.windowb_x_end = pipe->stream->timing.h_addressable;
+ param.windowb_y_end = pipe->stream->timing.v_addressable;
+
+ /* Default to the union of both windows */
+ param.selection = UNION_WINDOW_A_B;
+ param.continuous_mode = continuous;
+ param.enable = enable;
+
+ tg = pipe->stream_res.tg;
+
+ /* Only call if supported */
+ if (tg->funcs->configure_crc)
+ return tg->funcs->configure_crc(tg, &param);
+ DC_LOG_WARNING("CRC capture not supported.");
+ return false;
+}
+
+/**
+ * dc_stream_get_crc: Get CRC values for the given stream.
+ * @dc: DC object
+ * @stream: The DC stream state of the stream to get CRCs from.
+ * @r_cr, g_y, b_cb: CRC values for the three channels are stored here.
+ *
+ * dc_stream_configure_crc needs to be called beforehand to enable CRCs.
+ * Return false if stream is not found, or if CRCs are not enabled.
+ */
+bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream,
+ uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
+{
+ int i;
+ struct pipe_ctx *pipe;
+ struct timing_generator *tg;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe->stream == stream)
+ break;
+ }
+ /* Stream not found */
+ if (i == MAX_PIPES)
+ return false;
+
+ tg = pipe->stream_res.tg;
+
+ if (tg->funcs->get_crc)
+ return tg->funcs->get_crc(tg, r_cr, g_y, b_cb);
+ DC_LOG_WARNING("CRC capture not supported.");
+ return false;
+}
+
+void dc_stream_set_dither_option(struct dc_stream_state *stream,
+ enum dc_dither_option option)
+{
+ struct bit_depth_reduction_params params;
+ struct dc_link *link = stream->status.link;
+ struct pipe_ctx *pipes = NULL;
+ int i;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ if (link->dc->current_state->res_ctx.pipe_ctx[i].stream ==
+ stream) {
+ pipes = &link->dc->current_state->res_ctx.pipe_ctx[i];
+ break;
+ }
+ }
+
+ if (!pipes)
+ return;
+ if (option > DITHER_OPTION_MAX)
+ return;
+
+ stream->dither_option = option;
+
+ memset(&params, 0, sizeof(params));
+ resource_build_bit_depth_reduction_params(stream, &params);
+ stream->bit_depth_params = params;
+
+ if (pipes->plane_res.xfm &&
+ pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth) {
+ pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
+ pipes->plane_res.xfm,
+ pipes->plane_res.scl_data.lb_params.depth,
+ &stream->bit_depth_params);
+ }
+
+ pipes->stream_res.opp->funcs->
+ opp_program_bit_depth_reduction(pipes->stream_res.opp, &params);
+}
+
void dc_stream_set_static_screen_events(struct dc *dc,
struct dc_stream_state **streams,
int num_streams,
@@ -359,9 +488,6 @@ static bool construct(struct dc *dc,
dc_version = resource_parse_asic_id(init_params->asic_id);
dc_ctx->dce_version = dc_version;
-#if defined(CONFIG_DRM_AMD_DC_FBC)
- dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr;
-#endif
/* Resource should construct all asic specific resources.
* This should be the only place where we need to parse the asic id
*/
@@ -487,10 +613,15 @@ struct dc *dc_create(const struct dc_init_data *init_params)
dc->caps.max_audios = dc->res_pool->audio_count;
dc->caps.linear_pitch_alignment = 64;
+ /* 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->config = init_params->flags;
- dm_logger_write(dc->ctx->logger, LOG_DC,
- "Display Core initialized\n");
+ DC_LOG_DC("Display Core initialized\n");
/* TODO: missing feature to be enabled */
@@ -524,11 +655,13 @@ static void enable_timing_multisync(
if (!ctx->res_ctx.pipe_ctx[i].stream ||
!ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.enabled)
continue;
+ if (ctx->res_ctx.pipe_ctx[i].stream == ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.event_source)
+ continue;
multisync_pipes[multisync_count] = &ctx->res_ctx.pipe_ctx[i];
multisync_count++;
}
- if (multisync_count > 1) {
+ if (multisync_count > 0) {
dc->hwss.enable_per_frame_crtc_position_reset(
dc, multisync_count, multisync_pipes);
}
@@ -650,7 +783,6 @@ bool dc_enable_stereo(
return ret;
}
-
/*
* Applies given context to HW and copy it into current context.
* It's up to the user to release the src context afterwards.
@@ -669,7 +801,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc_streams[i] = context->streams[i];
if (!dcb->funcs->is_accelerated_mode(dcb))
- dc->hwss.enable_accelerated_mode(dc);
+ dc->hwss.enable_accelerated_mode(dc, context);
+
+ dc->hwss.set_bandwidth(dc, context, false);
/* re-program planes for existing stream, in case we need to
* free up plane resource for later use
@@ -739,6 +873,9 @@ 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);
+ /* pplib is notified if disp_num changed */
+ dc->hwss.set_bandwidth(dc, context, true);
+
dc_release_state(dc->current_state);
dc->current_state = context;
@@ -758,7 +895,7 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context)
if (false == context_changed(dc, context))
return DC_OK;
- dm_logger_write(dc->ctx->logger, LOG_DC, "%s: %d streams\n",
+ DC_LOG_DC("%s: %d streams\n",
__func__, context->stream_count);
for (i = 0; i < context->stream_count; i++) {
@@ -979,6 +1116,9 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
if (u->plane_info->rotation != u->surface->rotation)
update_flags->bits.rotation_change = 1;
+ if (u->plane_info->format != u->surface->format)
+ update_flags->bits.pixel_format_change = 1;
+
if (u->plane_info->stereo_format != u->surface->stereo_format)
update_flags->bits.stereo_format_change = 1;
@@ -997,6 +1137,9 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
*/
update_flags->bits.bpp_change = 1;
+ if (u->gamma && dce_use_lut(u->plane_info->format))
+ update_flags->bits.gamma_change = 1;
+
if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info,
sizeof(union dc_tiling_info)) != 0) {
update_flags->bits.swizzle_change = 1;
@@ -1012,8 +1155,11 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
if (update_flags->bits.rotation_change
|| update_flags->bits.stereo_format_change
+ || update_flags->bits.pixel_format_change
+ || update_flags->bits.gamma_change
|| update_flags->bits.bpp_change
- || update_flags->bits.bandwidth_change)
+ || update_flags->bits.bandwidth_change
+ || update_flags->bits.output_tf_change)
return UPDATE_TYPE_FULL;
return UPDATE_TYPE_MED;
@@ -1092,12 +1238,12 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
elevate_update_type(&overall_type, type);
if (u->in_transfer_func)
- update_flags->bits.in_transfer_func = 1;
+ update_flags->bits.in_transfer_func_change = 1;
if (u->input_csc_color_matrix)
update_flags->bits.input_csc_change = 1;
- if (update_flags->bits.in_transfer_func
+ if (update_flags->bits.in_transfer_func_change
|| update_flags->bits.input_csc_change) {
type = UPDATE_TYPE_MED;
elevate_update_type(&overall_type, type);
@@ -1183,6 +1329,7 @@ static void commit_planes_for_stream(struct dc *dc,
struct dc_state *context)
{
int i, j;
+ struct pipe_ctx *top_pipe_to_program = NULL;
if (update_type == UPDATE_TYPE_FULL) {
dc->hwss.set_bandwidth(dc, context, false);
@@ -1202,39 +1349,64 @@ static void commit_planes_for_stream(struct dc *dc,
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
- if (update_type == UPDATE_TYPE_FAST || !pipe_ctx->plane_state)
- continue;
-
if (!pipe_ctx->top_pipe &&
- pipe_ctx->stream &&
- pipe_ctx->stream == stream) {
- struct dc_stream_status *stream_status =
+ pipe_ctx->stream &&
+ pipe_ctx->stream == stream) {
+ struct dc_stream_status *stream_status = NULL;
+
+ top_pipe_to_program = pipe_ctx;
+
+ if (update_type == UPDATE_TYPE_FAST || !pipe_ctx->plane_state)
+ continue;
+
+ stream_status =
stream_get_status(context, pipe_ctx->stream);
dc->hwss.apply_ctx_for_surface(
dc, pipe_ctx->stream, stream_status->plane_count, context);
+
+ if (stream_update && stream_update->abm_level && pipe_ctx->stream_res.abm) {
+ if (pipe_ctx->stream_res.tg->funcs->is_blanked) {
+ // if otg funcs defined check if blanked before programming
+ if (!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
+ pipe_ctx->stream_res.abm->funcs->set_abm_level(
+ pipe_ctx->stream_res.abm, stream->abm_level);
+ } else
+ pipe_ctx->stream_res.abm->funcs->set_abm_level(
+ pipe_ctx->stream_res.abm, stream->abm_level);
+ }
}
}
if (update_type == UPDATE_TYPE_FULL)
context_timing_trace(dc, &context->res_ctx);
- /* Perform requested Updates */
- for (i = 0; i < surface_count; i++) {
- struct dc_plane_state *plane_state = srf_updates[i].surface;
+ /* Lock the top pipe while updating plane addrs, since freesync requires
+ * plane addr update event triggers to be synchronized.
+ * top_pipe_to_program is expected to never be NULL
+ */
+ if (update_type == UPDATE_TYPE_FAST) {
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
- for (j = 0; j < dc->res_pool->pipe_count; j++) {
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+ /* Perform requested Updates */
+ for (i = 0; i < surface_count; i++) {
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
- if (pipe_ctx->stream != stream)
- continue;
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
- if (pipe_ctx->plane_state != plane_state)
- continue;
+ if (pipe_ctx->stream != stream)
+ continue;
+
+ if (pipe_ctx->plane_state != plane_state)
+ continue;
- if (update_type == UPDATE_TYPE_FAST && srf_updates[i].flip_addr)
+ if (srf_updates[i].flip_addr)
dc->hwss.update_plane_addr(dc, pipe_ctx);
+ }
}
+
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
}
if (stream && stream_update && update_type > UPDATE_TYPE_FAST)
@@ -1358,13 +1530,13 @@ enum dc_irq_source dc_interrupt_to_irq_source(
return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id);
}
-void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)
+bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)
{
if (dc == NULL)
- return;
+ return false;
- dal_irq_service_set(dc->res_pool->irqs, src, enable);
+ return dal_irq_service_set(dc->res_pool->irqs, src, enable);
}
void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
@@ -1487,12 +1659,17 @@ struct dc_sink *dc_link_add_remote_sink(
&dc_sink->dc_edid,
&dc_sink->edid_caps);
- if (edid_status != EDID_OK)
- goto fail;
+ /*
+ * Treat device as no EDID device if EDID
+ * parsing fails
+ */
+ if (edid_status != EDID_OK) {
+ dc_sink->dc_edid.length = 0;
+ dm_error("Bad EDID, status%d!\n", edid_status);
+ }
return dc_sink;
-fail:
- dc_link_remove_remote_sink(link, dc_sink);
+
fail_add_sink:
dc_sink_release(dc_sink);
return NULL;
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 1babac07bcc9..5a552cb3f8a7 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c
@@ -36,26 +36,22 @@
#include "hw_sequencer.h"
#include "resource.h"
+#define DC_LOGGER \
+ logger
#define SURFACE_TRACE(...) do {\
if (dc->debug.surface_trace) \
- dm_logger_write(logger, \
- LOG_IF_TRACE, \
- ##__VA_ARGS__); \
+ DC_LOG_IF_TRACE(__VA_ARGS__); \
} while (0)
#define TIMING_TRACE(...) do {\
if (dc->debug.timing_trace) \
- dm_logger_write(logger, \
- LOG_SYNC, \
- ##__VA_ARGS__); \
+ DC_LOG_SYNC(__VA_ARGS__); \
} while (0)
#define CLOCK_TRACE(...) do {\
if (dc->debug.clock_trace) \
- dm_logger_write(logger, \
- LOG_BANDWIDTH_CALCS, \
- ##__VA_ARGS__); \
+ DC_LOG_BANDWIDTH_CALCS(__VA_ARGS__); \
} while (0)
void pre_surface_trace(
@@ -361,25 +357,20 @@ void context_clock_trace(
struct dc *core_dc = dc;
struct dal_logger *logger = core_dc->ctx->logger;
- CLOCK_TRACE("Current: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n"
- "dcfclk_deep_sleep_khz:%d fclk_khz:%d\n"
- "dram_ccm_us:%d min_active_dram_ccm_us:%d\n",
+ 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",
context->bw.dcn.calc_clk.dispclk_khz,
- context->bw.dcn.calc_clk.dppclk_div,
+ context->bw.dcn.calc_clk.dppclk_khz,
context->bw.dcn.calc_clk.dcfclk_khz,
context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz,
context->bw.dcn.calc_clk.fclk_khz,
- context->bw.dcn.calc_clk.dram_ccm_us,
- context->bw.dcn.calc_clk.min_active_dram_ccm_us);
- CLOCK_TRACE("Calculated: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n"
- "dcfclk_deep_sleep_khz:%d fclk_khz:%d\n"
- "dram_ccm_us:%d min_active_dram_ccm_us:%d\n",
+ context->bw.dcn.calc_clk.socclk_khz);
+ CLOCK_TRACE("Calculated: dispclk_khz:%d max_dppclk_khz:%d dcfclk_khz:%d\n"
+ "dcfclk_deep_sleep_khz:%d fclk_khz:%d socclk_khz:%d\n",
context->bw.dcn.calc_clk.dispclk_khz,
- context->bw.dcn.calc_clk.dppclk_div,
+ context->bw.dcn.calc_clk.dppclk_khz,
context->bw.dcn.calc_clk.dcfclk_khz,
context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz,
- context->bw.dcn.calc_clk.fclk_khz,
- context->bw.dcn.calc_clk.dram_ccm_us,
- context->bw.dcn.calc_clk.min_active_dram_ccm_us);
+ context->bw.dcn.calc_clk.fclk_khz);
#endif
}
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 a37428271573..eeb04471b2f5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -45,9 +45,11 @@
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_enum.h"
#include "dce/dce_11_0_sh_mask.h"
+#define DC_LOGGER \
+ dc_ctx->logger
#define LINK_INFO(...) \
- dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \
+ DC_LOG_HW_HOTPLUG( \
__VA_ARGS__)
/*******************************************************************************
@@ -126,6 +128,8 @@ static bool program_hpd_filter(
int delay_on_connect_in_ms = 0;
int delay_on_disconnect_in_ms = 0;
+ if (link->is_hpd_filter_disabled)
+ return false;
/* Verify feature is supported */
switch (link->connector_signal) {
case SIGNAL_TYPE_DVI_SINGLE_LINK:
@@ -464,7 +468,7 @@ static void link_disconnect_sink(struct dc_link *link)
link->dpcd_sink_count = 0;
}
-static void detect_dp(
+static bool detect_dp(
struct dc_link *link,
struct display_sink_capability *sink_caps,
bool *converter_disable_audio,
@@ -478,7 +482,8 @@ static void detect_dp(
if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
- detect_dp_sink_caps(link);
+ if (!detect_dp_sink_caps(link))
+ return false;
if (is_mst_supported(link)) {
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
@@ -529,7 +534,7 @@ static void detect_dp(
* active dongle unplug processing for short irq
*/
link_disconnect_sink(link);
- return;
+ return true;
}
if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER)
@@ -541,6 +546,8 @@ static void detect_dp(
sink_caps,
audio_support);
}
+
+ return true;
}
bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
@@ -604,11 +611,12 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
}
case SIGNAL_TYPE_DISPLAY_PORT: {
- detect_dp(
+ if (!detect_dp(
link,
&sink_caps,
&converter_disable_audio,
- aud_support, reason);
+ aud_support, reason))
+ return false;
/* Active dongle downstream unplug */
if (link->type == dc_connection_active_dongle
@@ -671,14 +679,10 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
switch (edid_status) {
case EDID_BAD_CHECKSUM:
- dm_logger_write(link->ctx->logger, LOG_ERROR,
- "EDID checksum invalid.\n");
+ DC_LOG_ERROR("EDID checksum invalid.\n");
break;
case EDID_NO_RESPONSE:
- dm_logger_write(link->ctx->logger, LOG_ERROR,
- "No EDID read.\n");
- return false;
-
+ DC_LOG_ERROR("No EDID read.\n");
default:
break;
}
@@ -708,8 +712,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
"%s: [Block %d] ", sink->edid_caps.display_name, i);
}
- dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER,
- "%s: "
+ DC_LOG_DETECTION_EDID_PARSER("%s: "
"manufacturer_id = %X, "
"product_id = %X, "
"serial_number = %X, "
@@ -729,8 +732,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
sink->edid_caps.audio_mode_count);
for (i = 0; i < sink->edid_caps.audio_mode_count; i++) {
- dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER,
- "%s: mode number = %d, "
+ DC_LOG_DETECTION_EDID_PARSER("%s: mode number = %d, "
"format_code = %d, "
"channel_count = %d, "
"sample_rate = %d, "
@@ -980,8 +982,7 @@ static bool construct(
}
break;
default:
- dm_logger_write(dc_ctx->logger, LOG_WARNING,
- "Unsupported Connector type:%d!\n", link->link_id.id);
+ DC_LOG_WARNING("Unsupported Connector type:%d!\n", link->link_id.id);
goto create_fail;
}
@@ -1134,7 +1135,7 @@ static void dpcd_configure_panel_mode(
{
union dpcd_edp_config edp_config_set;
bool panel_mode_edp = false;
-
+ struct dc_context *dc_ctx = link->ctx;
memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
if (DP_PANEL_MODE_DEFAULT != panel_mode) {
@@ -1171,8 +1172,7 @@ static void dpcd_configure_panel_mode(
ASSERT(result == DDC_RESULT_SUCESSFULL);
}
}
- dm_logger_write(link->ctx->logger, LOG_DETECTION_DP_CAPS,
- "Link: %d eDP panel mode supported: %d "
+ DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
"eDP panel mode enabled: %d \n",
link->link_index,
link->dpcd_caps.panel_mode_edp,
@@ -1248,6 +1248,12 @@ static enum dc_status enable_link_dp(
pipe_ctx->clock_source->id,
&link_settings);
+ if (stream->sink->edid_caps.panel_patch.dppowerup_delay > 0) {
+ int delay_dp_power_up_in_ms = stream->sink->edid_caps.panel_patch.dppowerup_delay;
+
+ msleep(delay_dp_power_up_in_ms);
+ }
+
panel_mode = dp_get_panel_mode(link);
dpcd_configure_panel_mode(link, panel_mode);
@@ -1279,13 +1285,12 @@ static enum dc_status enable_link_edp(
enum dc_status status;
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->sink->link;
-
+ /*in case it is not on*/
link->dc->hwss.edp_power_control(link, true);
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
status = enable_link_dp(state, pipe_ctx);
- link->dc->hwss.edp_backlight_control(link, true);
return status;
}
@@ -1302,6 +1307,9 @@ static enum dc_status enable_link_dp_mst(
if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
return DC_OK;
+ /* clear payload table */
+ dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
+
/* set the sink to MST mode before enabling the link */
dp_enable_mst_on_sink(link, true);
@@ -1749,8 +1757,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
link->link_enc,
pipe_ctx->clock_source->id,
display_color_depth,
- pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A,
- pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK,
+ pipe_ctx->stream->signal,
stream->phy_pix_clk);
if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
@@ -1788,9 +1795,21 @@ static enum dc_status enable_link(
}
if (pipe_ctx->stream_res.audio && status == DC_OK) {
+ struct dc *core_dc = pipe_ctx->stream->ctx->dc;
/* notify audio driver for audio modes of monitor */
+ struct pp_smu_funcs_rv *pp_smu = core_dc->res_pool->pp_smu;
+ unsigned int i, num_audio = 1;
+ for (i = 0; i < MAX_PIPES; i++) {
+ /*current_state not updated yet*/
+ if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL)
+ num_audio++;
+ }
+
pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
+ if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+ /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
+ pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
/* un-mute audio */
/* TODO: audio should be per stream rather than per link */
pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
@@ -1931,6 +1950,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level,
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_context *dc_ctx = link->ctx;
unsigned int controller_id = 0;
bool use_smooth_brightness = true;
int i;
@@ -1940,10 +1960,16 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level,
(abm->funcs->set_backlight_level == NULL))
return false;
+ if (stream) {
+ if (stream->bl_pwm_level == 0)
+ frame_ramp = 0;
+
+ ((struct dc_stream_state *)stream)->bl_pwm_level = level;
+ }
+
use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
- dm_logger_write(link->ctx->logger, LOG_BACKLIGHT,
- "New Backlight level: %d (0x%X)\n", level, level);
+ DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", level, level);
if (dc_is_embedded_signal(link->connector_signal)) {
if (stream != NULL) {
@@ -2110,6 +2136,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
+ struct dc_context *dc_ctx = link->ctx;
uint8_t i;
/* enable_link_dp_mst already check link->enabled_stream_count
@@ -2127,21 +2154,18 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
link, pipe_ctx->stream_res.stream_enc, &proposed_table);
}
else
- dm_logger_write(link->ctx->logger, LOG_WARNING,
- "Failed to update"
+ DC_LOG_WARNING("Failed to update"
"MST allocation table for"
"pipe idx:%d\n",
pipe_ctx->pipe_idx);
- dm_logger_write(link->ctx->logger, LOG_MST,
- "%s "
+ DC_LOG_MST("%s "
"stream_count: %d: \n ",
__func__,
link->mst_stream_alloc_table.stream_count);
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
- dm_logger_write(link->ctx->logger, LOG_MST,
- "stream_enc[%d]: 0x%x "
+ DC_LOG_MST("stream_enc[%d]: 0x%x "
"stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n",
i,
@@ -2192,6 +2216,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0);
uint8_t i;
bool mst_mode = (link->type == dc_connection_mst_branch);
+ struct dc_context *dc_ctx = link->ctx;
/* deallocate_mst_payload is called before disable link. When mode or
* disable/enable monitor, new stream is created which is not in link
@@ -2217,23 +2242,20 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
link, pipe_ctx->stream_res.stream_enc, &proposed_table);
}
else {
- dm_logger_write(link->ctx->logger, LOG_WARNING,
- "Failed to update"
+ DC_LOG_WARNING("Failed to update"
"MST allocation table for"
"pipe idx:%d\n",
pipe_ctx->pipe_idx);
}
}
- dm_logger_write(link->ctx->logger, LOG_MST,
- "%s"
+ DC_LOG_MST("%s"
"stream_count: %d: ",
__func__,
link->mst_stream_alloc_table.stream_count);
for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
- dm_logger_write(link->ctx->logger, LOG_MST,
- "stream_enc[%d]: 0x%x "
+ DC_LOG_MST("stream_enc[%d]: 0x%x "
"stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n",
i,
@@ -2267,12 +2289,24 @@ void core_link_enable_stream(
struct pipe_ctx *pipe_ctx)
{
struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+ struct dc_context *dc_ctx = pipe_ctx->stream->ctx;
+ enum dc_status status;
+
+ /* eDP lit up by bios already, no need to enable again. */
+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
+ core_dc->apply_edp_fast_boot_optimization) {
+ core_dc->apply_edp_fast_boot_optimization = false;
+ pipe_ctx->stream->dpms_off = false;
+ return;
+ }
+
+ if (pipe_ctx->stream->dpms_off)
+ return;
- enum dc_status status = enable_link(state, pipe_ctx);
+ status = enable_link(state, pipe_ctx);
if (status != DC_OK) {
- dm_logger_write(pipe_ctx->stream->ctx->logger,
- LOG_WARNING, "enabling link %u failed: %d\n",
+ DC_LOG_WARNING("enabling link %u failed: %d\n",
pipe_ctx->stream->sink->link->link_index,
status);
@@ -2298,9 +2332,8 @@ void core_link_enable_stream(
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
allocate_mst_payload(pipe_ctx);
- if (dc_is_dp_signal(pipe_ctx->stream->signal))
- core_dc->hwss.unblank_stream(pipe_ctx,
- &pipe_ctx->stream->sink->link->cur_link_settings);
+ core_dc->hwss.unblank_stream(pipe_ctx,
+ &pipe_ctx->stream->sink->link->cur_link_settings);
}
void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
@@ -2310,8 +2343,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
deallocate_mst_payload(pipe_ctx);
- if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP)
- core_dc->hwss.edp_backlight_control(pipe_ctx->stream->sink->link, false);
+ core_dc->hwss.blank_stream(pipe_ctx);
core_dc->hwss.disable_stream(pipe_ctx, option);
@@ -2328,3 +2360,36 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
core_dc->hwss.set_avmute(pipe_ctx, enable);
}
+void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
+{
+ struct gpio *hpd;
+
+ if (enable) {
+ link->is_hpd_filter_disabled = false;
+ program_hpd_filter(link);
+ } else {
+ link->is_hpd_filter_disabled = true;
+ /* Obtain HPD handle */
+ hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
+
+ if (!hpd)
+ return;
+
+ /* Setup HPD filtering */
+ if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
+ struct gpio_hpd_config config;
+
+ config.delay_on_connect = 0;
+ config.delay_on_disconnect = 0;
+
+ dal_irq_setup_hpd_filter(hpd, &config);
+
+ dal_gpio_close(hpd);
+ } else {
+ ASSERT_CRITICAL(false);
+ }
+ /* Release HPD handle */
+ dal_gpio_destroy_irq(&hpd);
+ }
+}
+
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 d5294798b0a5..49c2face1e7a 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
@@ -629,7 +629,7 @@ bool dal_ddc_service_query_ddc_data(
return ret;
}
-enum ddc_result dal_ddc_service_read_dpcd_data(
+ssize_t dal_ddc_service_read_dpcd_data(
struct ddc_service *ddc,
bool i2c,
enum i2c_mot_mode mot,
@@ -660,8 +660,9 @@ enum ddc_result dal_ddc_service_read_dpcd_data(
if (dal_i2caux_submit_aux_command(
ddc->ctx->i2caux,
ddc->ddc_pin,
- &command))
- return DDC_RESULT_SUCESSFULL;
+ &command)) {
+ return (ssize_t)command.payloads->length;
+ }
return DDC_RESULT_FAILED_OPERATION;
}
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 61e8c3e02d16..3b5053570229 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
@@ -11,6 +11,8 @@
#include "dpcd_defs.h"
#include "resource.h"
+#define DC_LOGGER \
+ link->ctx->logger
/* maximum pre emphasis level allowed for each voltage swing level*/
static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = {
@@ -63,8 +65,7 @@ static void wait_for_training_aux_rd_interval(
udelay(default_wait_in_micro_secs);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s:\n wait = %d\n",
+ DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
__func__,
default_wait_in_micro_secs);
}
@@ -79,8 +80,7 @@ static void dpcd_set_training_pattern(
&dpcd_pattern.raw,
1);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s\n %x pattern = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
__func__,
DP_TRAINING_PATTERN_SET,
dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
@@ -116,8 +116,7 @@ static void dpcd_set_link_settings(
core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
&downspread.raw, sizeof(downspread));
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
__func__,
DP_LINK_BW_SET,
lt_settings->link_settings.link_rate,
@@ -151,8 +150,7 @@ static enum dpcd_training_patterns
break;
default:
ASSERT(0);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s: Invalid HW Training pattern: %d\n",
+ DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
__func__, pattern);
break;
}
@@ -184,8 +182,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
= dpcd_pattern.raw;
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s\n %x pattern = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
__func__,
DP_TRAINING_PATTERN_SET,
dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
@@ -219,8 +216,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
dpcd_lane,
size_in_bytes);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s:\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
+ 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,
@@ -456,14 +452,12 @@ static void get_lane_status_and_drive_settings(
ln_status_updated->raw = dpcd_buf[2];
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
+ 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]);
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
+ DC_LOG_HW_LINK_TRAINING("%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
__func__,
DP_ADJUST_REQUEST_LANE0_1,
dpcd_buf[4],
@@ -556,8 +550,7 @@ static void dpcd_set_lane_settings(
}
*/
- dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING,
- "%s\n %x VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
+ 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,
@@ -669,16 +662,14 @@ static bool perform_post_lt_adj_req_sequence(
}
if (!req_drv_setting_changed) {
- dm_logger_write(link->ctx->logger, LOG_WARNING,
- "%s: Post Link Training Adjust Request Timed out\n",
+ DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
__func__);
ASSERT(0);
return true;
}
}
- dm_logger_write(link->ctx->logger, LOG_WARNING,
- "%s: Post Link Training Adjust Request limit reached\n",
+ DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
__func__);
ASSERT(0);
@@ -709,6 +700,22 @@ static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link)
return HW_DP_TRAINING_PATTERN_2;
}
+static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
+ union lane_status *dpcd_lane_status)
+{
+ enum link_training_result result = LINK_TRAINING_SUCCESS;
+
+ if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE0;
+ else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE1;
+ else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE23;
+ else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE23;
+ return result;
+}
+
static enum link_training_result perform_channel_equalization_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
@@ -718,7 +725,7 @@ static enum link_training_result perform_channel_equalization_sequence(
uint32_t retries_ch_eq;
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}}};;
+ union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};
hw_tr_pattern = get_supported_tp(link);
@@ -771,7 +778,7 @@ static enum link_training_result perform_channel_equalization_sequence(
}
-static bool perform_clock_recovery_sequence(
+static enum link_training_result perform_clock_recovery_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
{
@@ -846,11 +853,11 @@ static bool perform_clock_recovery_sequence(
/* 5. check CR done*/
if (is_cr_done(lane_count, dpcd_lane_status))
- return true;
+ return LINK_TRAINING_SUCCESS;
/* 6. max VS reached*/
if (is_max_vs_reached(lt_settings))
- return false;
+ break;
/* 7. same voltage*/
/* Note: VS same for all lanes,
@@ -869,20 +876,19 @@ static bool perform_clock_recovery_sequence(
if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
ASSERT(0);
- dm_logger_write(link->ctx->logger, LOG_ERROR,
- "%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
+ DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
__func__,
LINK_TRAINING_MAX_CR_RETRY);
}
- return false;
+ return get_cr_failure(lane_count, dpcd_lane_status);
}
-static inline bool perform_link_training_int(
+static inline enum link_training_result perform_link_training_int(
struct dc_link *link,
struct link_training_settings *lt_settings,
- bool status)
+ enum link_training_result status)
{
union lane_count_set lane_count_set = { {0} };
union dpcd_training_pattern dpcd_pattern = { {0} };
@@ -903,9 +909,9 @@ static inline bool perform_link_training_int(
get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4)
return status;
- if (status &&
+ if (status == LINK_TRAINING_SUCCESS &&
perform_post_lt_adj_req_sequence(link, lt_settings) == false)
- status = false;
+ status = LINK_TRAINING_LQA_FAIL;
lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
lane_count_set.bits.ENHANCED_FRAMING = 1;
@@ -928,6 +934,8 @@ enum link_training_result dc_link_dp_perform_link_training(
enum link_training_result status = LINK_TRAINING_SUCCESS;
char *link_rate = "Unknown";
+ char *lt_result = "Unknown";
+
struct link_training_settings lt_settings;
memset(&lt_settings, '\0', sizeof(lt_settings));
@@ -951,22 +959,16 @@ enum link_training_result dc_link_dp_perform_link_training(
/* 2. perform link training (set link training done
* to false is done as well)*/
- if (!perform_clock_recovery_sequence(link, &lt_settings)) {
- status = LINK_TRAINING_CR_FAIL;
- } else {
+ status = perform_clock_recovery_sequence(link, &lt_settings);
+ if (status == LINK_TRAINING_SUCCESS) {
status = perform_channel_equalization_sequence(link,
&lt_settings);
}
if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
- if (!perform_link_training_int(link,
+ status = perform_link_training_int(link,
&lt_settings,
- status == LINK_TRAINING_SUCCESS)) {
- /* the next link training setting in this case
- * would be the same as CR failure case.
- */
- status = LINK_TRAINING_CR_FAIL;
- }
+ status);
}
/* 6. print status message*/
@@ -991,13 +993,37 @@ enum link_training_result dc_link_dp_perform_link_training(
break;
}
+ switch (status) {
+ case LINK_TRAINING_SUCCESS:
+ lt_result = "pass";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE0:
+ lt_result = "CR failed lane0";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE1:
+ lt_result = "CR failed lane1";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE23:
+ lt_result = "CR failed lane23";
+ break;
+ case LINK_TRAINING_EQ_FAIL_CR:
+ lt_result = "CR failed in EQ";
+ break;
+ case LINK_TRAINING_EQ_FAIL_EQ:
+ lt_result = "EQ failed";
+ break;
+ case LINK_TRAINING_LQA_FAIL:
+ lt_result = "LQA failed";
+ break;
+ default:
+ break;
+ }
+
/* Connectivity log: link training */
CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d",
link_rate,
lt_settings.link_settings.lane_count,
- (status == LINK_TRAINING_SUCCESS) ? "pass" :
- ((status == LINK_TRAINING_CR_FAIL) ? "CR failed" :
- "EQ failed"),
+ lt_result,
lt_settings.lane_settings[0].VOLTAGE_SWING,
lt_settings.lane_settings[0].PRE_EMPHASIS);
@@ -1115,6 +1141,7 @@ bool dp_hbr_verify_link_cap(
dp_cs_id,
cur);
+
if (skip_link_training)
success = true;
else {
@@ -1279,7 +1306,10 @@ static bool decide_fallback_link_setting(
return false;
switch (training_result) {
- case LINK_TRAINING_CR_FAIL:
+ case LINK_TRAINING_CR_FAIL_LANE0:
+ case LINK_TRAINING_CR_FAIL_LANE1:
+ case LINK_TRAINING_CR_FAIL_LANE23:
+ case LINK_TRAINING_LQA_FAIL:
{
if (!reached_minimum_link_rate
(current_link_setting->link_rate)) {
@@ -1290,8 +1320,18 @@ static bool decide_fallback_link_setting(
(current_link_setting->lane_count)) {
current_link_setting->link_rate =
initial_link_settings.link_rate;
- current_link_setting->lane_count =
- reduce_lane_count(
+ if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
+ return false;
+ else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
+ current_link_setting->lane_count =
+ LANE_COUNT_ONE;
+ else if (training_result ==
+ LINK_TRAINING_CR_FAIL_LANE23)
+ current_link_setting->lane_count =
+ LANE_COUNT_TWO;
+ else
+ current_link_setting->lane_count =
+ reduce_lane_count(
current_link_setting->lane_count);
} else {
return false;
@@ -1465,7 +1505,7 @@ void decide_link_settings(struct dc_stream_state *stream,
/* MST doesn't perform link training for now
* TODO: add MST specific link training routine
*/
- if (is_mst_supported(link)) {
+ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
*link_setting = link->verified_link_cap;
return;
}
@@ -1556,8 +1596,7 @@ static bool hpd_rx_irq_check_link_loss_status(
if (sink_status_changed ||
!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: Link Status changed.\n", __func__);
+ DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
return_code = true;
@@ -1570,8 +1609,7 @@ static bool hpd_rx_irq_check_link_loss_status(
sizeof(irq_reg_rx_power_state));
if (dpcd_result != DC_OK) {
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: DPCD read failed to obtain power state.\n",
+ DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
__func__);
} else {
if (irq_reg_rx_power_state != DP_SET_POWER_D0)
@@ -1932,8 +1970,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
* PSR and device auto test, refer to function handle_sst_hpd_irq
* in DAL2.1*/
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: Got short pulse HPD on link %d\n",
+ DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
__func__, link->link_index);
@@ -1947,8 +1984,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
*out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
if (result != DC_OK) {
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: DPCD read failed to obtain irq data\n",
+ DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
__func__);
return false;
}
@@ -1966,8 +2002,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
}
if (!allow_hpd_rx_irq(link)) {
- dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
- "%s: skipping HPD handling on %d\n",
+ DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
__func__, link->link_index);
return false;
}
@@ -2235,13 +2270,14 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
link->wa_flags.dp_keep_receiver_powered = false;
}
-static void retrieve_link_cap(struct dc_link *link)
+static bool retrieve_link_cap(struct dc_link *link)
{
uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1];
union down_stream_port_count down_strm_port_count;
union edp_configuration_cap edp_config_cap;
union dp_downstream_port_present ds_port = { 0 };
+ enum dc_status status = DC_ERROR_UNEXPECTED;
memset(dpcd_data, '\0', sizeof(dpcd_data));
memset(&down_strm_port_count,
@@ -2249,11 +2285,16 @@ static void retrieve_link_cap(struct dc_link *link)
memset(&edp_config_cap, '\0',
sizeof(union edp_configuration_cap));
- core_link_read_dpcd(
- link,
- DP_DPCD_REV,
- dpcd_data,
- sizeof(dpcd_data));
+ status = core_link_read_dpcd(
+ link,
+ DP_DPCD_REV,
+ dpcd_data,
+ sizeof(dpcd_data));
+
+ if (status != DC_OK) {
+ dm_error("%s: Read dpcd data failed.\n", __func__);
+ return false;
+ }
{
union training_aux_rd_interval aux_rd_interval;
@@ -2315,11 +2356,13 @@ static void retrieve_link_cap(struct dc_link *link)
/* Connectivity log: detection */
CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
+
+ return true;
}
-void detect_dp_sink_caps(struct dc_link *link)
+bool detect_dp_sink_caps(struct dc_link *link)
{
- retrieve_link_cap(link);
+ return retrieve_link_cap(link);
/* dc init_hw has power encoder using default
* signal for connector. For native DP, no
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 2096f2a179f2..7c866a7d5e77 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
@@ -102,7 +102,7 @@ void dp_enable_link_phy(
dp_receiver_power_ctrl(link, true);
}
-static bool edp_receiver_ready_T9(struct dc_link *link)
+bool edp_receiver_ready_T9(struct dc_link *link)
{
unsigned int tries = 0;
unsigned char sinkstatus = 0;
@@ -123,6 +123,28 @@ static bool edp_receiver_ready_T9(struct dc_link *link)
} while (++tries < 50);
return result;
}
+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;
+
+ 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.*/
+ do {
+ sinkstatus = 0;
+ result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
+ if (sinkstatus == 1)
+ break;
+ if (result != DC_OK)
+ break;
+ udelay(25); //MAx T7 is 50ms
+ } while (++tries < 300);
+ return result;
+}
void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
{
@@ -130,7 +152,6 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
dp_receiver_power_ctrl(link, false);
if (signal == SIGNAL_TYPE_EDP) {
- edp_receiver_ready_T9(link);
link->link_enc->funcs->disable_output(link->link_enc, signal);
link->dc->hwss.edp_power_control(link, false);
} else
@@ -258,6 +279,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,
for (i = 0; i < MAX_PIPES; i++) {
if (pipes[i].stream != NULL &&
+ !pipes[i].top_pipe &&
pipes[i].stream->sink != NULL &&
pipes[i].stream->sink->link != NULL &&
pipes[i].stream_res.stream_enc != NULL &&
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 95b8dd0e53c6..ba3487e97361 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -35,6 +35,7 @@
#include "core_types.h"
#include "set_mode_types.h"
#include "virtual/virtual_stream_encoder.h"
+#include "dpcd_defs.h"
#include "dce80/dce80_resource.h"
#include "dce100/dce100_resource.h"
@@ -44,7 +45,8 @@
#include "dcn10/dcn10_resource.h"
#endif
#include "dce120/dce120_resource.h"
-
+#define DC_LOGGER \
+ ctx->logger
enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
{
enum dce_version dc_version = DCE_VERSION_UNKNOWN;
@@ -696,7 +698,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r
/* Adjust for viewport end clip-off */
- if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) {
+ if ((data->viewport.x + data->viewport.width) < (src.x + src.width) && !flip_horz_scan_dir) {
int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x;
int int_part = dal_fixed31_32_floor(
dal_fixed31_32_sub(data->inits.h, data->ratios.horz));
@@ -704,7 +706,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r
int_part = int_part > 0 ? int_part : 0;
data->viewport.width += int_part < vp_clip ? int_part : vp_clip;
}
- if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) {
+ if ((data->viewport.y + data->viewport.height) < (src.y + src.height) && !flip_vert_scan_dir) {
int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y;
int int_part = dal_fixed31_32_floor(
dal_fixed31_32_sub(data->inits.v, data->ratios.vert));
@@ -712,7 +714,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r
int_part = int_part > 0 ? int_part : 0;
data->viewport.height += int_part < vp_clip ? int_part : vp_clip;
}
- if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) {
+ if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div && !flip_horz_scan_dir) {
int vp_clip = (src.x + src.width) / vpc_div -
data->viewport_c.width - data->viewport_c.x;
int int_part = dal_fixed31_32_floor(
@@ -721,7 +723,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r
int_part = int_part > 0 ? int_part : 0;
data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip;
}
- if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) {
+ if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div && !flip_vert_scan_dir) {
int vp_clip = (src.y + src.height) / vpc_div -
data->viewport_c.height - data->viewport_c.y;
int int_part = dal_fixed31_32_floor(
@@ -833,7 +835,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
struct view recout_skip = { 0 };
bool res = false;
-
+ struct dc_context *ctx = pipe_ctx->stream->ctx;
/* Important: scaling ratio calculation requires pixel format,
* lb depth calculation requires recout and taps require scaling ratios.
* Inits require viewport, taps, ratios and recout of split pipe
@@ -892,7 +894,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
/* May need to re-check lb size after this in some obscure scenario */
calculate_inits_and_adj_vp(pipe_ctx, &recout_skip);
- dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
+ DC_LOG_SCALER(
"%s: Viewport:\nheight:%d width:%d x:%d "
"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
"y:%d\n",
@@ -1054,6 +1056,7 @@ static int acquire_first_split_pipe(
pipe_ctx->plane_res.ipp = pool->ipps[i];
pipe_ctx->plane_res.dpp = pool->dpps[i];
pipe_ctx->stream_res.opp = pool->opps[i];
+ pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst;
pipe_ctx->pipe_idx = i;
pipe_ctx->stream = stream;
@@ -1121,6 +1124,7 @@ bool dc_add_plane_to_context(
ASSERT(tail_pipe);
free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
+ free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
@@ -1360,9 +1364,6 @@ bool dc_is_stream_scaling_unchanged(
return true;
}
-/* Maximum TMDS single link pixel clock 165MHz */
-#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
-
static void update_stream_engine_usage(
struct resource_context *res_ctx,
const struct resource_pool *pool,
@@ -1409,6 +1410,8 @@ static int acquire_first_free_pipe(
pipe_ctx->plane_res.xfm = pool->transforms[i];
pipe_ctx->plane_res.dpp = pool->dpps[i];
pipe_ctx->stream_res.opp = pool->opps[i];
+ if (pool->dpps[i])
+ pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst;
pipe_ctx->pipe_idx = i;
@@ -1555,6 +1558,9 @@ enum dc_status dc_remove_stream_from_ctx(
dc->res_pool,
del_pipe->clock_source);
+ if (dc->res_pool->funcs->remove_stream_from_ctx)
+ dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
+
memset(del_pipe, 0, sizeof(*del_pipe));
break;
@@ -1731,6 +1737,10 @@ enum dc_status resource_map_pool_resources(
pipe_ctx->stream_res.audio, true);
}
+ /* Add ABM to the resource if on EDP */
+ if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal))
+ pipe_ctx->stream_res.abm = pool->abm;
+
for (i = 0; i < context->stream_count; i++)
if (context->streams[i] == stream) {
context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
@@ -2431,7 +2441,8 @@ static void set_vsc_info_packet(
unsigned int vscPacketRevision = 0;
unsigned int i;
- if (stream->sink->link->psr_enabled) {
+ /*VSC packet set to 2 when DP revision >= 1.2*/
+ if (stream->psr_version != 0) {
vscPacketRevision = 2;
}
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 261811e0c094..ce0747ed0f00 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -33,8 +33,7 @@
/*******************************************************************************
* Private functions
******************************************************************************/
-#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000
-static void update_stream_signal(struct dc_stream_state *stream)
+void update_stream_signal(struct dc_stream_state *stream)
{
struct dc_sink *dc_sink = stream->sink;
@@ -45,8 +44,9 @@ static void update_stream_signal(struct dc_stream_state *stream)
stream->signal = dc_sink->sink_signal;
if (dc_is_dvi_signal(stream->signal)) {
- if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST &&
- stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
+ if (stream->ctx->dc->caps.dual_link_dvi &&
+ stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK &&
+ stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
else
stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
@@ -193,44 +193,19 @@ bool dc_stream_set_cursor_attributes(
core_dc = stream->ctx->dc;
res_ctx = &core_dc->current_state->res_ctx;
+ stream->cursor_attributes = *attributes;
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
- if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
+ if (pipe_ctx->stream != stream)
continue;
if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
continue;
- if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL)
- pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
- pipe_ctx->plane_res.ipp, attributes);
-
- if (pipe_ctx->plane_res.hubp != NULL &&
- pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL)
- pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
- pipe_ctx->plane_res.hubp, attributes);
-
- if (pipe_ctx->plane_res.mi != NULL &&
- pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL)
- pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
- pipe_ctx->plane_res.mi, attributes);
-
-
- if (pipe_ctx->plane_res.xfm != NULL &&
- pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL)
- pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
- pipe_ctx->plane_res.xfm, attributes);
-
- if (pipe_ctx->plane_res.dpp != NULL &&
- pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL)
- pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
- pipe_ctx->plane_res.dpp, attributes->color_format);
+ core_dc->hwss.set_cursor_attribute(pipe_ctx);
}
-
- stream->cursor_attributes = *attributes;
-
return true;
}
@@ -254,55 +229,21 @@ bool dc_stream_set_cursor_position(
core_dc = stream->ctx->dc;
res_ctx = &core_dc->current_state->res_ctx;
+ stream->cursor_position = *position;
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
- struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
- struct mem_input *mi = pipe_ctx->plane_res.mi;
- struct hubp *hubp = pipe_ctx->plane_res.hubp;
- struct dpp *dpp = pipe_ctx->plane_res.dpp;
- struct dc_cursor_position pos_cpy = *position;
- struct dc_cursor_mi_param param = {
- .pixel_clk_khz = stream->timing.pix_clk_khz,
- .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz,
- .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x,
- .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width,
- .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz
- };
if (pipe_ctx->stream != stream ||
(!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) ||
!pipe_ctx->plane_state ||
- (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
- continue;
-
- if (pipe_ctx->plane_state->address.type
- == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
- pos_cpy.enable = false;
-
- if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
- pos_cpy.enable = false;
-
-
- if (ipp != NULL && ipp->funcs->ipp_cursor_set_position != NULL)
- ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
-
- if (mi != NULL && mi->funcs->set_cursor_position != NULL)
- mi->funcs->set_cursor_position(mi, &pos_cpy, &param);
-
- if (!hubp)
+ (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp) ||
+ !pipe_ctx->plane_res.ipp)
continue;
- if (hubp->funcs->set_cursor_position != NULL)
- hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
-
- if (dpp != NULL && dpp->funcs->set_cursor_position != NULL)
- dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width);
-
+ core_dc->hwss.set_cursor_position(pipe_ctx);
}
- stream->cursor_position = *position;
-
return true;
}