diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_vce.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_vce.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index f46563b60921..d130432e313a 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c | |||
@@ -34,11 +34,16 @@ | |||
34 | #include "radeon_asic.h" | 34 | #include "radeon_asic.h" |
35 | #include "sid.h" | 35 | #include "sid.h" |
36 | 36 | ||
37 | /* 1 second timeout */ | ||
38 | #define VCE_IDLE_TIMEOUT_MS 1000 | ||
39 | |||
37 | /* Firmware Names */ | 40 | /* Firmware Names */ |
38 | #define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin" | 41 | #define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin" |
39 | 42 | ||
40 | MODULE_FIRMWARE(FIRMWARE_BONAIRE); | 43 | MODULE_FIRMWARE(FIRMWARE_BONAIRE); |
41 | 44 | ||
45 | static void radeon_vce_idle_work_handler(struct work_struct *work); | ||
46 | |||
42 | /** | 47 | /** |
43 | * radeon_vce_init - allocate memory, load vce firmware | 48 | * radeon_vce_init - allocate memory, load vce firmware |
44 | * | 49 | * |
@@ -55,6 +60,8 @@ int radeon_vce_init(struct radeon_device *rdev) | |||
55 | uint8_t start, mid, end; | 60 | uint8_t start, mid, end; |
56 | int i, r; | 61 | int i, r; |
57 | 62 | ||
63 | INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler); | ||
64 | |||
58 | switch (rdev->family) { | 65 | switch (rdev->family) { |
59 | case CHIP_BONAIRE: | 66 | case CHIP_BONAIRE: |
60 | case CHIP_KAVERI: | 67 | case CHIP_KAVERI: |
@@ -220,6 +227,59 @@ int radeon_vce_resume(struct radeon_device *rdev) | |||
220 | } | 227 | } |
221 | 228 | ||
222 | /** | 229 | /** |
230 | * radeon_vce_idle_work_handler - power off VCE | ||
231 | * | ||
232 | * @work: pointer to work structure | ||
233 | * | ||
234 | * power of VCE when it's not used any more | ||
235 | */ | ||
236 | static void radeon_vce_idle_work_handler(struct work_struct *work) | ||
237 | { | ||
238 | struct radeon_device *rdev = | ||
239 | container_of(work, struct radeon_device, vce.idle_work.work); | ||
240 | |||
241 | if ((radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE1_INDEX) == 0) && | ||
242 | (radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE2_INDEX) == 0)) { | ||
243 | if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { | ||
244 | radeon_dpm_enable_vce(rdev, false); | ||
245 | } else { | ||
246 | radeon_set_vce_clocks(rdev, 0, 0); | ||
247 | } | ||
248 | } else { | ||
249 | schedule_delayed_work(&rdev->vce.idle_work, | ||
250 | msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS)); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * radeon_vce_note_usage - power up VCE | ||
256 | * | ||
257 | * @rdev: radeon_device pointer | ||
258 | * | ||
259 | * Make sure VCE is powerd up when we want to use it | ||
260 | */ | ||
261 | void radeon_vce_note_usage(struct radeon_device *rdev) | ||
262 | { | ||
263 | bool streams_changed = false; | ||
264 | bool set_clocks = !cancel_delayed_work_sync(&rdev->vce.idle_work); | ||
265 | set_clocks &= schedule_delayed_work(&rdev->vce.idle_work, | ||
266 | msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS)); | ||
267 | |||
268 | if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { | ||
269 | /* XXX figure out if the streams changed */ | ||
270 | streams_changed = false; | ||
271 | } | ||
272 | |||
273 | if (set_clocks || streams_changed) { | ||
274 | if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { | ||
275 | radeon_dpm_enable_vce(rdev, true); | ||
276 | } else { | ||
277 | radeon_set_vce_clocks(rdev, 53300, 40000); | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /** | ||
223 | * radeon_vce_free_handles - free still open VCE handles | 283 | * radeon_vce_free_handles - free still open VCE handles |
224 | * | 284 | * |
225 | * @rdev: radeon_device pointer | 285 | * @rdev: radeon_device pointer |
@@ -235,6 +295,8 @@ void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp) | |||
235 | if (!handle || rdev->vce.filp[i] != filp) | 295 | if (!handle || rdev->vce.filp[i] != filp) |
236 | continue; | 296 | continue; |
237 | 297 | ||
298 | radeon_vce_note_usage(rdev); | ||
299 | |||
238 | r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX, | 300 | r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX, |
239 | handle, NULL); | 301 | handle, NULL); |
240 | if (r) | 302 | if (r) |