diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm')
6 files changed, 270 insertions, 157 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f71fe6d2ddda..1ce4c98385e3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -59,9 +59,9 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "ivsrcid/irqsrcs_dcn_1_0.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -#include "vega10/soc15ip.h" +#include "dcn/dcn_1_0_offset.h" +#include "dcn/dcn_1_0_sh_mask.h" +#include "soc15ip.h" #include "soc15_common.h" #endif @@ -431,9 +431,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.dc = dc_create(&init_data); if (adev->dm.dc) { - DRM_INFO("Display Core initialized!\n"); + DRM_INFO("Display Core initialized with v%s!\n", DC_VER); } else { - DRM_INFO("Display Core failed to initialize!\n"); + DRM_INFO("Display Core failed to initialize with v%s!\n", DC_VER); goto error; } @@ -792,7 +792,7 @@ dm_atomic_state_alloc_free(struct drm_atomic_state *state) static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, - .output_poll_changed = amdgpu_output_poll_changed, + .output_poll_changed = drm_fb_helper_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = amdgpu_dm_atomic_commit, .atomic_state_alloc = dm_atomic_state_alloc, @@ -1590,7 +1590,6 @@ static int dm_early_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; adev->ddev->driver->driver_features |= DRIVER_ATOMIC; - amdgpu_dm_set_irq_funcs(adev); switch (adev->asic_type) { case CHIP_BONAIRE: @@ -1664,6 +1663,8 @@ static int dm_early_init(void *handle) return -EINVAL; } + amdgpu_dm_set_irq_funcs(adev); + if (adev->mode_info.funcs == NULL) adev->mode_info.funcs = &dm_display_funcs; @@ -1679,18 +1680,6 @@ static int dm_early_init(void *handle) return 0; } -struct dm_connector_state { - struct drm_connector_state base; - - enum amdgpu_rmx_type scaling; - uint8_t underscan_vborder; - uint8_t underscan_hborder; - bool underscan_enable; -}; - -#define to_dm_connector_state(x)\ - container_of((x), struct dm_connector_state, base) - static bool modeset_required(struct drm_crtc_state *crtc_state, struct dc_stream_state *new_stream, struct dc_stream_state *old_stream) @@ -1773,8 +1762,7 @@ static bool fill_rects_from_plane_state(const struct drm_plane_state *state, return true; } static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, - uint64_t *tiling_flags, - uint64_t *fb_location) + uint64_t *tiling_flags) { struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); int r = amdgpu_bo_reserve(rbo, false); @@ -1786,9 +1774,6 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, return r; } - if (fb_location) - *fb_location = amdgpu_bo_gpu_offset(rbo); - if (tiling_flags) amdgpu_bo_get_tiling_flags(rbo, tiling_flags); @@ -1799,12 +1784,9 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, struct dc_plane_state *plane_state, - const struct amdgpu_framebuffer *amdgpu_fb, - bool addReq) + const struct amdgpu_framebuffer *amdgpu_fb) { uint64_t tiling_flags; - uint64_t fb_location = 0; - uint64_t chroma_addr = 0; unsigned int awidth; const struct drm_framebuffer *fb = &amdgpu_fb->base; int ret = 0; @@ -1812,8 +1794,7 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, ret = get_fb_info( amdgpu_fb, - &tiling_flags, - addReq == true ? &fb_location:NULL); + &tiling_flags); if (ret) return ret; @@ -1851,8 +1832,6 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { plane_state->address.type = PLN_ADDR_TYPE_GRAPHICS; - plane_state->address.grph.addr.low_part = lower_32_bits(fb_location); - plane_state->address.grph.addr.high_part = upper_32_bits(fb_location); plane_state->plane_size.grph.surface_size.x = 0; plane_state->plane_size.grph.surface_size.y = 0; plane_state->plane_size.grph.surface_size.width = fb->width; @@ -1865,15 +1844,6 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, } else { awidth = ALIGN(fb->width, 64); plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; - plane_state->address.video_progressive.luma_addr.low_part - = lower_32_bits(fb_location); - plane_state->address.video_progressive.luma_addr.high_part - = upper_32_bits(fb_location); - chroma_addr = fb_location + (u64)(awidth * fb->height); - plane_state->address.video_progressive.chroma_addr.low_part - = lower_32_bits(chroma_addr); - plane_state->address.video_progressive.chroma_addr.high_part - = upper_32_bits(chroma_addr); plane_state->plane_size.video.luma_size.x = 0; plane_state->plane_size.video.luma_size.y = 0; plane_state->plane_size.video.luma_size.width = awidth; @@ -1983,8 +1953,7 @@ static void fill_gamma_from_crtc_state(const struct drm_crtc_state *crtc_state, static int fill_plane_attributes(struct amdgpu_device *adev, struct dc_plane_state *dc_plane_state, struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state, - bool addrReq) + struct drm_crtc_state *crtc_state) { const struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(plane_state->fb); @@ -1998,8 +1967,7 @@ static int fill_plane_attributes(struct amdgpu_device *adev, ret = fill_plane_attributes_from_fb( crtc->dev->dev_private, dc_plane_state, - amdgpu_fb, - addrReq); + amdgpu_fb); if (ret) return ret; @@ -2174,6 +2142,7 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, const struct drm_connector *connector) { struct dc_crtc_timing *timing_out = &stream->timing; + struct dc_transfer_func *tf = dc_create_transfer_func(); memset(timing_out, 0, sizeof(struct dc_crtc_timing)); @@ -2217,13 +2186,9 @@ fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, stream->output_color_space = get_output_color_space(timing_out); - { - struct dc_transfer_func *tf = dc_create_transfer_func(); - - tf->type = TF_TYPE_PREDEFINED; - tf->tf = TRANSFER_FUNCTION_SRGB; - stream->out_transfer_func = tf; - } + tf->type = TF_TYPE_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + stream->out_transfer_func = tf; } static void fill_audio_info(struct audio_info *audio_info, @@ -2330,13 +2295,63 @@ static int create_fake_sink(struct amdgpu_dm_connector *aconnector) return 0; } +static void set_multisync_trigger_params( + struct dc_stream_state *stream) +{ + if (stream->triggered_crtc_reset.enabled) { + stream->triggered_crtc_reset.event = CRTC_EVENT_VSYNC_RISING; + stream->triggered_crtc_reset.delay = TRIGGER_DELAY_NEXT_LINE; + } +} + +static void set_master_stream(struct dc_stream_state *stream_set[], + int stream_count) +{ + int j, highest_rfr = 0, master_stream = 0; + + for (j = 0; j < stream_count; j++) { + if (stream_set[j] && stream_set[j]->triggered_crtc_reset.enabled) { + int refresh_rate = 0; + + refresh_rate = (stream_set[j]->timing.pix_clk_khz*1000)/ + (stream_set[j]->timing.h_total*stream_set[j]->timing.v_total); + if (refresh_rate > highest_rfr) { + highest_rfr = refresh_rate; + master_stream = j; + } + } + } + for (j = 0; j < stream_count; j++) { + if (stream_set[j] && j != master_stream) + stream_set[j]->triggered_crtc_reset.event_source = stream_set[master_stream]; + } +} + +static void dm_enable_per_frame_crtc_master_sync(struct dc_state *context) +{ + int i = 0; + + if (context->stream_count < 2) + return; + for (i = 0; i < context->stream_count ; i++) { + if (!context->streams[i]) + continue; + /* TODO: add a function to read AMD VSDB bits and will set + * crtc_sync_master.multi_sync_enabled flag + * For now its set to false + */ + set_multisync_trigger_params(context->streams[i]); + } + set_master_stream(context->streams, context->stream_count); +} + static struct dc_stream_state * create_stream_for_sink(struct amdgpu_dm_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { struct drm_display_mode *preferred_mode = NULL; - const struct drm_connector *drm_connector; + struct drm_connector *drm_connector; struct dc_stream_state *stream = NULL; struct drm_display_mode mode = *drm_mode; bool native_mode_found = false; @@ -2355,11 +2370,13 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (!aconnector->dc_sink) { /* - * Exclude MST from creating fake_sink - * TODO: need to enable MST into fake_sink feature + * Create dc_sink when necessary to MST + * Don't apply fake_sink to MST */ - if (aconnector->mst_port) - goto stream_create_fail; + if (aconnector->mst_port) { + dm_dp_mst_dc_sink_create(drm_connector); + goto mst_dc_sink_create_done; + } if (create_fake_sink(aconnector)) goto stream_create_fail; @@ -2410,6 +2427,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, stream_create_fail: dm_state_null: drm_connector_null: +mst_dc_sink_create_done: return stream; } @@ -2710,8 +2728,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) }; struct edid *edid; - if (!aconnector->base.edid_blob_ptr || - !aconnector->base.edid_blob_ptr->data) { + if (!aconnector->base.edid_blob_ptr) { DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", aconnector->base.name); @@ -2986,7 +3003,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, = lower_32_bits(afb->address); plane_state->address.video_progressive.luma_addr.high_part = upper_32_bits(afb->address); - chroma_addr = afb->address + (u64)(awidth * new_state->fb->height); + chroma_addr = afb->address + (u64)awidth * new_state->fb->height; plane_state->address.video_progressive.chroma_addr.low_part = lower_32_bits(chroma_addr); plane_state->address.video_progressive.chroma_addr.high_part @@ -3333,8 +3350,6 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, amdgpu_dm_connector->num_modes = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); - amdgpu_dm_get_native_mode(connector); } else { amdgpu_dm_connector->num_modes = 0; @@ -3996,6 +4011,19 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, } } +/** + * amdgpu_dm_crtc_copy_transient_flags - copy mirrored flags from DRM to DC + * @crtc_state: the DRM CRTC state + * @stream_state: the DC stream state. + * + * Copy the mirrored transient state flags from DRM, to DC. It is used to bring + * a dc_stream_state's flags in sync with a drm_crtc_state's flags. + */ +static void amdgpu_dm_crtc_copy_transient_flags(struct drm_crtc_state *crtc_state, + struct dc_stream_state *stream_state) +{ + stream_state->mode_changed = crtc_state->mode_changed; +} static int amdgpu_dm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, @@ -4035,11 +4063,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) struct amdgpu_display_manager *dm = &adev->dm; struct dm_atomic_state *dm_state; uint32_t i, j; - uint32_t new_crtcs_count = 0; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; - struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; - struct dc_stream_state *new_stream = NULL; unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; @@ -4069,6 +4094,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) new_crtc_state->active_changed, new_crtc_state->connectors_changed); + /* Copy all transient state flags into dc state */ + if (dm_new_crtc_state->stream) { + amdgpu_dm_crtc_copy_transient_flags(&dm_new_crtc_state->base, + dm_new_crtc_state->stream); + } + /* handles headless hotplug case, updating new_state and * aconnector as needed */ @@ -4098,25 +4129,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) continue; } - if (dm_old_crtc_state->stream) remove_stream(adev, acrtc, dm_old_crtc_state->stream); - - /* - * this loop saves set mode crtcs - * we needed to enable vblanks once all - * resources acquired in dc after dc_commit_streams - */ - - /*TODO move all this into dm_crtc_state, get rid of - * new_crtcs array and use old and new atomic states - * instead - */ - new_crtcs[new_crtcs_count] = acrtc; - new_crtcs_count++; - - new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); acrtc->enabled = true; acrtc->hw_mode = new_crtc_state->mode; crtc->hwmode = new_crtc_state->mode; @@ -4134,31 +4149,61 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) * are removed from freesync module */ if (adev->dm.freesync_module) { - for (i = 0; i < new_crtcs_count; i++) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { struct amdgpu_dm_connector *aconnector = NULL; + struct dm_connector_state *dm_new_con_state = NULL; + struct amdgpu_crtc *acrtc = NULL; + bool modeset_needed; - new_crtc_state = drm_atomic_get_new_crtc_state(state, - &new_crtcs[i]->base); dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + modeset_needed = modeset_required( + new_crtc_state, + dm_new_crtc_state->stream, + dm_old_crtc_state->stream); + /* We add stream to freesync if: + * 1. Said stream is not null, and + * 2. A modeset is requested. This means that the + * stream was removed previously, and needs to be + * replaced. + */ + if (dm_new_crtc_state->stream == NULL || + !modeset_needed) + continue; + + acrtc = to_amdgpu_crtc(crtc); - new_stream = dm_new_crtc_state->stream; - aconnector = amdgpu_dm_find_first_crtc_matching_connector( - state, - &new_crtcs[i]->base); + aconnector = + amdgpu_dm_find_first_crtc_matching_connector( + state, crtc); if (!aconnector) { - DRM_DEBUG_DRIVER("Atomic commit: Failed to find connector for acrtc id:%d " - "skipping freesync init\n", - new_crtcs[i]->crtc_id); + DRM_DEBUG_DRIVER("Atomic commit: Failed to " + "find connector for acrtc " + "id:%d skipping freesync " + "init\n", + acrtc->crtc_id); continue; } mod_freesync_add_stream(adev->dm.freesync_module, - new_stream, &aconnector->caps); + dm_new_crtc_state->stream, + &aconnector->caps); + new_con_state = drm_atomic_get_new_connector_state( + state, &aconnector->base); + dm_new_con_state = to_dm_connector_state(new_con_state); + + mod_freesync_set_user_enable(adev->dm.freesync_module, + &dm_new_crtc_state->stream, + 1, + &dm_new_con_state->user_enable); } } - if (dm_state->context) + if (dm_state->context) { + dm_enable_per_frame_crtc_master_sync(dm_state->context); WARN_ON(!dc_commit_state(dm->dc, dm_state->context)); + } for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -4216,18 +4261,28 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm_error("%s: Failed to update stream scaling!\n", __func__); } - for (i = 0; i < new_crtcs_count; i++) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { /* * loop to enable interrupts on newly arrived crtc */ - struct amdgpu_crtc *acrtc = new_crtcs[i]; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + bool modeset_needed; - new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + modeset_needed = modeset_required( + new_crtc_state, + dm_new_crtc_state->stream, + dm_old_crtc_state->stream); + + if (dm_new_crtc_state->stream == NULL || !modeset_needed) + continue; if (adev->dm.freesync_module) mod_freesync_notify_mode_change( - adev->dm.freesync_module, &dm_new_crtc_state->stream, 1); + adev->dm.freesync_module, + &dm_new_crtc_state->stream, 1); manage_dm_interrupts(adev, acrtc, true); } @@ -4461,18 +4516,15 @@ static int dm_update_crtcs_state(struct dc *dc, __func__, acrtc->base.base.id); break; } - } - - 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; - DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", - new_crtc_state->mode_changed); + if (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; + DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", + new_crtc_state->mode_changed); + } } - if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) goto next_crtc; @@ -4529,6 +4581,7 @@ static int dm_update_crtcs_state(struct dc *dc, WARN_ON(dm_new_crtc_state->stream); dm_new_crtc_state->stream = new_stream; + dc_stream_retain(new_stream); DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", @@ -4654,8 +4707,7 @@ static int dm_update_planes_state(struct dc *dc, new_plane_crtc->dev->dev_private, dm_new_plane_state->dc_state, new_plane_state, - new_crtc_state, - false); + new_crtc_state); if (ret) return ret; @@ -4670,6 +4722,11 @@ static int dm_update_planes_state(struct dc *dc, return ret; } + /* Tell DC to do a full surface update every time there + * is a plane change. Inefficient, but works for now. + */ + dm_new_plane_state->dc_state->update_flags.bits.full_update = 1; + *lock_and_validation_needed = true; } } @@ -4681,8 +4738,6 @@ static int dm_update_planes_state(struct dc *dc, static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { - int i; - int ret; struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); @@ -4690,6 +4745,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_connector_state *old_con_state, *new_con_state; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; + int ret, i; /* * This bool will be set for true for any modeset/reset @@ -4701,37 +4757,21 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - /* - * legacy_cursor_update should be made false for SoC's having - * a dedicated hardware plane for cursor in amdgpu_dm_atomic_commit(), - * otherwise for software cursor plane, - * we should not add it to list of affected planes. - */ - if (state->legacy_cursor_update) { - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - if (new_crtc_state->color_mgmt_changed) { - ret = drm_atomic_add_affected_planes(state, crtc); - if (ret) - goto fail; - } - } - } 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) && - !new_crtc_state->color_mgmt_changed) - continue; + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && + !new_crtc_state->color_mgmt_changed) + continue; - if (!new_crtc_state->enable) - continue; + if (!new_crtc_state->enable) + continue; - ret = drm_atomic_add_affected_connectors(state, crtc); - if (ret) - return ret; + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret) + return ret; - ret = drm_atomic_add_affected_planes(state, crtc); - if (ret) - goto fail; - } + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + goto fail; } dm_state->context = dc_create_state(); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 117521c6a6ed..2faa77a7eeda 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -189,6 +189,8 @@ struct amdgpu_dm_connector { struct mutex hpd_lock; bool fake_enable; + + bool mst_connected; }; #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) @@ -220,6 +222,18 @@ struct dm_atomic_state { #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) +struct dm_connector_state { + struct drm_connector_state base; + + enum amdgpu_rmx_type scaling; + uint8_t underscan_vborder; + uint8_t underscan_hborder; + bool underscan_enable; + struct mod_freesync_user_enable user_enable; +}; + +#define to_dm_connector_state(x)\ + container_of((x), struct dm_connector_state, base) void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); struct drm_connector_state * diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index ca5d0d1581dc..1874b6cee6af 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -683,13 +683,16 @@ static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = { void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) { - adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST; + if (adev->mode_info.num_crtc > 0) + adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_VLINE1 + adev->mode_info.num_crtc; + else + adev->crtc_irq.num_types = 0; adev->crtc_irq.funcs = &dm_crtc_irq_funcs; - adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST; + adev->pageflip_irq.num_types = adev->mode_info.num_crtc; adev->pageflip_irq.funcs = &dm_pageflip_irq_funcs; - adev->hpd_irq.num_types = AMDGPU_HPD_LAST; + adev->hpd_irq.num_types = adev->mode_info.num_hpd; adev->hpd_irq.funcs = &dm_hpd_irq_funcs; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index f8efb98b1fa7..f3d87f418d2e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -177,12 +177,43 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { static int dm_connector_update_modes(struct drm_connector *connector, struct edid *edid) { - int ret; + return drm_add_edid_modes(connector, edid); +} + +void dm_dp_mst_dc_sink_create(struct drm_connector *connector) +{ + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + struct edid *edid; + struct dc_sink *dc_sink; + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; - ret = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); + edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); - return ret; + if (!edid) { + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); + return; + } + + aconnector->edid = edid; + + dc_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)aconnector->edid, + (aconnector->edid->extensions + 1) * EDID_LENGTH, + &init_params); + + dc_sink->priv = aconnector; + aconnector->dc_sink = dc_sink; + + amdgpu_dm_add_sink_to_freesync_module( + connector, aconnector->edid); + + drm_mode_connector_update_edid_property( + &aconnector->base, aconnector->edid); } static int dm_dp_mst_get_modes(struct drm_connector *connector) @@ -311,6 +342,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_mode_connector_set_path_property(connector, pathprop); drm_connector_list_iter_end(&conn_iter); + aconnector->mst_connected = true; return &aconnector->base; } } @@ -363,6 +395,8 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, */ amdgpu_dm_connector_funcs_reset(connector); + aconnector->mst_connected = true; + DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n", aconnector, connector->base.id, aconnector->mst_port); @@ -394,6 +428,8 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_mode_connector_update_edid_property( &aconnector->base, NULL); + + aconnector->mst_connected = false; } static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) @@ -404,10 +440,18 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) drm_kms_helper_hotplug_event(dev); } +static void dm_dp_mst_link_status_reset(struct drm_connector *connector) +{ + mutex_lock(&connector->dev->mode_config.mutex); + drm_mode_connector_set_link_status_property(connector, DRM_MODE_LINK_STATUS_BAD); + mutex_unlock(&connector->dev->mode_config.mutex); +} + static void dm_dp_mst_register_connector(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); if (adev->mode_info.rfbdev) drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); @@ -416,6 +460,8 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector) drm_connector_register(connector); + if (aconnector->mst_connected) + dm_dp_mst_link_status_reset(connector); } static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 2da851b40042..8cf51da26657 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -31,5 +31,6 @@ struct amdgpu_dm_connector; void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, struct amdgpu_dm_connector *aconnector); +void dm_dp_mst_dc_sink_create(struct drm_connector *connector); #endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 5df8fd5b537c..56e549249134 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -41,6 +41,10 @@ unsigned long long dm_get_timestamp(struct dc_context *ctx) return 0; } +void dm_perf_trace_timestamp(const char *func_name, unsigned int line) +{ +} + bool dm_write_persistent_data(struct dc_context *ctx, const struct dc_sink *sink, const char *module_name, @@ -131,11 +135,12 @@ bool dm_pp_apply_display_requirements( adev->pm.pm_display_cfg.min_bus_bandwidth = 0; /* TODO: complete implementation of - * amd_powerplay_display_configuration_change(). + * pp_display_configuration_change(). * Follow example of: * PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c * PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */ - amd_powerplay_display_configuration_change( + if (adev->powerplay.pp_funcs->display_configuration_change) + adev->powerplay.pp_funcs->display_configuration_change( adev->powerplay.pp_handle, &adev->pm.pm_display_cfg); @@ -264,22 +269,26 @@ bool dm_pp_get_clock_levels_by_type( struct amd_pp_simple_clock_info validation_clks = { 0 }; uint32_t i; - if (amd_powerplay_get_clock_by_type(pp_handle, + if (adev->powerplay.pp_funcs->get_clock_by_type) { + if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle, dc_to_pp_clock_type(clk_type), &pp_clks)) { /* Error in pplib. Provide default values. */ - get_default_clock_levels(clk_type, dc_clks); - return true; + get_default_clock_levels(clk_type, dc_clks); + return true; + } } pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type); - if (amd_powerplay_get_display_mode_validation_clocks(pp_handle, - &validation_clks)) { - /* Error in pplib. Provide default values. */ - DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n"); - validation_clks.engine_max_clock = 72000; - validation_clks.memory_max_clock = 80000; - validation_clks.level = 0; + if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks) { + if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks( + pp_handle, &validation_clks)) { + /* Error in pplib. Provide default values. */ + DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n"); + validation_clks.engine_max_clock = 72000; + validation_clks.memory_max_clock = 80000; + validation_clks.level = 0; + } } DRM_INFO("DM_PPLIB: Validation clocks:\n"); |