Commit 503505bf authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-fixes-4.15' of git://people.freedesktop.org/~agd5f/linux into drm-fixes

Fixes for 4.15.  Highlights:
- DC fixes for S3, gamma, audio, pageflipping, etc.
- fix a regression in radeon from kfd removal
- fix a ttm regression with swiotlb disabled
- misc other fixes

* 'drm-fixes-4.15' of git://people.freedesktop.org/~agd5f/linux: (36 commits)
  drm/radeon: remove init of CIK VMIDs 8-16 for amdkfd
  drm/ttm: fix populate_and_map() functions once more
  drm/amd/display: USB-C / thunderbolt dock specific workaround
  drm/amd/display: Switch to drm_atomic_helper_wait_for_flip_done
  drm/amd/display: fix gamma setting
  drm/amd/display: Do not put drm_atomic_state on resume
  drm/amd/display: Fix couple more inconsistent NULL checks in dc_resource
  drm/amd/display: Fix potential NULL and mem leak in create_links
  drm/amd/display: Fix hubp check in set_cursor_position
  drm/amd/display: Fix use before NULL check in validate_timing
  drm/amd/display: Bunch of smatch error and warning fixes in DC
  drm/amd/display: Fix amdgpu_dm bugs found by smatch
  drm/amd/display: try to find matching audio inst for enc inst first
  drm/amd/display: fix seq issue: turn on clock before programming afmt.
  drm/amd/display: fix memory leaks on error exit return
  drm/amd/display: check plane state before validating fbc
  drm/amd/display: Do DC mode-change check when adding CRTCs
  drm/amd/display: Revert noisy assert messages
  drm/amd/display: fix split viewport rounding error
  drm/amd/display: Check aux channel before MST resume
  ...
