aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/core/dc_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc_link.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c147
1 files changed, 80 insertions, 67 deletions
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 b0265dbebd4c..7f5a947ad31d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -43,10 +43,6 @@
#include "dpcd_defs.h"
#include "dmcu.h"
-#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_INIT(logger)
@@ -80,6 +76,12 @@ static void destruct(struct dc_link *link)
{
int i;
+ if (link->hpd_gpio != NULL) {
+ dal_gpio_close(link->hpd_gpio);
+ dal_gpio_destroy_irq(&link->hpd_gpio);
+ link->hpd_gpio = NULL;
+ }
+
if (link->ddc)
dal_ddc_service_destroy(&link->ddc);
@@ -789,7 +791,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
return false;
}
- sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
+ sink->link->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
sink->converter_disable_audio = converter_disable_audio;
link->local_sink = sink;
@@ -935,18 +937,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
bool dc_link_get_hpd_state(struct dc_link *dc_link)
{
- struct gpio *hpd_pin;
uint32_t state;
- hpd_pin = get_hpd_gpio(dc_link->ctx->dc_bios,
- dc_link->link_id, dc_link->ctx->gpio_service);
- if (hpd_pin == NULL)
- ASSERT(false);
-
- dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);
- dal_gpio_get_value(hpd_pin, &state);
- dal_gpio_close(hpd_pin);
- dal_gpio_destroy_irq(&hpd_pin);
+ dal_gpio_lock_pin(dc_link->hpd_gpio);
+ dal_gpio_get_value(dc_link->hpd_gpio, &state);
+ dal_gpio_unlock_pin(dc_link->hpd_gpio);
return state;
}
@@ -1102,7 +1097,6 @@ static bool construct(
const struct link_init_data *init_params)
{
uint8_t i;
- struct gpio *hpd_gpio = NULL;
struct ddc_service_init_data ddc_service_init_data = { { 0 } };
struct dc_context *dc_ctx = init_params->ctx;
struct encoder_init_data enc_init_data = { 0 };
@@ -1132,10 +1126,12 @@ static bool construct(
if (link->dc->res_pool->funcs->link_init)
link->dc->res_pool->funcs->link_init(link);
- hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
-
- if (hpd_gpio != NULL)
- link->irq_source_hpd = dal_irq_get_source(hpd_gpio);
+ link->hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
+ if (link->hpd_gpio != NULL) {
+ dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
+ dal_gpio_unlock_pin(link->hpd_gpio);
+ link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
+ }
switch (link->link_id.id) {
case CONNECTOR_ID_HDMI_TYPE_A:
@@ -1153,18 +1149,18 @@ static bool construct(
case CONNECTOR_ID_DISPLAY_PORT:
link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
- if (hpd_gpio != NULL)
+ if (link->hpd_gpio != NULL)
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(hpd_gpio);
+ dal_irq_get_rx_source(link->hpd_gpio);
break;
case CONNECTOR_ID_EDP:
link->connector_signal = SIGNAL_TYPE_EDP;
- if (hpd_gpio != NULL) {
+ if (link->hpd_gpio != NULL) {
link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(hpd_gpio);
+ dal_irq_get_rx_source(link->hpd_gpio);
}
break;
case CONNECTOR_ID_LVDS:
@@ -1175,10 +1171,7 @@ static bool construct(
goto create_fail;
}
- if (hpd_gpio != NULL) {
- dal_gpio_destroy_irq(&hpd_gpio);
- hpd_gpio = NULL;
- }
+
/* TODO: #DAL3 Implement id to str function.*/
LINK_INFO("Connector[%d] description:"
@@ -1281,8 +1274,9 @@ link_enc_create_fail:
ddc_create_fail:
create_fail:
- if (hpd_gpio != NULL) {
- dal_gpio_destroy_irq(&hpd_gpio);
+ if (link->hpd_gpio != NULL) {
+ dal_gpio_destroy_irq(&link->hpd_gpio);
+ link->hpd_gpio = NULL;
}
return false;
@@ -1372,7 +1366,7 @@ static void dpcd_configure_panel_mode(
static void enable_stream_features(struct pipe_ctx *pipe_ctx)
{
struct dc_stream_state *stream = pipe_ctx->stream;
- struct dc_link *link = stream->sink->link;
+ struct dc_link *link = stream->link;
union down_spread_ctrl old_downspread;
union down_spread_ctrl new_downspread;
@@ -1397,7 +1391,7 @@ static enum dc_status enable_link_dp(
struct dc_stream_state *stream = pipe_ctx->stream;
enum dc_status status;
bool skip_video_pattern;
- struct dc_link *link = stream->sink->link;
+ struct dc_link *link = stream->link;
struct dc_link_settings link_settings = {0};
enum dp_panel_mode panel_mode;
@@ -1414,8 +1408,8 @@ 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;
+ 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);
}
@@ -1448,7 +1442,7 @@ 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;
+ struct dc_link *link = stream->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);
@@ -1463,7 +1457,7 @@ static enum dc_status enable_link_dp_mst(
struct dc_state *state,
struct pipe_ctx *pipe_ctx)
{
- struct dc_link *link = pipe_ctx->stream->sink->link;
+ struct dc_link *link = pipe_ctx->stream->link;
/* sink signal type after MST branch is MST. Multiple MST sinks
* share one link. Link DP PHY is enable or training only once.
@@ -1471,6 +1465,11 @@ static enum dc_status enable_link_dp_mst(
if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
return DC_OK;
+ /* to make sure the pending down rep can be processed
+ * before clear payload table
+ */
+ dm_helpers_dp_mst_poll_pending_down_reply(link->ctx, link);
+
/* clear payload table */
dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
@@ -1597,7 +1596,7 @@ static bool i2c_write(struct pipe_ctx *pipe_ctx,
cmd.payloads = &payload;
if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx,
- pipe_ctx->stream->sink->link, &cmd))
+ pipe_ctx->stream->link, &cmd))
return true;
return false;
@@ -1651,7 +1650,7 @@ static void write_i2c_retimer_setting(
else {
i2c_success =
dal_ddc_service_query_ddc_data(
- pipe_ctx->stream->sink->link->ddc,
+ pipe_ctx->stream->link->ddc,
slave_address, &offset, 1, &value, 1);
if (!i2c_success)
/* Write failure */
@@ -1704,7 +1703,7 @@ static void write_i2c_retimer_setting(
else {
i2c_success =
dal_ddc_service_query_ddc_data(
- pipe_ctx->stream->sink->link->ddc,
+ pipe_ctx->stream->link->ddc,
slave_address, &offset, 1, &value, 1);
if (!i2c_success)
/* Write failure */
@@ -1929,7 +1928,7 @@ static void write_i2c_redriver_setting(
static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
{
struct dc_stream_state *stream = pipe_ctx->stream;
- struct dc_link *link = stream->sink->link;
+ struct dc_link *link = stream->link;
enum dc_color_depth display_color_depth;
enum engine_id eng_id;
struct ext_hdmi_settings settings = {0};
@@ -1938,12 +1937,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
&& (stream->timing.v_addressable == 480);
if (stream->phy_pix_clk == 0)
- stream->phy_pix_clk = stream->timing.pix_clk_khz;
+ stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
if (stream->phy_pix_clk > 340000)
is_over_340mhz = true;
if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
- unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps &
+ unsigned short masked_chip_caps = pipe_ctx->stream->link->chip_caps &
EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
/* DP159, Retimer settings */
@@ -1964,11 +1963,11 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
dal_ddc_service_write_scdc_data(
- stream->sink->link->ddc,
+ stream->link->ddc,
stream->phy_pix_clk,
stream->timing.flags.LTE_340MCSC_SCRAMBLE);
- memset(&stream->sink->link->cur_link_settings, 0,
+ memset(&stream->link->cur_link_settings, 0,
sizeof(struct dc_link_settings));
display_color_depth = stream->timing.display_color_depth;
@@ -1989,12 +1988,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
static void enable_link_lvds(struct pipe_ctx *pipe_ctx)
{
struct dc_stream_state *stream = pipe_ctx->stream;
- struct dc_link *link = stream->sink->link;
+ struct dc_link *link = stream->link;
if (stream->phy_pix_clk == 0)
- stream->phy_pix_clk = stream->timing.pix_clk_khz;
+ stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
- memset(&stream->sink->link->cur_link_settings, 0,
+ memset(&stream->link->cur_link_settings, 0,
sizeof(struct dc_link_settings));
link->link_enc->funcs->enable_lvds_output(
@@ -2067,7 +2066,7 @@ static bool dp_active_dongle_validate_timing(
const struct dc_crtc_timing *timing,
const struct dpcd_caps *dpcd_caps)
{
- unsigned int required_pix_clk = timing->pix_clk_khz;
+ unsigned int required_pix_clk_100hz = timing->pix_clk_100hz;
const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps;
switch (dpcd_caps->dongle_type) {
@@ -2107,9 +2106,9 @@ static bool dp_active_dongle_validate_timing(
/* Check Color Depth and Pixel Clock */
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
- required_pix_clk /= 2;
+ required_pix_clk_100hz /= 2;
else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
- required_pix_clk = required_pix_clk * 2 / 3;
+ required_pix_clk_100hz = required_pix_clk_100hz * 2 / 3;
switch (timing->display_color_depth) {
case COLOR_DEPTH_666:
@@ -2119,12 +2118,12 @@ static bool dp_active_dongle_validate_timing(
case COLOR_DEPTH_101010:
if (dongle_caps->dp_hdmi_max_bpc < 10)
return false;
- required_pix_clk = required_pix_clk * 10 / 8;
+ required_pix_clk_100hz = required_pix_clk_100hz * 10 / 8;
break;
case COLOR_DEPTH_121212:
if (dongle_caps->dp_hdmi_max_bpc < 12)
return false;
- required_pix_clk = required_pix_clk * 12 / 8;
+ required_pix_clk_100hz = required_pix_clk_100hz * 12 / 8;
break;
case COLOR_DEPTH_141414:
@@ -2134,7 +2133,7 @@ static bool dp_active_dongle_validate_timing(
return false;
}
- if (required_pix_clk > dongle_caps->dp_hdmi_max_pixel_clk)
+ if (required_pix_clk_100hz > (dongle_caps->dp_hdmi_max_pixel_clk * 10))
return false;
return true;
@@ -2145,7 +2144,7 @@ enum dc_status dc_link_validate_mode_timing(
struct dc_link *link,
const struct dc_crtc_timing *timing)
{
- uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk;
+ uint32_t max_pix_clk = stream->link->dongle_max_pix_clk * 10;
struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
/* A hack to avoid failing any modes for EDID override feature on
@@ -2155,7 +2154,7 @@ enum dc_status dc_link_validate_mode_timing(
return DC_OK;
/* Passive Dongle */
- if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
+ if (0 != max_pix_clk && timing->pix_clk_100hz > max_pix_clk)
return DC_EXCEED_DONGLE_CAP;
/* Active Dongle*/
@@ -2214,7 +2213,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
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.
- pipe_ctx[i].stream->sink->link
+ pipe_ctx[i].stream->link
== link)
/* DMCU -1 for all controller id values,
* therefore +1 here
@@ -2274,7 +2273,7 @@ void core_link_resume(struct dc_link *link)
static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
{
struct dc_link_settings *link_settings =
- &stream->sink->link->cur_link_settings;
+ &stream->link->cur_link_settings;
uint32_t link_rate_in_mbps =
link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ;
struct fixed31_32 mbps = dc_fixpt_from_int(
@@ -2305,7 +2304,7 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
uint32_t denominator;
bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth);
- kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk * bpc * 3;
+ kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 * bpc * 3;
/*
* margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
@@ -2381,7 +2380,7 @@ static void update_mst_stream_alloc_table(
static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
{
struct dc_stream_state *stream = pipe_ctx->stream;
- struct dc_link *link = stream->sink->link;
+ struct dc_link *link = stream->link;
struct link_encoder *link_encoder = link->link_enc;
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
struct dp_mst_stream_allocation_table proposed_table = {0};
@@ -2461,7 +2460,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
{
struct dc_stream_state *stream = pipe_ctx->stream;
- struct dc_link *link = stream->sink->link;
+ struct dc_link *link = stream->link;
struct link_encoder *link_encoder = link->link_enc;
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
struct dp_mst_stream_allocation_table proposed_table = {0};
@@ -2546,8 +2545,8 @@ void core_link_enable_stream(
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) {
- stream->sink->link->link_enc->funcs->setup(
- stream->sink->link->link_enc,
+ stream->link->link_enc->funcs->setup(
+ stream->link->link_enc,
pipe_ctx->stream->signal);
pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync(
pipe_ctx->stream_res.stream_enc,
@@ -2581,13 +2580,23 @@ void core_link_enable_stream(
&stream->timing);
if (!IS_FPGA_MAXIMUS_DC(core_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);
+ /* Do not touch link on seamless boot optimization. */
+ if (pipe_ctx->stream->apply_seamless_boot_optimization) {
+ pipe_ctx->stream->dpms_off = false;
+ return;
+ }
+
/* eDP lit up by bios already, no need to enable again. */
if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
- pipe_ctx->stream->apply_edp_fast_boot_optimization) {
- pipe_ctx->stream->apply_edp_fast_boot_optimization = false;
+ apply_edp_fast_boot_optimization) {
pipe_ctx->stream->dpms_off = false;
return;
}
@@ -2599,7 +2608,7 @@ void core_link_enable_stream(
if (status != DC_OK) {
DC_LOG_WARNING("enabling link %u failed: %d\n",
- pipe_ctx->stream->sink->link->link_index,
+ pipe_ctx->stream->link->link_index,
status);
/* Abort stream enable *unless* the failure was due to
@@ -2614,6 +2623,8 @@ void core_link_enable_stream(
}
}
+ stream->link->link_status.link_active = true;
+
core_dc->hwss.enable_audio_stream(pipe_ctx);
/* turn off otg test pattern if enable */
@@ -2628,7 +2639,7 @@ void core_link_enable_stream(
allocate_mst_payload(pipe_ctx);
core_dc->hwss.unblank_stream(pipe_ctx,
- &pipe_ctx->stream->sink->link->cur_link_settings);
+ &pipe_ctx->stream->link->cur_link_settings);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
enable_stream_features(pipe_ctx);
@@ -2647,7 +2658,9 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
core_dc->hwss.disable_stream(pipe_ctx, option);
- disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal);
+ disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
+
+ pipe_ctx->stream->link->link_status.link_active = false;
}
void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)