diff options
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_cs.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_uvd.c | 30 |
3 files changed, 34 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5020c7c9b7cb..7935370f01af 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -1143,6 +1143,7 @@ struct radeon_uvd { | |||
1143 | uint64_t gpu_addr; | 1143 | uint64_t gpu_addr; |
1144 | atomic_t handles[RADEON_MAX_UVD_HANDLES]; | 1144 | atomic_t handles[RADEON_MAX_UVD_HANDLES]; |
1145 | struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; | 1145 | struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; |
1146 | struct delayed_work idle_work; | ||
1146 | }; | 1147 | }; |
1147 | 1148 | ||
1148 | int radeon_uvd_init(struct radeon_device *rdev); | 1149 | int radeon_uvd_init(struct radeon_device *rdev); |
@@ -1157,6 +1158,7 @@ void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo); | |||
1157 | void radeon_uvd_free_handles(struct radeon_device *rdev, | 1158 | void radeon_uvd_free_handles(struct radeon_device *rdev, |
1158 | struct drm_file *filp); | 1159 | struct drm_file *filp); |
1159 | int radeon_uvd_cs_parse(struct radeon_cs_parser *parser); | 1160 | int radeon_uvd_cs_parse(struct radeon_cs_parser *parser); |
1161 | void radeon_uvd_note_usage(struct radeon_device *rdev); | ||
1160 | 1162 | ||
1161 | struct r600_audio { | 1163 | struct r600_audio { |
1162 | int channels; | 1164 | int channels; |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index c7407074c09b..7e265a58141f 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
@@ -549,6 +549,10 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
549 | r = radeon_cs_handle_lockup(rdev, r); | 549 | r = radeon_cs_handle_lockup(rdev, r); |
550 | return r; | 550 | return r; |
551 | } | 551 | } |
552 | |||
553 | if (parser.ring == R600_RING_TYPE_UVD_INDEX) | ||
554 | radeon_uvd_note_usage(rdev); | ||
555 | |||
552 | r = radeon_cs_ib_chunk(rdev, &parser); | 556 | r = radeon_cs_ib_chunk(rdev, &parser); |
553 | if (r) { | 557 | if (r) { |
554 | goto out; | 558 | goto out; |
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 15580fb8546e..0312a7f4d768 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c | |||
@@ -36,6 +36,9 @@ | |||
36 | #include "radeon.h" | 36 | #include "radeon.h" |
37 | #include "r600d.h" | 37 | #include "r600d.h" |
38 | 38 | ||
39 | /* 1 second timeout */ | ||
40 | #define UVD_IDLE_TIMEOUT_MS 1000 | ||
41 | |||
39 | /* Firmware Names */ | 42 | /* Firmware Names */ |
40 | #define FIRMWARE_RV710 "radeon/RV710_uvd.bin" | 43 | #define FIRMWARE_RV710 "radeon/RV710_uvd.bin" |
41 | #define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin" | 44 | #define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin" |
@@ -47,6 +50,8 @@ MODULE_FIRMWARE(FIRMWARE_CYPRESS); | |||
47 | MODULE_FIRMWARE(FIRMWARE_SUMO); | 50 | MODULE_FIRMWARE(FIRMWARE_SUMO); |
48 | MODULE_FIRMWARE(FIRMWARE_TAHITI); | 51 | MODULE_FIRMWARE(FIRMWARE_TAHITI); |
49 | 52 | ||
53 | static void radeon_uvd_idle_work_handler(struct work_struct *work); | ||
54 | |||
50 | int radeon_uvd_init(struct radeon_device *rdev) | 55 | int radeon_uvd_init(struct radeon_device *rdev) |
51 | { | 56 | { |
52 | struct platform_device *pdev; | 57 | struct platform_device *pdev; |
@@ -54,6 +59,8 @@ int radeon_uvd_init(struct radeon_device *rdev) | |||
54 | const char *fw_name; | 59 | const char *fw_name; |
55 | int i, r; | 60 | int i, r; |
56 | 61 | ||
62 | INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler); | ||
63 | |||
57 | pdev = platform_device_register_simple("radeon_uvd", 0, NULL, 0); | 64 | pdev = platform_device_register_simple("radeon_uvd", 0, NULL, 0); |
58 | r = IS_ERR(pdev); | 65 | r = IS_ERR(pdev); |
59 | if (r) { | 66 | if (r) { |
@@ -188,8 +195,6 @@ int radeon_uvd_resume(struct radeon_device *rdev) | |||
188 | 195 | ||
189 | radeon_bo_unreserve(rdev->uvd.vcpu_bo); | 196 | radeon_bo_unreserve(rdev->uvd.vcpu_bo); |
190 | 197 | ||
191 | radeon_set_uvd_clocks(rdev, 53300, 40000); | ||
192 | |||
193 | return 0; | 198 | return 0; |
194 | } | 199 | } |
195 | 200 | ||
@@ -666,3 +671,24 @@ int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring, | |||
666 | 671 | ||
667 | return radeon_uvd_send_msg(rdev, ring, bo, fence); | 672 | return radeon_uvd_send_msg(rdev, ring, bo, fence); |
668 | } | 673 | } |
674 | |||
675 | static void radeon_uvd_idle_work_handler(struct work_struct *work) | ||
676 | { | ||
677 | struct radeon_device *rdev = | ||
678 | container_of(work, struct radeon_device, uvd.idle_work.work); | ||
679 | |||
680 | if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) | ||
681 | radeon_set_uvd_clocks(rdev, 0, 0); | ||
682 | else | ||
683 | schedule_delayed_work(&rdev->uvd.idle_work, | ||
684 | msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS)); | ||
685 | } | ||
686 | |||
687 | void radeon_uvd_note_usage(struct radeon_device *rdev) | ||
688 | { | ||
689 | bool set_clocks = !cancel_delayed_work_sync(&rdev->uvd.idle_work); | ||
690 | set_clocks &= schedule_delayed_work(&rdev->uvd.idle_work, | ||
691 | msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS)); | ||
692 | if (set_clocks) | ||
693 | radeon_set_uvd_clocks(rdev, 53300, 40000); | ||
694 | } | ||