parents 062076e8 7fdf165a
......@@ -717,7 +717,7 @@ int amdgpu_queue_mgr_fini(struct amdgpu_device *adev,
struct amdgpu_queue_mgr *mgr);
int amdgpu_queue_mgr_map(struct amdgpu_device *adev,
struct amdgpu_queue_mgr *mgr,
int hw_ip, int instance, int ring,
u32 hw_ip, u32 instance, u32 ring,
struct amdgpu_ring **out_ring);
/*
......@@ -1572,18 +1572,14 @@ struct amdgpu_device {
/* sdma */
struct amdgpu_sdma sdma;
union {
struct {
/* uvd */
struct amdgpu_uvd uvd;
/* uvd */
struct amdgpu_uvd uvd;
/* vce */
struct amdgpu_vce vce;
};
/* vce */
struct amdgpu_vce vce;
/* vcn */
struct amdgpu_vcn vcn;
};
/* vcn */
struct amdgpu_vcn vcn;
/* firmwares */
struct amdgpu_firmware firmware;
......
......@@ -409,6 +409,10 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
if (candidate->robj == validated)
break;
/* We can't move pinned BOs here */
if (bo->pin_count)
continue;
other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
/* Check if this BO is in one of the domains we need space for */
......
......@@ -1837,9 +1837,6 @@ static int amdgpu_fini(struct amdgpu_device *adev)
adev->ip_blocks[i].status.hw = false;
}
if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU)
amdgpu_ucode_fini_bo(adev);
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
if (!adev->ip_blocks[i].status.sw)
continue;
......
......@@ -536,7 +536,7 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
{0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10},
/* Raven */
{0x1002, 0x15dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU|AMD_EXP_HW_SUPPORT},
{0x1002, 0x15dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU},
{0, 0, 0}
};
......
......@@ -164,6 +164,9 @@ static int amdgpu_pp_hw_fini(void *handle)
ret = adev->powerplay.ip_funcs->hw_fini(
adev->powerplay.pp_handle);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU)
amdgpu_ucode_fini_bo(adev);
return ret;
}
......
......@@ -442,6 +442,8 @@ static int psp_hw_fini(void *handle)
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
return 0;
amdgpu_ucode_fini_bo(adev);
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
......
......@@ -63,7 +63,7 @@ static int amdgpu_update_cached_map(struct amdgpu_queue_mapper *mapper,
static int amdgpu_identity_map(struct amdgpu_device *adev,
struct amdgpu_queue_mapper *mapper,
int ring,
u32 ring,
struct amdgpu_ring **out_ring)
{
switch (mapper->hw_ip) {
......@@ -121,7 +121,7 @@ static enum amdgpu_ring_type amdgpu_hw_ip_to_ring_type(int hw_ip)
static int amdgpu_lru_map(struct amdgpu_device *adev,
struct amdgpu_queue_mapper *mapper,
int user_ring, bool lru_pipe_order,
u32 user_ring, bool lru_pipe_order,
struct amdgpu_ring **out_ring)
{
int r, i, j;
......@@ -208,7 +208,7 @@ int amdgpu_queue_mgr_fini(struct amdgpu_device *adev,
*/
int amdgpu_queue_mgr_map(struct amdgpu_device *adev,
struct amdgpu_queue_mgr *mgr,
int hw_ip, int instance, int ring,
u32 hw_ip, u32 instance, u32 ring,
struct amdgpu_ring **out_ring)
{
int r, ip_num_rings;
......
......@@ -1023,22 +1023,101 @@ static const struct amdgpu_allowed_register_entry cik_allowed_read_registers[] =
{mmPA_SC_RASTER_CONFIG_1, true},
};
static uint32_t cik_read_indexed_register(struct amdgpu_device *adev,
u32 se_num, u32 sh_num,
u32 reg_offset)
static uint32_t cik_get_register_value(struct amdgpu_device *adev,
bool indexed, u32 se_num,
u32 sh_num, u32 reg_offset)
{
uint32_t val;
if (indexed) {
uint32_t val;
unsigned se_idx = (se_num == 0xffffffff) ? 0 : se_num;
unsigned sh_idx = (sh_num == 0xffffffff) ? 0 : sh_num;
switch (reg_offset) {
case mmCC_RB_BACKEND_DISABLE:
return adev->gfx.config.rb_config[se_idx][sh_idx].rb_backend_disable;
case mmGC_USER_RB_BACKEND_DISABLE:
return adev->gfx.config.rb_config[se_idx][sh_idx].user_rb_backend_disable;
case mmPA_SC_RASTER_CONFIG:
return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config;
case mmPA_SC_RASTER_CONFIG_1:
return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config_1;
}
mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
val = RREG32(reg_offset);
val = RREG32(reg_offset);
if (se_num != 0xffffffff || sh_num != 0xffffffff)
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
return val;
if (se_num != 0xffffffff || sh_num != 0xffffffff)
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
return val;
} else {
unsigned idx;
switch (reg_offset) {
case mmGB_ADDR_CONFIG:
return adev->gfx.config.gb_addr_config;
case mmMC_ARB_RAMCFG:
return adev->gfx.config.mc_arb_ramcfg;
case mmGB_TILE_MODE0:
case mmGB_TILE_MODE1:
case mmGB_TILE_MODE2:
case mmGB_TILE_MODE3:
case mmGB_TILE_MODE4:
case mmGB_TILE_MODE5:
case mmGB_TILE_MODE6:
case mmGB_TILE_MODE7:
case mmGB_TILE_MODE8:
case mmGB_TILE_MODE9:
case mmGB_TILE_MODE10:
case mmGB_TILE_MODE11:
case mmGB_TILE_MODE12:
case mmGB_TILE_MODE13:
case mmGB_TILE_MODE14:
case mmGB_TILE_MODE15:
case mmGB_TILE_MODE16:
case mmGB_TILE_MODE17:
case mmGB_TILE_MODE18:
case mmGB_TILE_MODE19:
case mmGB_TILE_MODE20:
case mmGB_TILE_MODE21:
case mmGB_TILE_MODE22:
case mmGB_TILE_MODE23:
case mmGB_TILE_MODE24:
case mmGB_TILE_MODE25:
case mmGB_TILE_MODE26:
case mmGB_TILE_MODE27:
case mmGB_TILE_MODE28:
case mmGB_TILE_MODE29:
case mmGB_TILE_MODE30:
case mmGB_TILE_MODE31:
idx = (reg_offset - mmGB_TILE_MODE0);
return adev->gfx.config.tile_mode_array[idx];
case mmGB_MACROTILE_MODE0:
case mmGB_MACROTILE_MODE1:
case mmGB_MACROTILE_MODE2:
case mmGB_MACROTILE_MODE3:
case mmGB_MACROTILE_MODE4:
case mmGB_MACROTILE_MODE5:
case mmGB_MACROTILE_MODE6:
case mmGB_MACROTILE_MODE7:
case mmGB_MACROTILE_MODE8:
case mmGB_MACROTILE_MODE9:
case mmGB_MACROTILE_MODE10:
case mmGB_MACROTILE_MODE11:
case mmGB_MACROTILE_MODE12:
case mmGB_MACROTILE_MODE13:
case mmGB_MACROTILE_MODE14:
case mmGB_MACROTILE_MODE15:
idx = (reg_offset - mmGB_MACROTILE_MODE0);
return adev->gfx.config.macrotile_mode_array[idx];
default:
return RREG32(reg_offset);
}
}
}
static int cik_read_register(struct amdgpu_device *adev, u32 se_num,
......@@ -1048,13 +1127,13 @@ static int cik_read_register(struct amdgpu_device *adev, u32 se_num,
*value = 0;
for (i = 0; i < ARRAY_SIZE(cik_allowed_read_registers); i++) {
bool indexed = cik_allowed_read_registers[i].grbm_indexed;
if (reg_offset != cik_allowed_read_registers[i].reg_offset)
continue;
*value = cik_allowed_read_registers[i].grbm_indexed ?
cik_read_indexed_register(adev, se_num,
sh_num, reg_offset) :
RREG32(reg_offset);
*value = cik_get_register_value(adev, indexed, se_num, sh_num,
reg_offset);
return 0;
}
return -EINVAL;
......
......@@ -1819,6 +1819,22 @@ static void gfx_v7_0_setup_rb(struct amdgpu_device *adev)
adev->gfx.config.backend_enable_mask,
num_rb_pipes);
}
/* cache the values for userspace */
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
gfx_v7_0_select_se_sh(adev, i, j, 0xffffffff);
adev->gfx.config.rb_config[i][j].rb_backend_disable =
RREG32(mmCC_RB_BACKEND_DISABLE);
adev->gfx.config.rb_config[i][j].user_rb_backend_disable =
RREG32(mmGC_USER_RB_BACKEND_DISABLE);
adev->gfx.config.rb_config[i][j].raster_config =
RREG32(mmPA_SC_RASTER_CONFIG);
adev->gfx.config.rb_config[i][j].raster_config_1 =
RREG32(mmPA_SC_RASTER_CONFIG_1);
}
}
gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
}
......
......@@ -1175,7 +1175,7 @@ static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev)
{
adev->uvd.irq.num_types = adev->vcn.num_enc_rings + 1;
adev->vcn.irq.num_types = adev->vcn.num_enc_rings + 1;
adev->vcn.irq.funcs = &vcn_v1_0_irq_funcs;
}
......
......@@ -520,7 +520,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
aconnector = to_amdgpu_dm_connector(connector);
if (aconnector->dc_link->type == dc_connection_mst_branch) {
if (aconnector->dc_link->type == dc_connection_mst_branch &&
aconnector->mst_mgr.aux) {
DRM_DEBUG_DRIVER("DM_MST: starting TM on aconnector: %p [id: %d]\n",
aconnector, aconnector->base.base.id);
......@@ -677,6 +678,10 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev)
mutex_lock(&aconnector->hpd_lock);
dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
if (aconnector->fake_enable && aconnector->dc_link->local_sink)
aconnector->fake_enable = false;
aconnector->dc_sink = NULL;
amdgpu_dm_update_connector_after_detect(aconnector);
mutex_unlock(&aconnector->hpd_lock);
......@@ -711,7 +716,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev)
ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state);
drm_atomic_state_put(adev->dm.cached_state);
adev->dm.cached_state = NULL;
amdgpu_dm_irq_resume_late(adev);
......@@ -2704,7 +2708,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
.link = aconnector->dc_link,
.sink_signal = SIGNAL_TYPE_VIRTUAL
};
struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
struct edid *edid;
if (!aconnector->base.edid_blob_ptr ||
!aconnector->base.edid_blob_ptr->data) {
......@@ -2716,6 +2720,8 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
return;
}
edid = (struct edid *) aconnector->base.edid_blob_ptr->data;
aconnector->edid = edid;
aconnector->dc_em_sink = dc_link_add_remote_sink(
......@@ -4193,13 +4199,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode,
dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream);
if (!dm_new_crtc_state->stream)
continue;
status = dc_stream_get_status(dm_new_crtc_state->stream);
WARN_ON(!status);
WARN_ON(!status->plane_count);
if (!dm_new_crtc_state->stream)
continue;
/*TODO How it works with MPO ?*/
if (!dc_commit_planes_to_stream(
dm->dc,
......@@ -4253,7 +4259,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_commit_hw_done(state);
if (wait_for_vblank)
drm_atomic_helper_wait_for_vblanks(dev, state);
drm_atomic_helper_wait_for_flip_done(dev, state);
drm_atomic_helper_cleanup_planes(dev, state);
}
......@@ -4332,9 +4338,11 @@ void dm_restore_drm_connector_state(struct drm_device *dev,
return;
disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc);
acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state);
if (!disconnected_acrtc)
return;
if (!disconnected_acrtc || !acrtc_state->stream)
acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state);
if (!acrtc_state->stream)
return;
/*
......@@ -4455,7 +4463,7 @@ static int dm_update_crtcs_state(struct dc *dc,
}
}
if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
if (enable && dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) {
new_crtc_state->mode_changed = false;
......@@ -4709,7 +4717,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
} else {
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
!new_crtc_state->color_mgmt_changed)
continue;
if (!new_crtc_state->enable)
......
......@@ -75,6 +75,9 @@ void dc_conn_log(struct dc_context *ctx,
if (signal == signal_type_info_tbl[i].type)
break;
if (i == NUM_ELEMENTS(signal_type_info_tbl))
goto fail;
dm_logger_append(&entry, "[%s][ConnIdx:%d] ",
signal_type_info_tbl[i].name,
link->link_index);
......@@ -96,6 +99,8 @@ void dc_conn_log(struct dc_context *ctx,
dm_logger_append(&entry, "^\n");
dm_helpers_dc_conn_log(ctx, &entry, event);
fail:
dm_logger_close(&entry);
va_end(args);
......
......@@ -249,7 +249,7 @@ static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
struct graphics_object_id *dest_object_id)
{
uint32_t number;
uint16_t *id;
uint16_t *id = NULL;
ATOM_OBJECT *object;
struct bios_parser *bp = BP_FROM_DCB(dcb);
......@@ -260,7 +260,7 @@ static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
number = get_dest_obj_list(bp, object, &id);
if (number <= index)
if (number <= index || !id)
return BP_RESULT_BADINPUT;
*dest_object_id = object_id_from_bios_object_id(id[index]);
......
......@@ -121,6 +121,10 @@ static bool create_links(
goto failed_alloc;
}
link->link_index = dc->link_count;
dc->links[dc->link_count] = link;
dc->link_count++;
link->ctx = dc->ctx;
link->dc = dc;
link->connector_signal = SIGNAL_TYPE_VIRTUAL;
......@@ -129,6 +133,13 @@ static bool create_links(
link->link_id.enum_id = ENUM_ID_1;
link->link_enc = kzalloc(sizeof(*link->link_enc), GFP_KERNEL);
if (!link->link_enc) {
BREAK_TO_DEBUGGER();
goto failed_alloc;
}
link->link_status.dpcd_caps = &link->dpcd_caps;
enc_init.ctx = dc->ctx;
enc_init.channel = CHANNEL_ID_UNKNOWN;
enc_init.hpd_source = HPD_SOURCEID_UNKNOWN;
......@@ -138,10 +149,6 @@ static bool create_links(
enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL;
enc_init.encoder.enum_id = ENUM_ID_1;
virtual_link_encoder_construct(link->link_enc, &enc_init);
link->link_index = dc->link_count;
dc->links[dc->link_count] = link;
dc->link_count++;
}
return true;
......
......@@ -480,22 +480,6 @@ static void detect_dp(
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
detect_dp_sink_caps(link);
/* DP active dongles */
if (is_dp_active_dongle(link)) {
link->type = dc_connection_active_dongle;
if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
/*
* active dongle unplug processing for short irq
*/
link_disconnect_sink(link);
return;
}
if (link->dpcd_caps.dongle_type !=
DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
*converter_disable_audio = true;
}
}
if (is_mst_supported(link)) {
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
link->type = dc_connection_mst_branch;
......@@ -535,6 +519,22 @@ static void detect_dp(
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
}
}
if (link->type != dc_connection_mst_branch &&
is_dp_active_dongle(link)) {
/* DP active dongles */
link->type = dc_connection_active_dongle;
if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
/*
* active dongle unplug processing for short irq
*/
link_disconnect_sink(link);
return;
}
if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER)
*converter_disable_audio = true;
}
} else {
/* DP passive dongles */
sink_caps->signal = dp_passive_dongle_detection(link->ddc,
......@@ -1801,12 +1801,75 @@ static void disable_link(struct dc_link *link, enum signal_type signal)
link->link_enc->funcs->disable_output(link->link_enc, signal, link);
}
bool dp_active_dongle_validate_timing(
const struct dc_crtc_timing *timing,
const struct dc_dongle_caps *dongle_caps)
{
unsigned int required_pix_clk = timing->pix_clk_khz;
if (dongle_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER ||
dongle_caps->extendedCapValid == false)
return true;
/* Check Pixel Encoding */
switch (timing->pixel_encoding) {
case PIXEL_ENCODING_RGB:
case PIXEL_ENCODING_YCBCR444:
break;
case PIXEL_ENCODING_YCBCR422:
if (!dongle_caps->is_dp_hdmi_ycbcr422_pass_through)
return false;
break;
case PIXEL_ENCODING_YCBCR420:
if (!dongle_caps->is_dp_hdmi_ycbcr420_pass_through)
return false;
break;
default:
/* Invalid Pixel Encoding*/
return false;
}
/* Check Color Depth and Pixel Clock */
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
required_pix_clk /= 2;
switch (timing->display_color_depth) {
case COLOR_DEPTH_666:
case COLOR_DEPTH_888:
/*888 and 666 should always be supported*/
break;
case COLOR_DEPTH_101010:
if (dongle_caps->dp_hdmi_max_bpc < 10)
return false;
required_pix_clk = required_pix_clk * 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;
break;
case COLOR_DEPTH_141414:
case COLOR_DEPTH_161616:
default:
/* These color depths are currently not supported */
return false;
}
if (required_pix_clk > dongle_caps->dp_hdmi_max_pixel_clk)
return false;
return true;
}
enum dc_status dc_link_validate_mode_timing(
const struct dc_stream_state *stream,
struct dc_link *link,
const struct dc_crtc_timing *timing)
{
uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk;
struct dc_dongle_caps *dongle_caps = &link->link_status.dpcd_caps->dongle_caps;
/* A hack to avoid failing any modes for EDID override feature on
* topology change such as lower quality cable for DP or different dongle
......@@ -1814,8 +1877,13 @@ enum dc_status dc_link_validate_mode_timing(
if (link->remote_sinks[0])
return DC_OK;
/* Passive Dongle */
if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
return DC_EXCEED_DONGLE_MAX_CLK;
return DC_EXCEED_DONGLE_CAP;
/* Active Dongle*/
if (!dp_active_dongle_validate_timing(timing, dongle_caps))
return DC_EXCEED_DONGLE_CAP;
switch (stream->signal) {
case SIGNAL_TYPE_EDP:
......
......@@ -1512,7 +1512,7 @@ static bool hpd_rx_irq_check_link_loss_status(
struct dc_link *link,
union hpd_irq_data *hpd_irq_dpcd_data)
{
uint8_t irq_reg_rx_power_state;
uint8_t irq_reg_rx_power_state = 0;
enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
union lane_status lane_status;
uint32_t lane;
......@@ -1524,60 +1524,55 @@ static bool hpd_rx_irq_check_link_loss_status(
if (link->cur_link_settings.lane_count == 0)
return return_code;
/*1. Check that we can handle interrupt: Not in FS DOS,
* Not in "Display Timeout" state, Link is trained.
*/
dpcd_result = core_link_read_dpcd(link,
DP_SET_POWER,
&irq_reg_rx_power_state,
sizeof(irq_reg_rx_power_state));
/*1. Check that Link Status changed, before re-training.*/
if (dpcd_result != DC_OK) {
irq_reg_rx_power_state = DP_SET_POWER_D0;
dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
"%s: DPCD read failed to obtain power state.\n",
__func__);
/*parse lane status*/
for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
/* check status of lanes 0,1
* changed DpcdAddress_Lane01Status (0x202)
*/
lane_status.raw = get_nibble_at_index(
&hpd_irq_dpcd_data->bytes.lane01_status.raw,
lane);
if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
!lane_status.bits.CR_DONE_0 ||
!lane_status.bits.SYMBOL_LOCKED_0) {
/* if one of the channel equalization, clock
* recovery or symbol lock is dropped
* consider it as (link has been
* dropped) dp sink status has changed
*/
sink_status_changed = true;
break;
}
}
if (irq_reg_rx_power_state == DP_SET_POWER_D0) {
/*2. Check that Link Status changed, before re-training.*/
/*parse lane status*/
for (lane = 0;
lane < link->cur_link_settings.lane_count;
lane++) {
/* Check interlane align.*/
if (sink_status_changed ||
!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
/* check status of lanes 0,1
* changed DpcdAddress_Lane01Status (0x202)*/
lane_status.raw = get_nibble_at_index(
&hpd_irq_dpcd_data->bytes.lane01_status.raw,
lane);
if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
!lane_status.bits.CR_DONE_0 ||
!lane_status.bits.SYMBOL_LOCKED_0) {
/* if one of the channel equalization, clock
* recovery or symbol lock is dropped
* consider it as (link has been
* dropped) dp sink status has changed*/
sink_status_changed = true;
break;
}
dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
"%s: Link Status changed.\n", __func__);
}
return_code = true;
/* Check interlane align.*/
if (sink_status_changed ||
!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.
INTERLANE_ALIGN_DONE) {
/*2. Check that we can handle interrupt: Not in FS DOS,
* Not in "Display Timeout" state, Link is trained.
*/
dpcd_result = core_link_read_dpcd(link,
DP_SET_POWER,
&irq_reg_rx_power_state,
sizeof(irq_reg_rx_power_state));
if (dpcd_result != DC_OK) {
dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
"%s: Link Status changed.\n",
"%s: DPCD read failed to obtain power state.\n",
__func__);
return_code = true;
} else {
if (irq_reg_rx_power_state != DP_SET_POWER_D0)
return_code = false;
}
}
......@@ -2062,6 +2057,24 @@ bool is_dp_active_dongle(const struct dc_link *link)
(dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER);
}
static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)