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 | 196 |
1 files changed, 119 insertions, 77 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 075429bea427..b30656959fd8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -76,7 +76,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_dp_mst_helper.h> +#include <drm/dp/drm_dp_mst_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_edid.h> @@ -114,6 +114,10 @@ MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB); MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY_DMUB); #define FIRMWARE_YELLOW_CARP_DMUB "amdgpu/yellow_carp_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP_DMUB); +#define FIRMWARE_DCN_315_DMUB "amdgpu/dcn_3_1_5_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_DCN_315_DMUB); +#define FIRMWARE_DCN316_DMUB "amdgpu/dcn_3_1_6_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_DCN316_DMUB); #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU); @@ -1027,7 +1031,6 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) const unsigned char *fw_inst_const, *fw_bss_data; uint32_t i, fw_inst_const_size, fw_bss_data_size; bool has_hw_support; - struct dc *dc = adev->dm.dc; if (!dmub_srv) /* DMUB isn't supported on the ASIC. */ @@ -1119,14 +1122,12 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) for (i = 0; i < fb_info->num_fb; ++i) hw_params.fb[i] = &fb_info->fb[i]; - switch (adev->asic_type) { - case CHIP_YELLOW_CARP: - if (dc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_A0) { - hw_params.dpia_supported = true; + switch (adev->ip_versions[DCE_HWIP][0]) { + case IP_VERSION(3, 1, 3): /* Only for this asic hw internal rev B0 */ + hw_params.dpia_supported = true; #if defined(CONFIG_DRM_AMD_DC_DCN) - hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia; + hw_params.disable_dpia = adev->dm.dc->debug.dpia_debug.bits.disable_dpia; #endif - } break; default: break; @@ -1442,6 +1443,25 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; + switch (adev->ip_versions[DCE_HWIP][0]) { + case IP_VERSION(2, 1, 0): + switch (adev->dm.dmcub_fw_version) { + case 0: /* development */ + case 0x1: /* linux-firmware.git hash 6d9f399 */ + case 0x01000000: /* linux-firmware.git hash 9a0b0f4 */ + init_data.flags.disable_dmcu = false; + break; + default: + init_data.flags.disable_dmcu = true; + } + break; + case IP_VERSION(2, 0, 3): + init_data.flags.disable_dmcu = true; + break; + default: + break; + } + switch (adev->asic_type) { case CHIP_CARRIZO: case CHIP_STONEY: @@ -1449,34 +1469,30 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) break; default: switch (adev->ip_versions[DCE_HWIP][0]) { - case IP_VERSION(2, 1, 0): - init_data.flags.gpu_vm_support = true; - switch (adev->dm.dmcub_fw_version) { - case 0: /* development */ - case 0x1: /* linux-firmware.git hash 6d9f399 */ - case 0x01000000: /* linux-firmware.git hash 9a0b0f4 */ - init_data.flags.disable_dmcu = false; - break; - default: - init_data.flags.disable_dmcu = true; - } - break; case IP_VERSION(1, 0, 0): case IP_VERSION(1, 0, 1): + /* enable S/G on PCO and RV2 */ + if ((adev->apu_flags & AMD_APU_IS_RAVEN2) || + (adev->apu_flags & AMD_APU_IS_PICASSO)) + init_data.flags.gpu_vm_support = true; + break; + case IP_VERSION(2, 1, 0): case IP_VERSION(3, 0, 1): case IP_VERSION(3, 1, 2): case IP_VERSION(3, 1, 3): + case IP_VERSION(3, 1, 5): + case IP_VERSION(3, 1, 6): init_data.flags.gpu_vm_support = true; break; - case IP_VERSION(2, 0, 3): - init_data.flags.disable_dmcu = true; - break; default: break; } break; } + if (init_data.flags.gpu_vm_support) + adev->mode_info.gpu_vm_support = true; + if (amdgpu_dc_feature_mask & DC_FBC_MASK) init_data.flags.fbc_support = true; @@ -1496,10 +1512,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) init_data.flags.allow_lttpr_non_transparent_mode.bits.DP2_0 = true; #endif - init_data.flags.power_down_display_on_boot = true; + init_data.flags.seamless_boot_edp_requested = false; if (check_seamless_boot_capability(adev)) { - init_data.flags.power_down_display_on_boot = false; + init_data.flags.seamless_boot_edp_requested = true; init_data.flags.allow_seamless_boot_optimization = true; DRM_INFO("Seamless boot condition check passed\n"); } @@ -1804,6 +1820,8 @@ static int load_dmcu_fw(struct amdgpu_device *adev) case IP_VERSION(3, 0, 1): case IP_VERSION(3, 1, 2): case IP_VERSION(3, 1, 3): + case IP_VERSION(3, 1, 5): + case IP_VERSION(3, 1, 6): return 0; default: break; @@ -1919,7 +1937,14 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) dmub_asic = (adev->external_rev_id == YELLOW_CARP_B0) ? DMUB_ASIC_DCN31B : DMUB_ASIC_DCN31; fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB; break; - + case IP_VERSION(3, 1, 5): + dmub_asic = DMUB_ASIC_DCN315; + fw_name_dmub = FIRMWARE_DCN_315_DMUB; + break; + case IP_VERSION(3, 1, 6): + dmub_asic = DMUB_ASIC_DCN316; + fw_name_dmub = FIRMWARE_DCN316_DMUB; + break; default: /* ASIC doesn't support DMUB. */ return 0; @@ -2179,12 +2204,8 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; int ret = 0; - if (!is_support_sw_smu(adev)) - return 0; - /* This interface is for dGPU Navi1x.Linux dc-pplib interface depends * on window driver dc implementation. * For Navi1x, clock settings of dcn watermarks are fixed. the settings @@ -2223,7 +2244,7 @@ static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev) return 0; } - ret = smu_write_watermarks_table(smu); + ret = amdgpu_dpm_write_watermarks_table(adev); if (ret) { DRM_ERROR("Failed to update WMTABLE!\n"); return ret; @@ -2413,7 +2434,7 @@ static int dm_suspend(void *handle) return 0; } -static struct amdgpu_dm_connector * +struct amdgpu_dm_connector * amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state, struct drm_crtc *crtc) { @@ -2613,10 +2634,13 @@ static int dm_resume(void *handle) * before the 0 streams commit. * * DC expects that link encoder assignments are *not* valid - * when committing a state, so as a workaround it needs to be - * cleared here. + * when committing a state, so as a workaround we can copy + * off of the current state. + * + * We lose the previous assignments, but we had already + * commit 0 streams anyway. */ - link_enc_cfg_init(dm->dc, dc_state); + link_enc_cfg_copy(adev->dm.dc->current_state, dc_state); if (dc_enable_dmub_notifications(adev->dm.dc)) amdgpu_dm_outbox_init(adev); @@ -3730,8 +3754,8 @@ static int register_outbox_irq_handlers(struct amdgpu_device *adev) * * This should only be called during atomic check. */ -static int dm_atomic_get_state(struct drm_atomic_state *state, - struct dm_atomic_state **dm_state) +int dm_atomic_get_state(struct drm_atomic_state *state, + struct dm_atomic_state **dm_state) { struct drm_device *dev = state->dev; struct amdgpu_device *adev = drm_to_adev(dev); @@ -4231,6 +4255,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(3, 0, 0): case IP_VERSION(3, 1, 2): case IP_VERSION(3, 1, 3): + case IP_VERSION(3, 1, 5): + case IP_VERSION(3, 1, 6): case IP_VERSION(2, 1, 0): if (register_outbox_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); @@ -4247,6 +4273,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) switch (adev->ip_versions[DCE_HWIP][0]) { case IP_VERSION(3, 1, 2): case IP_VERSION(3, 1, 3): + case IP_VERSION(3, 1, 5): + case IP_VERSION(3, 1, 6): psr_feature_enabled = true; break; default: @@ -4364,6 +4392,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(3, 0, 1): case IP_VERSION(3, 1, 2): case IP_VERSION(3, 1, 3): + case IP_VERSION(3, 1, 5): + case IP_VERSION(3, 1, 6): if (dcn10_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); goto fail; @@ -4549,6 +4579,8 @@ static int dm_early_init(void *handle) case IP_VERSION(2, 1, 0): case IP_VERSION(3, 1, 2): case IP_VERSION(3, 1, 3): + case IP_VERSION(3, 1, 5): + case IP_VERSION(3, 1, 6): adev->mode_info.num_crtc = 4; adev->mode_info.num_hpd = 4; adev->mode_info.num_dig = 4; @@ -5221,6 +5253,8 @@ get_plane_modifiers(const struct amdgpu_device *adev, unsigned int plane_type, u case AMDGPU_FAMILY_NV: case AMDGPU_FAMILY_VGH: case AMDGPU_FAMILY_YC: + case AMDGPU_FAMILY_GC_10_3_6: + case AMDGPU_FAMILY_GC_10_3_7: if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0)) add_gfx10_3_modifiers(adev, mods, &size, &capacity); else @@ -5857,7 +5891,7 @@ static void fill_stream_properties_from_drm_display_mode( else if (drm_mode_is_420_also(info, mode_in) && aconnector->force_yuv420_output) timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; - else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) + else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR444) && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; else @@ -6187,7 +6221,7 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, if (stream->link && stream->link->local_sink) max_dsc_target_bpp_limit_override = stream->link->local_sink->edid_caps.panel_patch.max_dsc_target_bpp_limit; - + /* 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); @@ -6326,7 +6360,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector, } } - aconnector->freesync_vid_base = *m_pref; + drm_mode_copy(&aconnector->freesync_vid_base, m_pref); return m_pref; } @@ -6436,12 +6470,11 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, */ DRM_DEBUG_DRIVER("No preferred mode found\n"); } else { - recalculate_timing = amdgpu_freesync_vid_mode && - is_freesync_video_mode(&mode, aconnector); + recalculate_timing = is_freesync_video_mode(&mode, aconnector); if (recalculate_timing) { freesync_mode = get_highest_refresh_rate_mode(aconnector, false); - saved_mode = mode; - mode = *freesync_mode; + drm_mode_copy(&saved_mode, &mode); + drm_mode_copy(&mode, freesync_mode); } else { decide_crtc_timing_for_drm_display_mode( &mode, preferred_mode, scale); @@ -6500,7 +6533,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) stream->use_vsc_sdp_for_colorimetry = true; } - mod_build_vsc_infopacket(stream, &stream->vsc_infopacket); + mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space); aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; } @@ -7011,7 +7044,7 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector) create_eml_sink(aconnector); } -static struct dc_stream_state * +struct dc_stream_state * create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state, @@ -7895,6 +7928,9 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, if (res) return res; + if (modifiers == NULL) + adev_to_drm(dm->adev)->mode_config.fb_modifiers_not_supported = true; + res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs, &dm_plane_funcs, formats, num_formats, modifiers, plane->type, NULL); @@ -8144,6 +8180,9 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, mode = amdgpu_dm_create_common_mode(encoder, common_modes[i].name, common_modes[i].w, common_modes[i].h); + if (!mode) + continue; + drm_mode_probed_add(connector, mode); amdgpu_dm_connector->num_modes++; } @@ -8305,7 +8344,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); - if (!(amdgpu_freesync_vid_mode && edid)) + if (!edid) return; if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) @@ -8372,7 +8411,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, break; case DRM_MODE_CONNECTOR_DisplayPort: aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; - link->link_enc = dp_get_link_enc(link); + link->link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link->link_enc); if (link->link_enc) aconnector->base.ycbcr_420_allowed = @@ -10142,27 +10181,27 @@ static bool is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state, struct drm_crtc_state *new_crtc_state) { - struct drm_display_mode old_mode, new_mode; + const struct drm_display_mode *old_mode, *new_mode; if (!old_crtc_state || !new_crtc_state) return false; - old_mode = old_crtc_state->mode; - new_mode = new_crtc_state->mode; - - if (old_mode.clock == new_mode.clock && - old_mode.hdisplay == new_mode.hdisplay && - old_mode.vdisplay == new_mode.vdisplay && - old_mode.htotal == new_mode.htotal && - old_mode.vtotal != new_mode.vtotal && - old_mode.hsync_start == new_mode.hsync_start && - old_mode.vsync_start != new_mode.vsync_start && - old_mode.hsync_end == new_mode.hsync_end && - old_mode.vsync_end != new_mode.vsync_end && - old_mode.hskew == new_mode.hskew && - old_mode.vscan == new_mode.vscan && - (old_mode.vsync_end - old_mode.vsync_start) == - (new_mode.vsync_end - new_mode.vsync_start)) + old_mode = &old_crtc_state->mode; + new_mode = &new_crtc_state->mode; + + if (old_mode->clock == new_mode->clock && + old_mode->hdisplay == new_mode->hdisplay && + old_mode->vdisplay == new_mode->vdisplay && + old_mode->htotal == new_mode->htotal && + old_mode->vtotal != new_mode->vtotal && + old_mode->hsync_start == new_mode->hsync_start && + old_mode->vsync_start != new_mode->vsync_start && + old_mode->hsync_end == new_mode->hsync_end && + old_mode->vsync_end != new_mode->vsync_end && + old_mode->hskew == new_mode->hskew && + old_mode->vscan == new_mode->vscan && + (old_mode->vsync_end - old_mode->vsync_start) == + (new_mode->vsync_end - new_mode->vsync_start)) return true; return false; @@ -10183,12 +10222,12 @@ static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) { } static int dm_update_crtc_state(struct amdgpu_display_manager *dm, - struct drm_atomic_state *state, - struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state, - struct drm_crtc_state *new_crtc_state, - bool enable, - bool *lock_and_validation_needed) + struct drm_atomic_state *state, + struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state, + struct drm_crtc_state *new_crtc_state, + bool enable, + bool *lock_and_validation_needed) { struct dm_atomic_state *dm_state = NULL; struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; @@ -10272,8 +10311,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, * TODO: Refactor this function to allow this check to work * in all conditions. */ - if (amdgpu_freesync_vid_mode && - dm_new_crtc_state->stream && + if (dm_new_crtc_state->stream && is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) goto skip_modeset; @@ -10308,7 +10346,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, if (!dm_old_crtc_state->stream) goto skip_modeset; - if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream && + if (dm_new_crtc_state->stream && is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) { new_crtc_state->mode_changed = false; @@ -10320,7 +10358,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, set_freesync_fixed_config(dm_new_crtc_state); goto skip_modeset; - } else if (amdgpu_freesync_vid_mode && aconnector && + } else if (aconnector && is_freesync_video_mode(&new_crtc_state->mode, aconnector)) { struct drm_display_mode *high_mode; @@ -10858,10 +10896,13 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state, static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc) { struct drm_connector *connector; - struct drm_connector_state *conn_state; + struct drm_connector_state *conn_state, *old_conn_state; struct amdgpu_dm_connector *aconnector = NULL; int i; - for_each_new_connector_in_state(state, connector, conn_state, i) { + for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) { + if (!conn_state->crtc) + conn_state = old_conn_state; + if (conn_state->crtc != crtc) continue; @@ -10968,6 +11009,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } } + pre_validate_dsc(state, &dm_state, vars); } #endif for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |