drm/amdgpu: implement vce3 check/post_soft_reset
authorChunming Zhou <David1.Zhou@amd.com>
Mon, 18 Jul 2016 09:38:50 +0000 (17:38 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 8 Aug 2016 15:32:12 +0000 (11:32 -0400)
Signed-off-by: Chunming Zhou <David1.Zhou@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c

index 108e04fc0987672211dcddc9707cfe29c77ce462..e9364687cd95fc800819340570028e9a23f7ae07 100644 (file)
@@ -1716,6 +1716,7 @@ struct amdgpu_vce {
        struct amdgpu_irq_src   irq;
        unsigned                harvest_config;
        struct amd_sched_entity entity;
+       uint32_t                srbm_soft_reset;
 };
 
 /*
index c271abffd8dd7475ea0b25101a86d1b32b53696c..e5b18ad42721bc0c53f021d2744b44f55b24d99a 100644 (file)
@@ -37,6 +37,9 @@
 #include "gca/gfx_8_0_d.h"
 #include "smu/smu_7_1_2_d.h"
 #include "smu/smu_7_1_2_sh_mask.h"
+#include "gca/gfx_8_0_d.h"
+#include "gca/gfx_8_0_sh_mask.h"
+
 
 #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT    0x04
 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK      0x10
@@ -601,20 +604,115 @@ static int vce_v3_0_wait_for_idle(void *handle)
        return -ETIMEDOUT;
 }
 
+#define AMDGPU_VCE_STATUS_BUSY_MASK    0x78
+
+static int vce_v3_0_check_soft_reset(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       u32 srbm_soft_reset = 0;
+       u32 tmp;
+
+       /* VCE BUG: it is always busy, so skip its checking now */
+       return 0;
+
+       /* According to VCE team , we should use VCE_STATUS instead
+        * SRBM_STATUS.VCE_BUSY bit for busy status checking.
+        * GRBM_GFX_INDEX.INSTANCE_INDEX is used to specify which VCE
+        * instance's registers are accessed
+        * (0 for 1st instance, 10 for 2nd instance).
+        *
+        *VCE_STATUS
+        *|UENC|ACPI|AUTO ACTIVE|RB1 |RB0 |RB2 |          |FW_LOADED|JOB |
+        *|----+----+-----------+----+----+----+----------+---------+----|
+        *|bit8|bit7|    bit6   |bit5|bit4|bit3|   bit2   |  bit1   |bit0|
+        *
+        * VCE team suggest use bit 3--bit 6 for busy status check
+        */
+       tmp = RREG32(mmGRBM_GFX_INDEX);
+       tmp = REG_SET_FIELD(tmp, GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+       WREG32(mmGRBM_GFX_INDEX, tmp);
+       if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
+               srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
+               srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
+       }
+       tmp = RREG32(mmGRBM_GFX_INDEX);
+       tmp = REG_SET_FIELD(tmp, GRBM_GFX_INDEX, INSTANCE_INDEX, 0x10);
+       WREG32(mmGRBM_GFX_INDEX, tmp);
+       if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
+               srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
+               srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
+       }
+       tmp = RREG32(mmGRBM_GFX_INDEX);
+       tmp = REG_SET_FIELD(tmp, GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+       WREG32(mmGRBM_GFX_INDEX, tmp);
+
+       if (adev->vce.harvest_config & (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
+               srbm_soft_reset = 0;
+
+       if (srbm_soft_reset) {
+               adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = true;
+               adev->vce.srbm_soft_reset = srbm_soft_reset;
+       } else {
+               adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = false;
+               adev->vce.srbm_soft_reset = 0;
+       }
+       return 0;
+}
+
 static int vce_v3_0_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       u32 mask = 0;
+       u32 srbm_soft_reset;
+
+       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
+               return 0;
+       srbm_soft_reset = adev->vce.srbm_soft_reset;
+
+       if (srbm_soft_reset) {
+               u32 tmp;
 
-       mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
-       mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
+               tmp = RREG32(mmSRBM_SOFT_RESET);
+               tmp |= srbm_soft_reset;
+               dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
+               WREG32(mmSRBM_SOFT_RESET, tmp);
+               tmp = RREG32(mmSRBM_SOFT_RESET);
+
+               udelay(50);
+
+               tmp &= ~srbm_soft_reset;
+               WREG32(mmSRBM_SOFT_RESET, tmp);
+               tmp = RREG32(mmSRBM_SOFT_RESET);
+
+               /* Wait a little for things to settle down */
+               udelay(50);
+       }
+
+       return 0;
+}
+
+static int vce_v3_0_pre_soft_reset(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
+               return 0;
+
+       mdelay(5);
+
+       return vce_v3_0_suspend(adev);
+}
+
+
+static int vce_v3_0_post_soft_reset(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
+               return 0;
 
-       WREG32_P(mmSRBM_SOFT_RESET, mask,
-                ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK |
-                  SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK));
        mdelay(5);
 
-       return vce_v3_0_start(adev);
+       return vce_v3_0_resume(adev);
 }
 
 static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
@@ -751,7 +849,10 @@ const struct amd_ip_funcs vce_v3_0_ip_funcs = {
        .resume = vce_v3_0_resume,
        .is_idle = vce_v3_0_is_idle,
        .wait_for_idle = vce_v3_0_wait_for_idle,
+       .check_soft_reset = vce_v3_0_check_soft_reset,
+       .pre_soft_reset = vce_v3_0_pre_soft_reset,
        .soft_reset = vce_v3_0_soft_reset,
+       .post_soft_reset = vce_v3_0_post_soft_reset,
        .set_clockgating_state = vce_v3_0_set_clockgating_state,
        .set_powergating_state = vce_v3_0_set_powergating_state,
 };