diff options
author | Boyuan Zhang <boyuan.zhang@amd.com> | 2018-05-30 14:57:16 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-06-15 13:20:36 -0400 |
commit | 8a998052f29b811497b004b87dfe1ea1dfef75d1 (patch) | |
tree | 59e91feb497d38742da9825bd63a39a4d18d4f47 | |
parent | d2314b48d62110d5ce9aebcc8900bc44eed72700 (diff) |
drm/amdgpu: implement patch for fixing a known bug
Implement a patch to maunally reset read pointer
v2: using ring assignment instead of amdgpu_ring_write. adding comments
for each steps in the patch function.
v3: fixing a typo bug.
v4: fixing a bug in v3.
Signed-off-by: Boyuan Zhang <boyuan.zhang@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index ea1d677d02c8..92f78c559fc5 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | |||
@@ -40,6 +40,7 @@ static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev); | |||
40 | static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); | 40 | static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); |
41 | static void vcn_v1_0_set_jpeg_ring_funcs(struct amdgpu_device *adev); | 41 | static void vcn_v1_0_set_jpeg_ring_funcs(struct amdgpu_device *adev); |
42 | static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev); | 42 | static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev); |
43 | static void vcn_v1_0_jpeg_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr); | ||
43 | 44 | ||
44 | /** | 45 | /** |
45 | * vcn_v1_0_early_init - set function pointers | 46 | * vcn_v1_0_early_init - set function pointers |
@@ -1442,6 +1443,97 @@ static void vcn_v1_0_jpeg_ring_nop(struct amdgpu_ring *ring, uint32_t count) | |||
1442 | } | 1443 | } |
1443 | } | 1444 | } |
1444 | 1445 | ||
1446 | static void vcn_v1_0_jpeg_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val) | ||
1447 | { | ||
1448 | struct amdgpu_device *adev = ring->adev; | ||
1449 | ring->ring[(*ptr)++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0); | ||
1450 | if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) || | ||
1451 | ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) { | ||
1452 | ring->ring[(*ptr)++] = 0; | ||
1453 | ring->ring[(*ptr)++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0); | ||
1454 | } else { | ||
1455 | ring->ring[(*ptr)++] = reg_offset; | ||
1456 | ring->ring[(*ptr)++] = PACKETJ(0, 0, 0, PACKETJ_TYPE0); | ||
1457 | } | ||
1458 | ring->ring[(*ptr)++] = val; | ||
1459 | } | ||
1460 | |||
1461 | static void vcn_v1_0_jpeg_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr) | ||
1462 | { | ||
1463 | struct amdgpu_device *adev = ring->adev; | ||
1464 | |||
1465 | uint32_t reg, reg_offset, val, mask, i; | ||
1466 | |||
1467 | // 1st: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW | ||
1468 | reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW); | ||
1469 | reg_offset = (reg << 2); | ||
1470 | val = lower_32_bits(ring->gpu_addr); | ||
1471 | vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val); | ||
1472 | |||
1473 | // 2nd: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH | ||
1474 | reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH); | ||
1475 | reg_offset = (reg << 2); | ||
1476 | val = upper_32_bits(ring->gpu_addr); | ||
1477 | vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val); | ||
1478 | |||
1479 | // 3rd to 5th: issue MEM_READ commands | ||
1480 | for (i = 0; i <= 2; i++) { | ||
1481 | ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE2); | ||
1482 | ring->ring[ptr++] = 0; | ||
1483 | } | ||
1484 | |||
1485 | // 6th: program mmUVD_JRBC_RB_CNTL register to enable NO_FETCH and RPTR write ability | ||
1486 | reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL); | ||
1487 | reg_offset = (reg << 2); | ||
1488 | val = 0x13; | ||
1489 | vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val); | ||
1490 | |||
1491 | // 7th: program mmUVD_JRBC_RB_REF_DATA | ||
1492 | reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA); | ||
1493 | reg_offset = (reg << 2); | ||
1494 | val = 0x1; | ||
1495 | vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val); | ||
1496 | |||
1497 | // 8th: issue conditional register read mmUVD_JRBC_RB_CNTL | ||
1498 | reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL); | ||
1499 | reg_offset = (reg << 2); | ||
1500 | val = 0x1; | ||
1501 | mask = 0x1; | ||
1502 | |||
1503 | ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0); | ||
1504 | ring->ring[ptr++] = 0x01400200; | ||
1505 | ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0); | ||
1506 | ring->ring[ptr++] = val; | ||
1507 | ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0); | ||
1508 | if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) || | ||
1509 | ((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) { | ||
1510 | ring->ring[ptr++] = 0; | ||
1511 | ring->ring[ptr++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3); | ||
1512 | } else { | ||
1513 | ring->ring[ptr++] = reg_offset; | ||
1514 | ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE3); | ||
1515 | } | ||
1516 | ring->ring[ptr++] = mask; | ||
1517 | |||
1518 | //9th to 21st: insert no-op | ||
1519 | for (i = 0; i <= 12; i++) { | ||
1520 | ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE6); | ||
1521 | ring->ring[ptr++] = 0; | ||
1522 | } | ||
1523 | |||
1524 | //22nd: reset mmUVD_JRBC_RB_RPTR | ||
1525 | reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_RPTR); | ||
1526 | reg_offset = (reg << 2); | ||
1527 | val = 0; | ||
1528 | vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val); | ||
1529 | |||
1530 | //23rd: program mmUVD_JRBC_RB_CNTL to disable no_fetch | ||
1531 | reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL); | ||
1532 | reg_offset = (reg << 2); | ||
1533 | val = 0x12; | ||
1534 | vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val); | ||
1535 | } | ||
1536 | |||
1445 | static int vcn_v1_0_set_interrupt_state(struct amdgpu_device *adev, | 1537 | static int vcn_v1_0_set_interrupt_state(struct amdgpu_device *adev, |
1446 | struct amdgpu_irq_src *source, | 1538 | struct amdgpu_irq_src *source, |
1447 | unsigned type, | 1539 | unsigned type, |