|
35 | 35 | #include "amdgpu_dm_trace.h" |
36 | 36 | #include "amdgpu_dm_debugfs.h" |
37 | 37 |
|
| 38 | +#define HPD_DETECTION_PERIOD_uS 5000000 |
| 39 | +#define HPD_DETECTION_TIME_uS 1000 |
| 40 | + |
38 | 41 | void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc) |
39 | 42 | { |
40 | 43 | struct drm_crtc *crtc = &acrtc->base; |
@@ -146,11 +149,65 @@ static void amdgpu_dm_crtc_set_panel_sr_feature( |
146 | 149 | struct amdgpu_dm_connector *aconn = |
147 | 150 | (struct amdgpu_dm_connector *) vblank_work->stream->dm_stream_context; |
148 | 151 |
|
149 | | - if (!aconn->disallow_edp_enter_psr) |
| 152 | + if (!aconn->disallow_edp_enter_psr) { |
| 153 | + struct amdgpu_display_manager *dm = vblank_work->dm; |
| 154 | + |
150 | 155 | amdgpu_dm_psr_enable(vblank_work->stream); |
| 156 | + if (dm->idle_workqueue && |
| 157 | + dm->dc->idle_optimizations_allowed && |
| 158 | + dm->idle_workqueue->enable && |
| 159 | + !dm->idle_workqueue->running) |
| 160 | + schedule_work(&dm->idle_workqueue->work); |
| 161 | + } |
151 | 162 | } |
152 | 163 | } |
153 | 164 |
|
| 165 | +static void amdgpu_dm_idle_worker(struct work_struct *work) |
| 166 | +{ |
| 167 | + struct idle_workqueue *idle_work; |
| 168 | + |
| 169 | + idle_work = container_of(work, struct idle_workqueue, work); |
| 170 | + idle_work->dm->idle_workqueue->running = true; |
| 171 | + fsleep(HPD_DETECTION_PERIOD_uS); |
| 172 | + mutex_lock(&idle_work->dm->dc_lock); |
| 173 | + while (idle_work->enable) { |
| 174 | + if (!idle_work->dm->dc->idle_optimizations_allowed) |
| 175 | + break; |
| 176 | + |
| 177 | + dc_allow_idle_optimizations(idle_work->dm->dc, false); |
| 178 | + |
| 179 | + mutex_unlock(&idle_work->dm->dc_lock); |
| 180 | + fsleep(HPD_DETECTION_TIME_uS); |
| 181 | + mutex_lock(&idle_work->dm->dc_lock); |
| 182 | + |
| 183 | + if (!amdgpu_dm_psr_is_active_allowed(idle_work->dm)) |
| 184 | + break; |
| 185 | + |
| 186 | + dc_allow_idle_optimizations(idle_work->dm->dc, true); |
| 187 | + mutex_unlock(&idle_work->dm->dc_lock); |
| 188 | + fsleep(HPD_DETECTION_PERIOD_uS); |
| 189 | + mutex_lock(&idle_work->dm->dc_lock); |
| 190 | + } |
| 191 | + mutex_unlock(&idle_work->dm->dc_lock); |
| 192 | + idle_work->dm->idle_workqueue->running = false; |
| 193 | +} |
| 194 | + |
| 195 | +struct idle_workqueue *idle_create_workqueue(struct amdgpu_device *adev) |
| 196 | +{ |
| 197 | + struct idle_workqueue *idle_work; |
| 198 | + |
| 199 | + idle_work = kzalloc(sizeof(*idle_work), GFP_KERNEL); |
| 200 | + if (ZERO_OR_NULL_PTR(idle_work)) |
| 201 | + return NULL; |
| 202 | + |
| 203 | + idle_work->dm = &adev->dm; |
| 204 | + idle_work->enable = false; |
| 205 | + idle_work->running = false; |
| 206 | + INIT_WORK(&idle_work->work, amdgpu_dm_idle_worker); |
| 207 | + |
| 208 | + return idle_work; |
| 209 | +} |
| 210 | + |
154 | 211 | static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work) |
155 | 212 | { |
156 | 213 | struct vblank_control_work *vblank_work = |
|
0 commit comments