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 | 218 |
1 files changed, 50 insertions, 168 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 6fda0dfb78f8..d3a2a5ff57e9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -58,6 +58,7 @@ #if defined(CONFIG_DEBUG_FS) #include "amdgpu_dm_debugfs.h" #endif +#include "amdgpu_dm_psr.h" #include "ivsrcid/ivsrcid_vislands30.h" @@ -109,10 +110,8 @@ MODULE_FIRMWARE(FIRMWARE_VANGOGH_DMUB); MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB); #define FIRMWARE_BEIGE_GOBY_DMUB "amdgpu/beige_goby_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY_DMUB); -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) #define FIRMWARE_YELLOW_CARP_DMUB "amdgpu/yellow_carp_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP_DMUB); -#endif #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU); @@ -213,12 +212,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, static void handle_cursor_update(struct drm_plane *plane, struct drm_plane_state *old_plane_state); -static void amdgpu_dm_set_psr_caps(struct dc_link *link); -static bool amdgpu_dm_psr_enable(struct dc_stream_state *stream); -static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream); -static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream); -static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm); - static const struct drm_format_info * amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd); @@ -1150,16 +1143,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id)) init_data.flags.disable_dmcu = true; break; -#if defined(CONFIG_DRM_AMD_DC_DCN) case CHIP_VANGOGH: - init_data.flags.gpu_vm_support = true; - break; -#endif -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) case CHIP_YELLOW_CARP: init_data.flags.gpu_vm_support = true; break; -#endif default: break; } @@ -1173,6 +1160,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_dc_feature_mask & DC_DISABLE_FRACTIONAL_PWM_MASK) init_data.flags.disable_fractional_pwm = true; + if (amdgpu_dc_feature_mask & DC_EDP_NO_POWER_SEQUENCING) + init_data.flags.edp_no_power_sequencing = true; + init_data.flags.power_down_display_on_boot = true; INIT_LIST_HEAD(&adev->dm.da_list); @@ -1416,9 +1406,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev) case CHIP_DIMGREY_CAVEFISH: case CHIP_BEIGE_GOBY: case CHIP_VANGOGH: -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) case CHIP_YELLOW_CARP: -#endif return 0; case CHIP_NAVI12: fw_name_dmcu = FIRMWARE_NAVI12_DMCU; @@ -1537,12 +1525,10 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) dmub_asic = DMUB_ASIC_DCN303; fw_name_dmub = FIRMWARE_BEIGE_GOBY_DMUB; break; -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) case CHIP_YELLOW_CARP: dmub_asic = DMUB_ASIC_DCN31; fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB; break; -#endif default: /* ASIC doesn't support DMUB. */ @@ -2237,7 +2223,7 @@ static int dm_resume(void *handle) = 0xffffffff; } } -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) +#if defined(CONFIG_DRM_AMD_DC_DCN) /* * Resource allocation happens for link encoders for newer ASIC in * dc_validate_global_state, so we need to revalidate it. @@ -3791,9 +3777,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_SIENNA_CICHLID: case CHIP_NAVY_FLOUNDER: -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) case CHIP_YELLOW_CARP: -#endif case CHIP_RENOIR: if (register_outbox_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); @@ -3898,9 +3882,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_DIMGREY_CAVEFISH: case CHIP_BEIGE_GOBY: case CHIP_VANGOGH: -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) case CHIP_YELLOW_CARP: -#endif if (dcn10_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); goto fail; @@ -4072,13 +4054,11 @@ static int dm_early_init(void *handle) adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; break; -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) case CHIP_YELLOW_CARP: adev->mode_info.num_crtc = 4; adev->mode_info.num_hpd = 4; adev->mode_info.num_dig = 4; break; -#endif case CHIP_NAVI14: case CHIP_DIMGREY_CAVEFISH: adev->mode_info.num_crtc = 5; @@ -4316,9 +4296,7 @@ fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev, adev->asic_type == CHIP_NAVY_FLOUNDER || adev->asic_type == CHIP_DIMGREY_CAVEFISH || adev->asic_type == CHIP_BEIGE_GOBY || -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) adev->asic_type == CHIP_YELLOW_CARP || -#endif adev->asic_type == CHIP_VANGOGH) tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs; } @@ -5651,6 +5629,36 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, } #endif +/** + * DOC: FreeSync Video + * + * When a userspace application wants to play a video, the content follows a + * standard format definition that usually specifies the FPS for that format. + * The below list illustrates some video format and the expected FPS, + * respectively: + * + * - TV/NTSC (23.976 FPS) + * - Cinema (24 FPS) + * - TV/PAL (25 FPS) + * - TV/NTSC (29.97 FPS) + * - TV/NTSC (30 FPS) + * - Cinema HFR (48 FPS) + * - TV/PAL (50 FPS) + * - Commonly used (60 FPS) + * - Multiples of 24 (48,72,96 FPS) + * + * The list of standards video format is not huge and can be added to the + * connector modeset list beforehand. With that, userspace can leverage + * FreeSync to extends the front porch in order to attain the target refresh + * rate. Such a switch will happen seamlessly, without screen blanking or + * reprogramming of the output in any other way. If the userspace requests a + * modesetting change compatible with FreeSync modes that only differ in the + * refresh rate, DC will skip the full update and avoid blink during the + * transition. For example, the video player can change the modesetting from + * 60Hz to 30Hz for playing TV/NTSC content when it goes full screen without + * causing any display blink. This same concept can be applied to a mode + * setting change. + */ static struct drm_display_mode * get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector, bool use_probed_modes) @@ -5875,6 +5883,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, stream->use_vsc_sdp_for_colorimetry = true; } mod_build_vsc_infopacket(stream, &stream->vsc_infopacket); + aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; + } finish: dc_sink_release(sink); @@ -8688,7 +8698,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, else if ((acrtc_state->update_type == UPDATE_TYPE_FAST) && acrtc_state->stream->link->psr_settings.psr_feature_enabled && !acrtc_state->stream->link->psr_settings.psr_allow_active) { - amdgpu_dm_psr_enable(acrtc_state->stream); + struct amdgpu_dm_connector *aconn = (struct amdgpu_dm_connector *) + acrtc_state->stream->dm_stream_context; + + if (aconn->psr_skip_count > 0) + aconn->psr_skip_count--; + else + amdgpu_dm_psr_enable(acrtc_state->stream); } mutex_unlock(&dm->dc_lock); @@ -9175,7 +9191,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) /* restore the backlight level */ - if (dm->backlight_dev) + if (dm->backlight_dev && (amdgpu_dm_backlight_get_level(dm) != dm->brightness[0])) amdgpu_dm_backlight_set_level(dm, dm->brightness[0]); #endif /* @@ -10105,7 +10121,7 @@ static int validate_overlay(struct drm_atomic_state *state) int i; struct drm_plane *plane; struct drm_plane_state *new_plane_state; - struct drm_plane_state *primary_state, *cursor_state, *overlay_state = NULL; + struct drm_plane_state *primary_state, *overlay_state = NULL; /* Check if primary plane is contained inside overlay */ for_each_new_plane_in_state_reverse(state, plane, new_plane_state, i) { @@ -10135,14 +10151,6 @@ 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 || @@ -10245,6 +10253,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, dm_old_crtc_state->dsc_force_changed == false) continue; + ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); + if (ret) + goto fail; + if (!new_crtc_state->enable) continue; @@ -10725,136 +10737,6 @@ update: freesync_capable); } -static void amdgpu_dm_set_psr_caps(struct dc_link *link) -{ - uint8_t dpcd_data[EDP_PSR_RECEIVER_CAP_SIZE]; - - if (!(link->connector_signal & SIGNAL_TYPE_EDP)) - return; - if (link->type == dc_connection_none) - return; - if (dm_helpers_dp_read_dpcd(NULL, link, DP_PSR_SUPPORT, - dpcd_data, sizeof(dpcd_data))) { - link->dpcd_caps.psr_caps.psr_version = dpcd_data[0]; - - if (dpcd_data[0] == 0) { - link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; - link->psr_settings.psr_feature_enabled = false; - } else { - link->psr_settings.psr_version = DC_PSR_VERSION_1; - link->psr_settings.psr_feature_enabled = true; - } - - DRM_INFO("PSR support:%d\n", link->psr_settings.psr_feature_enabled); - } -} - -/* - * amdgpu_dm_link_setup_psr() - configure psr link - * @stream: stream state - * - * Return: true if success - */ -static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream) -{ - struct dc_link *link = NULL; - struct psr_config psr_config = {0}; - struct psr_context psr_context = {0}; - bool ret = false; - - if (stream == NULL) - return false; - - link = stream->link; - - psr_config.psr_version = link->dpcd_caps.psr_caps.psr_version; - - if (psr_config.psr_version > 0) { - psr_config.psr_exit_link_training_required = 0x1; - psr_config.psr_frame_capture_indication_req = 0; - psr_config.psr_rfb_setup_time = 0x37; - psr_config.psr_sdp_transmit_line_num_deadline = 0x20; - psr_config.allow_smu_optimizations = 0x0; - - ret = dc_link_setup_psr(link, stream, &psr_config, &psr_context); - - } - DRM_DEBUG_DRIVER("PSR link: %d\n", link->psr_settings.psr_feature_enabled); - - return ret; -} - -/* - * amdgpu_dm_psr_enable() - enable psr f/w - * @stream: stream state - * - * Return: true if success - */ -bool amdgpu_dm_psr_enable(struct dc_stream_state *stream) -{ - struct dc_link *link = stream->link; - unsigned int vsync_rate_hz = 0; - struct dc_static_screen_params params = {0}; - /* Calculate number of static frames before generating interrupt to - * enter PSR. - */ - // Init fail safe of 2 frames static - unsigned int num_frames_static = 2; - - DRM_DEBUG_DRIVER("Enabling psr...\n"); - - vsync_rate_hz = div64_u64(div64_u64(( - stream->timing.pix_clk_100hz * 100), - stream->timing.v_total), - stream->timing.h_total); - - /* Round up - * Calculate number of frames such that at least 30 ms of time has - * passed. - */ - if (vsync_rate_hz != 0) { - unsigned int frame_time_microsec = 1000000 / vsync_rate_hz; - num_frames_static = (30000 / frame_time_microsec) + 1; - } - - params.triggers.cursor_update = true; - params.triggers.overlay_update = true; - params.triggers.surface_update = true; - params.num_frames = num_frames_static; - - dc_stream_set_static_screen_params(link->ctx->dc, - &stream, 1, - ¶ms); - - return dc_link_set_psr_allow_active(link, true, false, false); -} - -/* - * amdgpu_dm_psr_disable() - disable psr f/w - * @stream: stream state - * - * Return: true if success - */ -static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) -{ - - DRM_DEBUG_DRIVER("Disabling psr...\n"); - - return dc_link_set_psr_allow_active(stream->link, false, true, false); -} - -/* - * amdgpu_dm_psr_disable() - disable psr f/w - * if psr is enabled on any stream - * - * Return: true if success - */ -static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm) -{ - DRM_DEBUG_DRIVER("Disabling psr if psr is enabled on any stream\n"); - return dc_set_psr_allow_active(dm->dc, false); -} - void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) { struct amdgpu_device *adev = drm_to_adev(dev); |
