aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/radeon/radeon.h3
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c100
-rw-r--r--drivers/gpu/drm/radeon/rv770.c2
4 files changed, 52 insertions, 55 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index f4dcfdd5a28b..aad18e676826 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1145,6 +1145,8 @@ struct radeon_uvd {
1145 struct radeon_bo *vcpu_bo; 1145 struct radeon_bo *vcpu_bo;
1146 void *cpu_addr; 1146 void *cpu_addr;
1147 uint64_t gpu_addr; 1147 uint64_t gpu_addr;
1148 void *saved_bo;
1149 unsigned fw_size;
1148 atomic_t handles[RADEON_MAX_UVD_HANDLES]; 1150 atomic_t handles[RADEON_MAX_UVD_HANDLES];
1149 struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; 1151 struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
1150 struct delayed_work idle_work; 1152 struct delayed_work idle_work;
@@ -1684,7 +1686,6 @@ struct radeon_device {
1684 const struct firmware *rlc_fw; /* r6/700 RLC firmware */ 1686 const struct firmware *rlc_fw; /* r6/700 RLC firmware */
1685 const struct firmware *mc_fw; /* NI MC firmware */ 1687 const struct firmware *mc_fw; /* NI MC firmware */
1686 const struct firmware *ce_fw; /* SI CE firmware */ 1688 const struct firmware *ce_fw; /* SI CE firmware */
1687 const struct firmware *uvd_fw; /* UVD firmware */
1688 struct r600_blit r600_blit; 1689 struct r600_blit r600_blit;
1689 struct r600_vram_scratch vram_scratch; 1690 struct r600_vram_scratch vram_scratch;
1690 int msi_enabled; /* msi enabled */ 1691 int msi_enabled; /* msi enabled */
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index ddb8f8e04eb5..7ddb0efe2408 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -782,7 +782,7 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
782 782
783 } else { 783 } else {
784 /* put fence directly behind firmware */ 784 /* put fence directly behind firmware */
785 index = ALIGN(rdev->uvd_fw->size, 8); 785 index = ALIGN(rdev->uvd.fw_size, 8);
786 rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index; 786 rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index;
787 rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index; 787 rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index;
788 } 788 }
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index cad735dd02c6..1b3a91bf1a9d 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -55,6 +55,7 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work);
55int radeon_uvd_init(struct radeon_device *rdev) 55int radeon_uvd_init(struct radeon_device *rdev)
56{ 56{
57 struct platform_device *pdev; 57 struct platform_device *pdev;
58 const struct firmware *fw;
58 unsigned long bo_size; 59 unsigned long bo_size;
59 const char *fw_name; 60 const char *fw_name;
60 int i, r; 61 int i, r;
@@ -104,7 +105,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
104 return -EINVAL; 105 return -EINVAL;
105 } 106 }
106 107
107 r = request_firmware(&rdev->uvd_fw, fw_name, &pdev->dev); 108 r = request_firmware(&fw, fw_name, &pdev->dev);
108 if (r) { 109 if (r) {
109 dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n", 110 dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
110 fw_name); 111 fw_name);
@@ -114,7 +115,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
114 115
115 platform_device_unregister(pdev); 116 platform_device_unregister(pdev);
116 117
117 bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) + 118 bo_size = RADEON_GPU_PAGE_ALIGN(fw->size + 8) +
118 RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE; 119 RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
119 r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, 120 r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
120 RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo); 121 RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo);
@@ -123,16 +124,35 @@ int radeon_uvd_init(struct radeon_device *rdev)
123 return r; 124 return r;
124 } 125 }
125 126
126 r = radeon_uvd_resume(rdev); 127 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
127 if (r) 128 if (r) {
129 radeon_bo_unref(&rdev->uvd.vcpu_bo);
130 dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
128 return r; 131 return r;
132 }
129 133
130 memset(rdev->uvd.cpu_addr, 0, bo_size); 134 r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
131 memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size); 135 &rdev->uvd.gpu_addr);
136 if (r) {
137 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
138 radeon_bo_unref(&rdev->uvd.vcpu_bo);
139 dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
140 return r;
141 }
132 142
133 r = radeon_uvd_suspend(rdev); 143 r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
134 if (r) 144 if (r) {
145 dev_err(rdev->dev, "(%d) UVD map failed\n", r);
135 return r; 146 return r;
147 }
148
149 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
150
151 rdev->uvd.fw_size = fw->size;
152 memset(rdev->uvd.cpu_addr, 0, bo_size);
153 memcpy(rdev->uvd.cpu_addr, fw->data, fw->size);
154
155 release_firmware(fw);
136 156
137 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { 157 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
138 atomic_set(&rdev->uvd.handles[i], 0); 158 atomic_set(&rdev->uvd.handles[i], 0);
@@ -144,71 +164,47 @@ int radeon_uvd_init(struct radeon_device *rdev)
144 164
145void radeon_uvd_fini(struct radeon_device *rdev) 165void radeon_uvd_fini(struct radeon_device *rdev)
146{ 166{
147 radeon_uvd_suspend(rdev);
148 radeon_bo_unref(&rdev->uvd.vcpu_bo);
149}
150
151int radeon_uvd_suspend(struct radeon_device *rdev)
152{
153 int r; 167 int r;
154 168
155 if (rdev->uvd.vcpu_bo == NULL) 169 if (rdev->uvd.vcpu_bo == NULL)
156 return 0; 170 return;
157 171
158 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); 172 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
159 if (!r) { 173 if (!r) {
160 radeon_bo_kunmap(rdev->uvd.vcpu_bo); 174 radeon_bo_kunmap(rdev->uvd.vcpu_bo);
161 radeon_bo_unpin(rdev->uvd.vcpu_bo); 175 radeon_bo_unpin(rdev->uvd.vcpu_bo);
162 rdev->uvd.cpu_addr = NULL;
163 if (!radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_CPU, NULL)) {
164 radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
165 }
166 radeon_bo_unreserve(rdev->uvd.vcpu_bo); 176 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
167
168 if (rdev->uvd.cpu_addr) {
169 radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
170 } else {
171 rdev->fence_drv[R600_RING_TYPE_UVD_INDEX].cpu_addr = NULL;
172 }
173 } 177 }
174 return r; 178
179 radeon_bo_unref(&rdev->uvd.vcpu_bo);
175} 180}
176 181
177int radeon_uvd_resume(struct radeon_device *rdev) 182int radeon_uvd_suspend(struct radeon_device *rdev)
178{ 183{
179 int r; 184 unsigned size;
180 185
181 if (rdev->uvd.vcpu_bo == NULL) 186 if (rdev->uvd.vcpu_bo == NULL)
182 return -EINVAL; 187 return 0;
183 188
184 r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); 189 size = radeon_bo_size(rdev->uvd.vcpu_bo);
185 if (r) { 190 rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
186 radeon_bo_unref(&rdev->uvd.vcpu_bo); 191 memcpy(rdev->uvd.saved_bo, rdev->uvd.cpu_addr, size);
187 dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
188 return r;
189 }
190 192
191 /* Have been pin in cpu unmap unpin */ 193 return 0;
192 radeon_bo_kunmap(rdev->uvd.vcpu_bo); 194}
193 radeon_bo_unpin(rdev->uvd.vcpu_bo);
194 195
195 r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, 196int radeon_uvd_resume(struct radeon_device *rdev)
196 &rdev->uvd.gpu_addr); 197{
197 if (r) { 198 if (rdev->uvd.vcpu_bo == NULL)
198 radeon_bo_unreserve(rdev->uvd.vcpu_bo); 199 return -EINVAL;
199 radeon_bo_unref(&rdev->uvd.vcpu_bo);
200 dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
201 return r;
202 }
203 200
204 r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); 201 if (rdev->uvd.saved_bo != NULL) {
205 if (r) { 202 unsigned size = radeon_bo_size(rdev->uvd.vcpu_bo);
206 dev_err(rdev->dev, "(%d) UVD map failed\n", r); 203 memcpy(rdev->uvd.cpu_addr, rdev->uvd.saved_bo, size);
207 return r; 204 kfree(rdev->uvd.saved_bo);
205 rdev->uvd.saved_bo = NULL;
208 } 206 }
209 207
210 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
211
212 return 0; 208 return 0;
213} 209}
214 210
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 4a62ad2e5399..30ea14e8854c 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -813,7 +813,7 @@ int rv770_uvd_resume(struct radeon_device *rdev)
813 813
814 /* programm the VCPU memory controller bits 0-27 */ 814 /* programm the VCPU memory controller bits 0-27 */
815 addr = rdev->uvd.gpu_addr >> 3; 815 addr = rdev->uvd.gpu_addr >> 3;
816 size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; 816 size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3;
817 WREG32(UVD_VCPU_CACHE_OFFSET0, addr); 817 WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
818 WREG32(UVD_VCPU_CACHE_SIZE0, size); 818 WREG32(UVD_VCPU_CACHE_SIZE0, size);
819 819