diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 222 |
1 files changed, 140 insertions, 82 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 3267eb2e35dd..4f4c6438d245 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -28,6 +28,7 @@ #include "dm_services_types.h" #include "dc.h" +#include "dc_link_dp.h" #include "dc/inc/core_types.h" #include "dal_asic_id.h" #include "dmub/dmub_srv.h" @@ -314,10 +315,8 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev, struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; - if (otg_inst == -1) { - WARN_ON(1); + if (WARN_ON(otg_inst == -1)) return adev->mode_info.crtcs[0]; - } list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { amdgpu_crtc = to_amdgpu_crtc(crtc); @@ -396,8 +395,7 @@ static void dm_pflip_high_irq(void *interrupt_params) e = amdgpu_crtc->event; amdgpu_crtc->event = NULL; - if (!e) - WARN_ON(1); + WARN_ON(!e); vrr_active = amdgpu_dm_vrr_active_irq(amdgpu_crtc); @@ -600,14 +598,14 @@ static void dm_crtc_high_irq(void *interrupt_params) } #if defined(CONFIG_DRM_AMD_DC_DCN) +#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) /** * dm_dcn_vertical_interrupt0_high_irq() - Handles OTG Vertical interrupt0 for * DCN generation ASICs - * @interrupt params - interrupt parameters + * @interrupt_params: interrupt parameters * * Used to set crc window/read out crc value at vertical line 0 position */ -#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) { struct common_irq_params *irq_params = interrupt_params; @@ -981,7 +979,8 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu); } - adev->dm.dc->ctx->dmub_srv = dc_dmub_srv_create(adev->dm.dc, dmub_srv); + if (!adev->dm.dc->ctx->dmub_srv) + adev->dm.dc->ctx->dmub_srv = dc_dmub_srv_create(adev->dm.dc, dmub_srv); if (!adev->dm.dc->ctx->dmub_srv) { DRM_ERROR("Couldn't allocate DC DMUB server!\n"); return -ENOMEM; @@ -1335,10 +1334,7 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) } #endif - if (adev->dm.dc->ctx->dmub_srv) { - dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); - adev->dm.dc->ctx->dmub_srv = NULL; - } + dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); if (dc_enable_dmub_notifications(adev->dm.dc)) { kfree(adev->dm.dmub_notify); @@ -1715,7 +1711,6 @@ static int dm_late_init(void *handle) unsigned int linear_lut[16]; int i; struct dmcu *dmcu = NULL; - bool ret = true; dmcu = adev->dm.dc->res_pool->dmcu; @@ -1732,18 +1727,23 @@ static int dm_late_init(void *handle) * 0xFFFF x 0.01 = 0x28F */ params.min_abm_backlight = 0x28F; - /* In the case where abm is implemented on dmcub, - * dmcu object will be null. - * ABM 2.4 and up are implemented on dmcub. - */ - if (dmcu) - ret = dmcu_load_iram(dmcu, params); - else if (adev->dm.dc->ctx->dmub_srv) - ret = dmub_init_abm_config(adev->dm.dc->res_pool, params); + * dmcu object will be null. + * ABM 2.4 and up are implemented on dmcub. + */ + if (dmcu) { + if (!dmcu_load_iram(dmcu, params)) + return -EINVAL; + } else if (adev->dm.dc->ctx->dmub_srv) { + struct dc_link *edp_links[MAX_NUM_EDP]; + int edp_num; - if (!ret) - return -EINVAL; + get_edp_links(adev->dm.dc, edp_links, &edp_num); + for (i = 0; i < edp_num; i++) { + if (!dmub_init_abm_config(adev->dm.dc->res_pool, params, i)) + return -EINVAL; + } + } return detect_mst_link_for_all_connectors(adev_to_drm(adev)); } @@ -2008,7 +2008,6 @@ static int dm_suspend(void *handle) amdgpu_dm_irq_suspend(adev); - dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); return 0; @@ -2747,6 +2746,7 @@ static void handle_hpd_rx_irq(void *param) enum dc_connection_type new_connection_type = dc_connection_none; struct amdgpu_device *adev = drm_to_adev(dev); union hpd_irq_data hpd_irq_data; + bool lock_flag = 0; memset(&hpd_irq_data, 0, sizeof(hpd_irq_data)); @@ -2776,15 +2776,28 @@ static void handle_hpd_rx_irq(void *param) } } - if (!amdgpu_in_reset(adev)) { + /* + * TODO: We need the lock to avoid touching DC state while it's being + * modified during automated compliance testing, or when link loss + * happens. While this should be split into subhandlers and proper + * interfaces to avoid having to conditionally lock like this in the + * outer layer, we need this workaround temporarily to allow MST + * lightup in some scenarios to avoid timeout. + */ + if (!amdgpu_in_reset(adev) && + (hpd_rx_irq_check_link_loss_status(dc_link, &hpd_irq_data) || + hpd_irq_data.bytes.device_service_irq.bits.AUTOMATED_TEST)) { mutex_lock(&adev->dm.dc_lock); + lock_flag = 1; + } + #ifdef CONFIG_DRM_AMD_DC_HDCP result = dc_link_handle_hpd_rx_irq(dc_link, &hpd_irq_data, NULL); #else result = dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL); #endif + if (!amdgpu_in_reset(adev) && lock_flag) mutex_unlock(&adev->dm.dc_lock); - } out: if (result && !is_mst_root_connector) { @@ -3407,7 +3420,7 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) if (dm->backlight_caps.caps_valid) return; - amdgpu_acpi_get_backlight_caps(dm->adev, &caps); + amdgpu_acpi_get_backlight_caps(&caps); if (caps.caps_valid) { dm->backlight_caps.caps_valid = true; if (caps.aux_support) @@ -3499,7 +3512,7 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, rc = dc_link_set_backlight_level_nits(link[i], true, brightness[i], AUX_BL_DEFAULT_TRANSITION_TIME_MS); if (!rc) { - DRM_ERROR("DM: Failed to update backlight via AUX on eDP[%d]\n", i); + DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", i); break; } } @@ -3507,7 +3520,7 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, for (i = 0; i < dm->num_of_edps; i++) { rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness[i], 0); if (!rc) { - DRM_ERROR("DM: Failed to update backlight on eDP[%d]\n", i); + DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", i); break; } } @@ -4953,6 +4966,14 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev, case DRM_FORMAT_ABGR16161616F: plane_info->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F; break; + case DRM_FORMAT_XRGB16161616: + case DRM_FORMAT_ARGB16161616: + plane_info->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616; + break; + case DRM_FORMAT_XBGR16161616: + case DRM_FORMAT_ABGR16161616: + plane_info->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616; + break; default: DRM_ERROR( "Unsupported screen format %p4cc\n", @@ -5529,6 +5550,63 @@ static void dm_enable_per_frame_crtc_master_sync(struct dc_state *context) } } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static void update_dsc_caps(struct amdgpu_dm_connector *aconnector, + struct dc_sink *sink, struct dc_stream_state *stream, + struct dsc_dec_dpcd_caps *dsc_caps) +{ + stream->timing.flags.DSC = 0; + + if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) { + dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc, + aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw, + aconnector->dc_link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, + dsc_caps); + } +} + +static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, + struct dc_sink *sink, struct dc_stream_state *stream, + struct dsc_dec_dpcd_caps *dsc_caps) +{ + struct drm_connector *drm_connector = &aconnector->base; + uint32_t link_bandwidth_kbps; + + link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, + dc_link_get_link_cap(aconnector->dc_link)); + /* Set DSC policy according to dsc_clock_en */ + dc_dsc_policy_set_enable_dsc_when_not_needed( + aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE); + + if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) { + + if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], + dsc_caps, + aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, + 0, + link_bandwidth_kbps, + &stream->timing, + &stream->timing.dsc_cfg)) { + stream->timing.flags.DSC = 1; + DRM_DEBUG_DRIVER("%s: [%s] DSC is selected from SST RX\n", __func__, drm_connector->name); + } + } + + /* Overwrite the stream flag if DSC is enabled through debugfs */ + if (aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE) + stream->timing.flags.DSC = 1; + + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_num_slices_h) + stream->timing.dsc_cfg.num_slices_h = aconnector->dsc_settings.dsc_num_slices_h; + + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_num_slices_v) + stream->timing.dsc_cfg.num_slices_v = aconnector->dsc_settings.dsc_num_slices_v; + + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel) + stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel; +} +#endif + static struct drm_display_mode * get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector, bool use_probed_modes) @@ -5625,12 +5703,12 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, struct drm_display_mode saved_mode; struct drm_display_mode *freesync_mode = NULL; bool native_mode_found = false; - bool recalculate_timing = dm_state ? (dm_state->scaling != RMX_OFF) : false; + bool recalculate_timing = false; + bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false; int mode_refresh; int preferred_refresh = 0; #if defined(CONFIG_DRM_AMD_DC_DCN) struct dsc_dec_dpcd_caps dsc_caps; - uint32_t link_bandwidth_kbps; #endif struct dc_sink *sink = NULL; @@ -5688,7 +5766,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, */ DRM_DEBUG_DRIVER("No preferred mode found\n"); } else { - recalculate_timing |= amdgpu_freesync_vid_mode && + recalculate_timing = amdgpu_freesync_vid_mode && is_freesync_video_mode(&mode, aconnector); if (recalculate_timing) { freesync_mode = get_highest_refresh_rate_mode(aconnector, false); @@ -5696,11 +5774,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, mode = *freesync_mode; } else { decide_crtc_timing_for_drm_display_mode( - &mode, preferred_mode, - dm_state ? (dm_state->scaling != RMX_OFF) : false); - } + &mode, preferred_mode, scale); - preferred_refresh = drm_mode_vrefresh(preferred_mode); + preferred_refresh = drm_mode_vrefresh(preferred_mode); + } } if (recalculate_timing) @@ -5712,7 +5789,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, * If scaling is enabled and refresh rate didn't change * we copy the vic and polarities of the old timings */ - if (!recalculate_timing || mode_refresh != preferred_refresh) + if (!scale || mode_refresh != preferred_refresh) fill_stream_properties_from_drm_display_mode( stream, &mode, &aconnector->base, con_state, NULL, requested_bpc); @@ -5721,45 +5798,12 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, stream, &mode, &aconnector->base, con_state, old_stream, requested_bpc); - stream->timing.flags.DSC = 0; - - if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) { #if defined(CONFIG_DRM_AMD_DC_DCN) - dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc, - aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw, - aconnector->dc_link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, - &dsc_caps); - link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, - dc_link_get_link_cap(aconnector->dc_link)); - - if (aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE && dsc_caps.is_dsc_supported) { - /* Set DSC policy according to dsc_clock_en */ - dc_dsc_policy_set_enable_dsc_when_not_needed( - aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE); - - if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], - &dsc_caps, - aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, - 0, - link_bandwidth_kbps, - &stream->timing, - &stream->timing.dsc_cfg)) - stream->timing.flags.DSC = 1; - /* Overwrite the stream flag if DSC is enabled through debugfs */ - if (aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE) - stream->timing.flags.DSC = 1; - - if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_num_slices_h) - stream->timing.dsc_cfg.num_slices_h = aconnector->dsc_settings.dsc_num_slices_h; - - if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_num_slices_v) - stream->timing.dsc_cfg.num_slices_v = aconnector->dsc_settings.dsc_num_slices_v; - - if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel) - stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel; - } + /* SST DSC determination policy */ + update_dsc_caps(aconnector, sink, stream, &dsc_caps); + if (aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE && dsc_caps.is_dsc_supported) + apply_dsc_policy_for_stream(aconnector, sink, stream, &dsc_caps); #endif - } update_stream_scaling_settings(&mode, dm_state, stream); @@ -6558,9 +6602,8 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, dm_update_crtc_active_planes(crtc, crtc_state); - if (unlikely(!dm_crtc_state->stream && - modeset_required(crtc_state, NULL, dm_crtc_state->stream))) { - WARN_ON(1); + if (WARN_ON(unlikely(!dm_crtc_state->stream && + modeset_required(crtc_state, NULL, dm_crtc_state->stream)))) { return ret; } @@ -7059,6 +7102,10 @@ static const uint32_t rgb_formats[] = { DRM_FORMAT_XBGR2101010, DRM_FORMAT_ARGB2101010, DRM_FORMAT_ABGR2101010, + DRM_FORMAT_XRGB16161616, + DRM_FORMAT_XBGR16161616, + DRM_FORMAT_ARGB16161616, + DRM_FORMAT_ABGR16161616, DRM_FORMAT_XBGR8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_RGB565, @@ -8967,7 +9014,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) } status = dc_stream_get_status(dm_new_crtc_state->stream); - WARN_ON(!status); + + if (WARN_ON(!status)) + continue; + WARN_ON(!status->plane_count); /* @@ -9974,7 +10024,7 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state, if (cursor_scale_w != primary_scale_w || cursor_scale_h != primary_scale_h) { - DRM_DEBUG_ATOMIC("Cursor plane scaling doesn't match primary plane\n"); + drm_dbg_atomic(crtc->dev, "Cursor plane scaling doesn't match primary plane\n"); return -EINVAL; } @@ -10010,11 +10060,11 @@ static int validate_overlay(struct drm_atomic_state *state) { int i; struct drm_plane *plane; - struct drm_plane_state *old_plane_state, *new_plane_state; - struct drm_plane_state *primary_state, *overlay_state = NULL; + struct drm_plane_state *new_plane_state; + struct drm_plane_state *primary_state, *cursor_state, *overlay_state = NULL; /* Check if primary plane is contained inside overlay */ - for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) { + for_each_new_plane_in_state_reverse(state, plane, new_plane_state, i) { if (plane->type == DRM_PLANE_TYPE_OVERLAY) { if (drm_atomic_plane_disabling(plane->state, new_plane_state)) return 0; @@ -10041,6 +10091,14 @@ static int validate_overlay(struct drm_atomic_state *state) if (!primary_state->crtc) return 0; + /* check if cursor plane is enabled */ + cursor_state = drm_atomic_get_plane_state(state, overlay_state->crtc->cursor); + if (IS_ERR(cursor_state)) + return PTR_ERR(cursor_state); + + if (drm_atomic_plane_disabling(plane->state, cursor_state)) + return 0; + /* Perform the bounds check to ensure the overlay plane covers the primary */ if (primary_state->crtc_x < overlay_state->crtc_x || primary_state->crtc_y < overlay_state->crtc_y || |
