Commit 9862ef7b authored by Roman Li's avatar Roman Li Committed by Alex Deucher

drm/amd/display: Use periodic detection for ipx/headless

[WHY]
Hotplug is not detected in headless (no eDP) mode on dcn35x.
With no display dcn35x goes to IPS2 powersaving state where HPD interrupt
is not handled.

[HOW]
Use idle worker thread for periodic detection of HPD in headless mode.
Reviewed-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarAlex Hung <alex.hung@amd.com>
Signed-off-by: default avatarRoman Li <roman.li@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 58acedd7
......@@ -989,4 +989,7 @@ void *dm_allocate_gpu_mem(struct amdgpu_device *adev,
enum dc_gpu_mem_alloc_type type,
size_t size,
long long *addr);
bool amdgpu_dm_is_headless(struct amdgpu_device *adev);
#endif /* __AMDGPU_DM_H__ */
......@@ -162,33 +162,63 @@ static void amdgpu_dm_crtc_set_panel_sr_feature(
}
}
bool amdgpu_dm_is_headless(struct amdgpu_device *adev)
{
struct drm_connector *connector;
struct drm_connector_list_iter iter;
struct drm_device *dev;
bool is_headless = true;
if (adev == NULL)
return true;
dev = adev->dm.ddev;
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
if (connector->status == connector_status_connected) {
is_headless = false;
break;
}
}
drm_connector_list_iter_end(&iter);
return is_headless;
}
static void amdgpu_dm_idle_worker(struct work_struct *work)
{
struct idle_workqueue *idle_work;
idle_work = container_of(work, struct idle_workqueue, work);
idle_work->dm->idle_workqueue->running = true;
fsleep(HPD_DETECTION_PERIOD_uS);
mutex_lock(&idle_work->dm->dc_lock);
while (idle_work->enable) {
if (!idle_work->dm->dc->idle_optimizations_allowed)
fsleep(HPD_DETECTION_PERIOD_uS);
mutex_lock(&idle_work->dm->dc_lock);
if (!idle_work->dm->dc->idle_optimizations_allowed) {
mutex_unlock(&idle_work->dm->dc_lock);
break;
}
dc_allow_idle_optimizations(idle_work->dm->dc, false);
mutex_unlock(&idle_work->dm->dc_lock);
fsleep(HPD_DETECTION_TIME_uS);
mutex_lock(&idle_work->dm->dc_lock);
if (!amdgpu_dm_psr_is_active_allowed(idle_work->dm))
if (!amdgpu_dm_is_headless(idle_work->dm->adev) &&
!amdgpu_dm_psr_is_active_allowed(idle_work->dm)) {
mutex_unlock(&idle_work->dm->dc_lock);
break;
}
dc_allow_idle_optimizations(idle_work->dm->dc, true);
if (idle_work->enable)
dc_allow_idle_optimizations(idle_work->dm->dc, true);
mutex_unlock(&idle_work->dm->dc_lock);
fsleep(HPD_DETECTION_PERIOD_uS);
mutex_lock(&idle_work->dm->dc_lock);
}
mutex_unlock(&idle_work->dm->dc_lock);
idle_work->dm->idle_workqueue->running = false;
}
......
......@@ -1239,8 +1239,11 @@ void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable)
{
struct amdgpu_device *adev = ctx->driver_context;
if (adev->dm.idle_workqueue)
if (adev->dm.idle_workqueue) {
adev->dm.idle_workqueue->enable = enable;
if (enable && !adev->dm.idle_workqueue->running && amdgpu_dm_is_headless(adev))
schedule_work(&adev->dm.idle_workqueue->work);
}
}
void dm_helpers_dp_mst_update_branch_bandwidth(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment