Rev 5271 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5271 | Rev 6104 | ||
---|---|---|---|
Line 38... | Line 38... | ||
38 | 38 | ||
39 | /* 1 second timeout */ |
39 | /* 1 second timeout */ |
Line 40... | Line 40... | ||
40 | #define UVD_IDLE_TIMEOUT_MS 1000 |
40 | #define UVD_IDLE_TIMEOUT_MS 1000 |
- | 41 | ||
- | 42 | /* Firmware Names */ |
|
- | 43 | #define FIRMWARE_R600 "radeon/R600_uvd.bin" |
|
41 | 44 | #define FIRMWARE_RS780 "radeon/RS780_uvd.bin" |
|
42 | /* Firmware Names */ |
45 | #define FIRMWARE_RV770 "radeon/RV770_uvd.bin" |
43 | #define FIRMWARE_RV710 "radeon/RV710_uvd.bin" |
46 | #define FIRMWARE_RV710 "radeon/RV710_uvd.bin" |
44 | #define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin" |
47 | #define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin" |
45 | #define FIRMWARE_SUMO "radeon/SUMO_uvd.bin" |
48 | #define FIRMWARE_SUMO "radeon/SUMO_uvd.bin" |
Line 64... | Line 67... | ||
64 | int i, r; |
67 | int i, r; |
Line 65... | Line 68... | ||
65 | 68 | ||
Line 66... | Line 69... | ||
66 | // INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler); |
69 | // INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler); |
- | 70 | ||
- | 71 | switch (rdev->family) { |
|
- | 72 | case CHIP_RV610: |
|
- | 73 | case CHIP_RV630: |
|
- | 74 | case CHIP_RV670: |
|
- | 75 | case CHIP_RV620: |
|
- | 76 | case CHIP_RV635: |
|
- | 77 | fw_name = FIRMWARE_R600; |
|
- | 78 | break; |
|
- | 79 | ||
- | 80 | case CHIP_RS780: |
|
- | 81 | case CHIP_RS880: |
|
- | 82 | fw_name = FIRMWARE_RS780; |
|
- | 83 | break; |
|
- | 84 | ||
- | 85 | case CHIP_RV770: |
|
- | 86 | fw_name = FIRMWARE_RV770; |
|
67 | 87 | break; |
|
68 | switch (rdev->family) { |
88 | |
69 | case CHIP_RV710: |
89 | case CHIP_RV710: |
70 | case CHIP_RV730: |
90 | case CHIP_RV730: |
71 | case CHIP_RV740: |
91 | case CHIP_RV740: |
Line 182... | Line 202... | ||
182 | release_firmware(rdev->uvd_fw); |
202 | release_firmware(rdev->uvd_fw); |
183 | } |
203 | } |
Line 184... | Line 204... | ||
184 | 204 | ||
185 | int radeon_uvd_suspend(struct radeon_device *rdev) |
205 | int radeon_uvd_suspend(struct radeon_device *rdev) |
186 | { |
- | |
187 | unsigned size; |
- | |
188 | void *ptr; |
206 | { |
Line 189... | Line 207... | ||
189 | int i; |
207 | int i, r; |
190 | 208 | ||
Line 191... | Line 209... | ||
191 | if (rdev->uvd.vcpu_bo == NULL) |
209 | if (rdev->uvd.vcpu_bo == NULL) |
192 | return 0; |
210 | return 0; |
193 | 211 | ||
- | 212 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { |
|
Line 194... | Line 213... | ||
194 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) |
213 | uint32_t handle = atomic_read(&rdev->uvd.handles[i]); |
195 | if (atomic_read(&rdev->uvd.handles[i])) |
- | |
Line 196... | Line 214... | ||
196 | break; |
214 | if (handle != 0) { |
- | 215 | struct radeon_fence *fence; |
|
- | 216 | ||
197 | 217 | radeon_uvd_note_usage(rdev); |
|
- | 218 | ||
- | 219 | r = radeon_uvd_get_destroy_msg(rdev, |
|
Line 198... | Line 220... | ||
198 | if (i == RADEON_MAX_UVD_HANDLES) |
220 | R600_RING_TYPE_UVD_INDEX, handle, &fence); |
199 | return 0; |
221 | if (r) { |
Line 200... | Line 222... | ||
200 | 222 | DRM_ERROR("Error destroying UVD (%d)!\n", r); |
|
201 | size = radeon_bo_size(rdev->uvd.vcpu_bo); |
223 | continue; |
- | 224 | } |
|
- | 225 | ||
Line 202... | Line 226... | ||
202 | size -= rdev->uvd_fw->size; |
226 | radeon_fence_wait(fence, false); |
203 | 227 | radeon_fence_unref(&fence); |
|
Line 204... | Line 228... | ||
204 | ptr = rdev->uvd.cpu_addr; |
228 | |
Line 224... | Line 248... | ||
224 | size -= rdev->uvd_fw->size; |
248 | size -= rdev->uvd_fw->size; |
Line 225... | Line 249... | ||
225 | 249 | ||
226 | ptr = rdev->uvd.cpu_addr; |
250 | ptr = rdev->uvd.cpu_addr; |
Line 227... | Line -... | ||
227 | ptr += rdev->uvd_fw->size; |
- | |
228 | - | ||
229 | if (rdev->uvd.saved_bo != NULL) { |
- | |
230 | memcpy(ptr, rdev->uvd.saved_bo, size); |
- | |
231 | kfree(rdev->uvd.saved_bo); |
- | |
232 | rdev->uvd.saved_bo = NULL; |
251 | ptr += rdev->uvd_fw->size; |
Line 233... | Line 252... | ||
233 | } else |
252 | |
234 | memset(ptr, 0, size); |
253 | memset(ptr, 0, size); |
Line 374... | Line 393... | ||
374 | buf_sizes[0x1] = dpb_size; |
393 | buf_sizes[0x1] = dpb_size; |
375 | buf_sizes[0x2] = image_size; |
394 | buf_sizes[0x2] = image_size; |
376 | return 0; |
395 | return 0; |
377 | } |
396 | } |
Line -... | Line 397... | ||
- | 397 | ||
- | 398 | static int radeon_uvd_validate_codec(struct radeon_cs_parser *p, |
|
- | 399 | unsigned stream_type) |
|
- | 400 | { |
|
- | 401 | switch (stream_type) { |
|
- | 402 | case 0: /* H264 */ |
|
- | 403 | case 1: /* VC1 */ |
|
- | 404 | /* always supported */ |
|
- | 405 | return 0; |
|
- | 406 | ||
- | 407 | case 3: /* MPEG2 */ |
|
- | 408 | case 4: /* MPEG4 */ |
|
- | 409 | /* only since UVD 3 */ |
|
- | 410 | if (p->rdev->family >= CHIP_PALM) |
|
- | 411 | return 0; |
|
- | 412 | ||
- | 413 | /* fall through */ |
|
- | 414 | default: |
|
- | 415 | DRM_ERROR("UVD codec not supported by hardware %d!\n", |
|
- | 416 | stream_type); |
|
- | 417 | return -EINVAL; |
|
- | 418 | } |
|
- | 419 | } |
|
378 | 420 | ||
379 | static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, |
421 | static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, |
380 | unsigned offset, unsigned buf_sizes[]) |
422 | unsigned offset, unsigned buf_sizes[]) |
381 | { |
423 | { |
382 | int32_t *msg, msg_type, handle; |
424 | int32_t *msg, msg_type, handle; |
Line 414... | Line 456... | ||
414 | if (handle == 0) { |
456 | if (handle == 0) { |
415 | DRM_ERROR("Invalid UVD handle!\n"); |
457 | DRM_ERROR("Invalid UVD handle!\n"); |
416 | return -EINVAL; |
458 | return -EINVAL; |
417 | } |
459 | } |
Line 418... | Line 460... | ||
418 | 460 | ||
419 | if (msg_type == 1) { |
- | |
420 | /* it's a decode msg, calc buffer sizes */ |
- | |
421 | r = radeon_uvd_cs_msg_decode(msg, buf_sizes); |
- | |
422 | /* calc image size (width * height) */ |
- | |
423 | img_size = msg[6] * msg[7]; |
- | |
424 | radeon_bo_kunmap(bo); |
- | |
425 | if (r) |
- | |
426 | return r; |
- | |
427 | - | ||
428 | } else if (msg_type == 2) { |
- | |
429 | /* it's a destroy msg, free the handle */ |
- | |
430 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) |
- | |
431 | atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0); |
- | |
432 | radeon_bo_kunmap(bo); |
- | |
433 | return 0; |
461 | switch (msg_type) { |
434 | } else { |
462 | case 0: |
435 | /* it's a create msg, calc image size (width * height) */ |
463 | /* it's a create msg, calc image size (width * height) */ |
- | 464 | img_size = msg[7] * msg[8]; |
|
- | 465 | ||
436 | img_size = msg[7] * msg[8]; |
466 | r = radeon_uvd_validate_codec(p, msg[4]); |
- | 467 | radeon_bo_kunmap(bo); |
|
- | 468 | if (r) |
|
Line 437... | Line 469... | ||
437 | radeon_bo_kunmap(bo); |
469 | return r; |
- | 470 | ||
- | 471 | /* try to alloc a new handle */ |
|
438 | 472 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { |
|
439 | if (msg_type != 0) { |
473 | if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { |
440 | DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); |
474 | DRM_ERROR("Handle 0x%x already in use!\n", handle); |
Line 441... | Line 475... | ||
441 | return -EINVAL; |
475 | return -EINVAL; |
- | 476 | } |
|
- | 477 | ||
- | 478 | if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { |
|
- | 479 | p->rdev->uvd.filp[i] = p->filp; |
|
442 | } |
480 | p->rdev->uvd.img_size[i] = img_size; |
Line -... | Line 481... | ||
- | 481 | return 0; |
|
- | 482 | } |
|
- | 483 | } |
|
- | 484 | ||
- | 485 | DRM_ERROR("No more free UVD handles!\n"); |
|
- | 486 | return -EINVAL; |
|
- | 487 | ||
- | 488 | case 1: |
|
- | 489 | /* it's a decode msg, validate codec and calc buffer sizes */ |
|
- | 490 | r = radeon_uvd_validate_codec(p, msg[4]); |
|
- | 491 | if (!r) |
|
- | 492 | r = radeon_uvd_cs_msg_decode(msg, buf_sizes); |
|
443 | 493 | radeon_bo_kunmap(bo); |
|
444 | /* it's a create msg, no special handling needed */ |
494 | if (r) |
445 | } |
495 | return r; |
- | 496 | ||
- | 497 | /* validate the handle */ |
|
- | 498 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { |
|
- | 499 | if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { |
|
446 | 500 | if (p->rdev->uvd.filp[i] != p->filp) { |
|
447 | /* create or decode, validate the handle */ |
501 | DRM_ERROR("UVD handle collision detected!\n"); |
- | 502 | return -EINVAL; |
|
Line -... | Line 503... | ||
- | 503 | } |
|
- | 504 | return 0; |
|
- | 505 | } |
|
- | 506 | } |
|
448 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { |
507 | |
449 | if (atomic_read(&p->rdev->uvd.handles[i]) == handle) |
508 | DRM_ERROR("Invalid UVD handle 0x%x!\n", handle); |
450 | return 0; |
509 | return -ENOENT; |
451 | } |
510 | |
452 | - | ||
453 | /* handle not found try to alloc a new one */ |
511 | case 2: |
- | 512 | /* it's a destroy msg, free the handle */ |
|
- | 513 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) |
|
454 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { |
514 | atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0); |
- | 515 | radeon_bo_kunmap(bo); |
|
- | 516 | return 0; |
|
455 | if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { |
517 | |
Line 456... | Line 518... | ||
456 | p->rdev->uvd.filp[i] = p->filp; |
518 | default: |
457 | p->rdev->uvd.img_size[i] = img_size; |
519 | |
458 | return 0; |
520 | DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); |
Line 459... | Line 521... | ||
459 | } |
521 | return -EINVAL; |
460 | } |
522 | } |