aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoyuan Zhang <boyuan.zhang@amd.com>2018-05-30 14:57:16 -0400
committerAlex Deucher <alexander.deucher@amd.com>2018-06-15 13:20:36 -0400
commit8a998052f29b811497b004b87dfe1ea1dfef75d1 (patch)
tree59e91feb497d38742da9825bd63a39a4d18d4f47
parentd2314b48d62110d5ce9aebcc8900bc44eed72700 (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.c92
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);
40static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev); 40static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
41static void vcn_v1_0_set_jpeg_ring_funcs(struct amdgpu_device *adev); 41static void vcn_v1_0_set_jpeg_ring_funcs(struct amdgpu_device *adev);
42static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev); 42static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
43static 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
1446static 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
1461static 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
1445static int vcn_v1_0_set_interrupt_state(struct amdgpu_device *adev, 1537static 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,