diff options
author | Cristian Ciocaltea <cristian.ciocaltea@collabora.com> | 2023-09-13 00:41:59 +0300 |
---|---|---|
committer | Cristian Ciocaltea <cristian.ciocaltea@collabora.com> | 2023-09-13 00:41:59 +0300 |
commit | 1dbcc906d9e32d5b6b679b7f4cb6aeb228b29540 (patch) | |
tree | 165851c6936396f7e824cf03deb3b580032ea53a /drivers/gpu/drm | |
parent | 90bc7b31b51da81f1457e27227f0acc3d6ed93e9 (diff) | |
parent | a7249215f71f45d7b4ba94557e00310a3dbec977 (diff) | |
download | linux-1dbcc906d9e32d5b6b679b7f4cb6aeb228b29540.tar.gz |
Merge branch 6.1/features/amd-drm-extra
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 193 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/link/link_detection.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_atomic_uapi.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_ioctl.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_kms.c | 1 |
13 files changed, 199 insertions, 81 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index b8633df418d4..77a1bedaee98 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -346,8 +346,6 @@ struct amdgpu_mode_info { const enum drm_plane_type *plane_type; }; -#define AMDGPU_MAX_BL_LEVEL 0xFF - struct amdgpu_backlight_privdata { struct amdgpu_encoder *encoder; uint8_t negative; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index 18ae9433e463..37cb6e7ba47a 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -39,6 +39,10 @@ #include <linux/backlight.h> #include "bif/bif_4_1_d.h" + +/* Maximum backlight level. */ +#define AMDGPU_ATOM_MAX_BL_LEVEL 0xFF + u8 amdgpu_atombios_encoder_get_backlight_level_from_reg(struct amdgpu_device *adev) { @@ -127,8 +131,8 @@ static u8 amdgpu_atombios_encoder_backlight_level(struct backlight_device *bd) /* Convert brightness to hardware level */ if (bd->props.brightness < 0) level = 0; - else if (bd->props.brightness > AMDGPU_MAX_BL_LEVEL) - level = AMDGPU_MAX_BL_LEVEL; + else if (bd->props.brightness > AMDGPU_ATOM_MAX_BL_LEVEL) + level = AMDGPU_ATOM_MAX_BL_LEVEL; else level = bd->props.brightness; @@ -198,7 +202,7 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode } memset(&props, 0, sizeof(props)); - props.max_brightness = AMDGPU_MAX_BL_LEVEL; + props.max_brightness = AMDGPU_ATOM_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", dev->primary->index); 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 8fb33fe87866..5b99e71eb4d2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -146,6 +146,9 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU); /* Number of bytes in PSP footer for firmware. */ #define PSP_FOOTER_BYTES 0x100 +/* Maximum backlight level. */ +#define AMDGPU_MAX_BL_LEVEL 0xFFFF + /** * DOC: overview * @@ -2256,6 +2259,7 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true); if (ret < 0) { DRM_ERROR("DM_MST: Failed to start MST\n"); + aconnector->mst_mgr.mst_state = false; aconnector->dc_link->type = dc_connection_single; ret = dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx, @@ -2323,6 +2327,7 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) struct drm_dp_mst_topology_mgr *mgr; int ret; bool need_hotplug = false; + bool is_dp_alt_mode = false; drm_connector_list_iter_begin(dev, &iter); drm_for_each_connector_iter(connector, &iter) { @@ -2346,9 +2351,21 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) ret = drm_dp_mst_topology_mgr_resume(mgr, true); if (ret < 0) { - dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx, - aconnector->dc_link); - need_hotplug = true; + aconnector->dc_link->mst_dpcd_fail_on_resume = true; + is_dp_alt_mode = wait_for_entering_dp_alt_mode(aconnector->dc_link); + if (is_dp_alt_mode) { + do { + ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, 1); + } while (ret != 1); + msleep(50); + ret = drm_dp_mst_topology_mgr_resume(mgr, true); + } + + if (!is_dp_alt_mode || ret < 0) { + dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx, + aconnector->dc_link); + need_hotplug = true; + } } } } @@ -4002,7 +4019,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) return 0; } -#define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 12 +#define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 0 #define AMDGPU_DM_DEFAULT_MAX_BACKLIGHT 255 #define AUX_BL_DEFAULT_TRANSITION_TIME_MS 50 @@ -4020,11 +4037,27 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm, amdgpu_acpi_get_backlight_caps(&caps); if (caps.caps_valid) { dm->backlight_caps[bl_idx].caps_valid = true; + + printk(KERN_NOTICE"VLV Successfully queried backlight range over ACPI: %d %d\n", + (int) caps.min_input_signal, (int) caps.max_input_signal); + + if ( caps.min_input_signal != AMDGPU_DM_DEFAULT_MIN_BACKLIGHT || + caps.max_input_signal != AMDGPU_DM_DEFAULT_MAX_BACKLIGHT ) + { + caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; + caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; + + printk(KERN_NOTICE"VLV OVERRIDE backlight range: %d %d\n", + (int) caps.min_input_signal, (int) caps.max_input_signal); + } + if (caps.aux_support) return; dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal; dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal; } else { + printk(KERN_NOTICE"VLV ACPI does not provide backlight range, using defaults: %d %d\n", + AMDGPU_DM_DEFAULT_MIN_BACKLIGHT, AMDGPU_DM_DEFAULT_MAX_BACKLIGHT); dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; dm->backlight_caps[bl_idx].max_input_signal = @@ -4034,6 +4067,9 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm, if (dm->backlight_caps[bl_idx].aux_support) return; + printk(KERN_NOTICE"VLV Kernel built without ACPI. using backlight range defaults: %d %d\n", + AMDGPU_DM_DEFAULT_MIN_BACKLIGHT, AMDGPU_DM_DEFAULT_MAX_BACKLIGHT); + dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; #endif @@ -4065,7 +4101,7 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c if (!get_brightness_range(caps, &min, &max)) return brightness; - // Rescale 0..255 to min..max + // Rescale 0..AMDGPU_MAX_BL_LEVEL to min..max return min + DIV_ROUND_CLOSEST((max - min) * brightness, AMDGPU_MAX_BL_LEVEL); } @@ -4080,7 +4116,7 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap if (brightness < min) return 0; - // Rescale min..max to 0..255 + // Rescale min..max to 0..AMDGPU_MAX_BL_LEVEL return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min), max - min); } @@ -4092,12 +4128,16 @@ static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, struct amdgpu_dm_backlight_caps caps; struct dc_link *link; u32 brightness; + u32 prev_brightness; bool rc; amdgpu_dm_update_backlight_caps(dm, bl_idx); caps = dm->backlight_caps[bl_idx]; + prev_brightness = dm->brightness[bl_idx]; dm->brightness[bl_idx] = user_brightness; + dm->actual_brightness[bl_idx] = user_brightness; + /* update scratch register */ if (bl_idx == 0) amdgpu_atombios_scratch_regs_set_backlight_level(dm->adev, dm->brightness[bl_idx]); @@ -4116,8 +4156,8 @@ static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx); } - if (rc) - dm->actual_brightness[bl_idx] = user_brightness; + if (!rc) + dm->actual_brightness[bl_idx] = prev_brightness; } static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) @@ -4278,6 +4318,7 @@ static void setup_backlight_device(struct amdgpu_display_manager *dm, amdgpu_dm_update_backlight_caps(dm, bl_idx); dm->brightness[bl_idx] = AMDGPU_MAX_BL_LEVEL; + dm->actual_brightness[bl_idx] = AMDGPU_MAX_BL_LEVEL; dm->backlight_link[bl_idx] = link; dm->num_of_edps++; @@ -7945,7 +7986,6 @@ static inline uint32_t get_mem_type(struct drm_framebuffer *fb) } static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, - struct dc_state *dc_state, struct drm_device *dev, struct amdgpu_display_manager *dm, struct drm_crtc *pcrtc, @@ -8426,52 +8466,17 @@ static void amdgpu_dm_crtc_copy_transient_flags(struct drm_crtc_state *crtc_stat stream_state->mode_changed = drm_atomic_crtc_needs_modeset(crtc_state); } -/** - * amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation. - * @state: The atomic state to commit - * - * This will tell DC to commit the constructed DC state from atomic_check, - * programming the hardware. Any failures here implies a hardware failure, since - * atomic check should have filtered anything non-kosher. - */ -static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) +static void amdgpu_dm_commit_streams(struct drm_atomic_state *state, + struct dc_state *dc_state) { struct drm_device *dev = state->dev; struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; - struct dm_atomic_state *dm_state; - struct dc_state *dc_state = NULL, *dc_state_temp = NULL; - u32 i, j; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; - unsigned long flags; - bool wait_for_vblank = true; - struct drm_connector *connector; - struct drm_connector_state *old_con_state, *new_con_state; struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; - int crtc_disable_count = 0; bool mode_set_reset_required = false; - int r; - - trace_amdgpu_dm_atomic_commit_tail_begin(state); - - r = drm_atomic_helper_wait_for_fences(dev, state, false); - if (unlikely(r)) - DRM_ERROR("Waiting for fences timed out!"); - - drm_atomic_helper_update_legacy_modeset_state(dev, state); - drm_dp_mst_atomic_wait_for_dependencies(state); - - dm_state = dm_atomic_get_new_state(state); - if (dm_state && dm_state->context) { - dc_state = dm_state->context; - } else { - /* No state changes, retain current state. */ - dc_state_temp = dc_create_state(dm->dc); - ASSERT(dc_state_temp); - dc_state = dc_state_temp; - dc_resource_state_copy_construct_current(dm->dc, dc_state); - } + u32 i; for_each_oldnew_crtc_in_state (state, crtc, old_crtc_state, new_crtc_state, i) { @@ -8572,24 +8577,22 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) } } /* for_each_crtc_in_state() */ - if (dc_state) { - /* if there mode set or reset, disable eDP PSR */ - if (mode_set_reset_required) { - if (dm->vblank_control_workqueue) - flush_workqueue(dm->vblank_control_workqueue); + /* if there mode set or reset, disable eDP PSR */ + if (mode_set_reset_required) { + if (dm->vblank_control_workqueue) + flush_workqueue(dm->vblank_control_workqueue); - amdgpu_dm_psr_disable_all(dm); - } + amdgpu_dm_psr_disable_all(dm); + } - dm_enable_per_frame_crtc_master_sync(dc_state); - mutex_lock(&dm->dc_lock); - WARN_ON(!dc_commit_streams(dm->dc, dc_state->streams, dc_state->stream_count)); + dm_enable_per_frame_crtc_master_sync(dc_state); + mutex_lock(&dm->dc_lock); + WARN_ON(!dc_commit_streams(dm->dc, dc_state->streams, dc_state->stream_count)); - /* Allow idle optimization when vblank count is 0 for display off */ - if (dm->active_vblank_irq_count == 0) - dc_allow_idle_optimizations(dm->dc, true); - mutex_unlock(&dm->dc_lock); - } + /* Allow idle optimization when vblank count is 0 for display off */ + if (dm->active_vblank_irq_count == 0) + dc_allow_idle_optimizations(dm->dc, true); + mutex_unlock(&dm->dc_lock); for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -8609,6 +8612,44 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) acrtc->otg_inst = status->primary_otg_inst; } } +} + +/** + * amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation. + * @state: The atomic state to commit + * + * This will tell DC to commit the constructed DC state from atomic_check, + * programming the hardware. Any failures here implies a hardware failure, since + * atomic check should have filtered anything non-kosher. + */ +static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct amdgpu_device *adev = drm_to_adev(dev); + struct amdgpu_display_manager *dm = &adev->dm; + struct dm_atomic_state *dm_state; + struct dc_state *dc_state = NULL; + u32 i, j; + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; + unsigned long flags; + bool wait_for_vblank = true; + struct drm_connector *connector; + struct drm_connector_state *old_con_state, *new_con_state; + struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; + int crtc_disable_count = 0; + + trace_amdgpu_dm_atomic_commit_tail_begin(state); + + drm_atomic_helper_update_legacy_modeset_state(dev, state); + drm_dp_mst_atomic_wait_for_dependencies(state); + + dm_state = dm_atomic_get_new_state(state); + if (dm_state && dm_state->context) { + dc_state = dm_state->context; + amdgpu_dm_commit_streams(state, dc_state); + } + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); @@ -8885,8 +8926,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); if (dm_new_crtc_state->stream) - amdgpu_dm_commit_planes(state, dc_state, dev, - dm, crtc, wait_for_vblank); + amdgpu_dm_commit_planes(state, dev, dm, crtc, wait_for_vblank); } /* Update audio instances for each connector. */ @@ -8934,9 +8974,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) for (i = 0; i < crtc_disable_count; i++) pm_runtime_put_autosuspend(dev->dev); pm_runtime_mark_last_busy(dev->dev); - - if (dc_state_temp) - dc_release_state(dc_state_temp); } static int dm_force_atomic_commit(struct drm_connector *connector) @@ -9856,6 +9893,28 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state, break; } + if (new_underlying_state->rotation != new_cursor_state->rotation) { + drm_dbg_atomic(crtc->dev, "Cursor plane rotation doesn't match underlying plane\n"); + return -EINVAL; + } + + /* In theory we could probably support YUV cursors when the underlying + * plane uses a YUV format, but there's no use-case for it yet. */ + if (new_underlying_state->fb && new_underlying_state->fb->format && new_underlying_state->fb->format->is_yuv) { + drm_dbg_atomic(crtc->dev, "Cursor plane can't be used with YUV underlying plane\n"); + return -EINVAL; + } + + if (new_underlying_state->alpha != DRM_BLEND_ALPHA_OPAQUE) { + drm_dbg_atomic(crtc->dev, "Cursor plane can't be used with non-opaque underlying plane\n"); + return -EINVAL; + } + + if (new_underlying_state->pixel_blend_mode != DRM_MODE_BLEND_PREMULTI) { + drm_dbg_atomic(crtc->dev, "Cursor plane can't be used with non-premultiplied underlying plane\n"); + return -EINVAL; + } + return 0; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 6c84ca2ae373..1cc0a5348e53 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -1485,8 +1485,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; - if (dm->adev->asic_type >= CHIP_BONAIRE && - plane->type != DRM_PLANE_TYPE_CURSOR) + if (dm->adev->asic_type >= CHIP_BONAIRE) drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, supported_rotations); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7fd9f5a9e191..11e88413342e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1428,6 +1428,7 @@ struct dc_link { bool sync_lt_in_progress; bool skip_stream_reenable; bool is_internal_display; + bool mst_dpcd_fail_on_resume; /** @todo Rename. Flag an endpoint as having a programmable mapping to a DIG encoder. */ bool is_dig_mapping_flexible; bool hpd_status; /* HPD status of link without physical HPD pin. */ @@ -1849,6 +1850,7 @@ bool dc_link_is_dp_sink_present(struct dc_link *link); void dc_link_set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, struct dc_link *link); +bool wait_for_entering_dp_alt_mode(struct dc_link *link); /* Enable a test pattern in Link or PHY layer in an active link for compliance * test or debugging purpose. The test pattern will remain until next un-plug. diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d4cacb8df631..e5f4587aa40c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1766,9 +1766,29 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) break; } } - // We are trying to enable eDP, don't power down VDD - if (can_apply_edp_fast_boot) + + /* + * TO-DO: So far the code logic below only addresses single eDP case. + * For dual eDP case, there are a few things that need to be + * implemented first: + * + * 1. Change the fastboot logic above, so eDP link[0 or 1]'s + * stream[0 or 1] will all be checked. + * + * 2. Change keep_edp_vdd_on to an array, and maintain keep_edp_vdd_on + * for each eDP. + * + * Once above 2 things are completed, we can then change the logic below + * correspondingly, so dual eDP case will be fully covered. + */ + + // We are trying to enable eDP, don't power down VDD if eDP stream is existing + if ((edp_stream_num == 1 && edp_streams[0] != NULL) || can_apply_edp_fast_boot) { keep_edp_vdd_on = true; + DC_LOG_EVENT_LINK_TRAINING("Keep eDP Vdd on\n"); + } else { + DC_LOG_EVENT_LINK_TRAINING("No eDP stream enabled, turn eDP Vdd off\n"); + } } // Check seamless boot support diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index 17904de4f155..0347287a3033 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -621,7 +621,7 @@ static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid) new_edid->raw_edid, new_edid->length) == 0); } -static bool wait_for_entering_dp_alt_mode(struct dc_link *link) +bool wait_for_entering_dp_alt_mode(struct dc_link *link) { /** @@ -629,7 +629,7 @@ static bool wait_for_entering_dp_alt_mode(struct dc_link *link) * 500 microseconds * 400 tries us 200 ms **/ unsigned int sleep_time_in_microseconds = 500; - unsigned int tries_allowed = 400; + unsigned int tries_allowed = 1000; bool is_in_alt_mode; unsigned long long enter_timestamp; unsigned long long finish_timestamp; @@ -646,6 +646,11 @@ static bool wait_for_entering_dp_alt_mode(struct dc_link *link) if (!link->link_enc->funcs->is_in_alt_mode) return true; + if (link->mst_dpcd_fail_on_resume) { + tries_allowed = 3000; + link->mst_dpcd_fail_on_resume = false; + } + is_in_alt_mode = link->link_enc->funcs->is_in_alt_mode(link->link_enc); DC_LOG_DC("DP Alt mode state on HPD: %d\n", is_in_alt_mode); diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index a2bb5b916235..39333732a43d 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -639,6 +639,7 @@ static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev) dev->mode_config.max_height = dc->desc->max_height; dev->mode_config.funcs = &mode_config_funcs; dev->mode_config.async_page_flip = true; + dev->mode_config.atomic_async_page_flip_not_supported = true; return 0; } diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index c06d0639d552..945761968428 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1282,6 +1282,18 @@ static void complete_signaling(struct drm_device *dev, kfree(fence_state); } +static void +set_async_flip(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + crtc_state->async_flip = true; + } +} + int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1322,9 +1334,16 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, } if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) { - drm_dbg_atomic(dev, - "commit failed: invalid flag DRM_MODE_PAGE_FLIP_ASYNC\n"); - return -EINVAL; + if (!dev->mode_config.async_page_flip) { + drm_dbg_atomic(dev, + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported\n"); + return -EINVAL; + } + if (dev->mode_config.atomic_async_page_flip_not_supported) { + drm_dbg_atomic(dev, + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported with atomic\n"); + return -EINVAL; + } } /* can't test and expect an event at the same time. */ @@ -1422,6 +1441,9 @@ retry: if (ret) goto out; + if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) + set_async_flip(state); + if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { ret = drm_atomic_check_only(state); } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index ca2a6e6101dc..5b1591e2b46c 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -302,6 +302,11 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ case DRM_CAP_CRTC_IN_VBLANK_EVENT: req->value = 1; break; + case DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP: + req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) && + dev->mode_config.async_page_flip && + !dev->mode_config.atomic_async_page_flip_not_supported; + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 520ed321435a..f0d36f1598a6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8591,6 +8591,7 @@ static void intel_mode_config_init(struct drm_i915_private *i915) mode_config->helper_private = &intel_mode_config_funcs; mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915); + mode_config->atomic_async_page_flip_not_supported = true; /* * Maximum framebuffer dimensions, chosen to match diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index ec3ffff487fc..f497dcd9e22f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -709,6 +709,7 @@ nouveau_display_create(struct drm_device *dev) dev->mode_config.async_page_flip = false; else dev->mode_config.async_page_flip = true; + dev->mode_config.atomic_async_page_flip_not_supported = true; drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 8fbeecdf2ec4..80b64442bc25 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -1050,6 +1050,7 @@ int vc4_kms_load(struct drm_device *dev) dev->mode_config.helper_private = &vc4_mode_config_helpers; dev->mode_config.preferred_depth = 24; dev->mode_config.async_page_flip = true; + dev->mode_config.atomic_async_page_flip_not_supported = true; ret = vc4_ctm_obj_init(vc4); if (ret) |