drm/amdgpu: Add VCN static PG support on RV
authorRex Zhu <Rex.Zhu@amd.com>
Thu, 17 May 2018 08:07:02 +0000 (16:07 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 24 May 2018 15:07:51 +0000 (10:07 -0500)
Implement static powergating suport on VCN.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c

index 2fd7db8..181e6af 100644 (file)
 #define VCN_ENC_CMD_REG_WRITE          0x0000000b
 #define VCN_ENC_CMD_REG_WAIT           0x0000000c
 
+enum engine_status_constants {
+       UVD_PGFSM_STATUS__UVDM_UVDU_PWR_ON = 0x2AAAA0,
+       UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON = 0x00000002,
+       UVD_STATUS__UVD_BUSY = 0x00000004,
+       GB_ADDR_CONFIG_DEFAULT = 0x26010011,
+       UVD_STATUS__IDLE = 0x2,
+       UVD_STATUS__BUSY = 0x5,
+       UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF = 0x1,
+       UVD_STATUS__RBC_BUSY = 0x1,
+};
+
 struct amdgpu_vcn {
        struct amdgpu_bo        *vcpu_bo;
        void                    *cpu_addr;
index 7a36641..dcb60ee 100644 (file)
@@ -480,6 +480,94 @@ static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev)
        WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
 }
 
+static void vcn_1_0_disable_static_power_gating(struct amdgpu_device *adev)
+{
+       uint32_t data = 0;
+       int ret;
+
+       if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
+               data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDIL_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDIR_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDW_PWR_CONFIG__SHIFT);
+
+               WREG32_SOC15(VCN, 0, mmUVD_PGFSM_CONFIG, data);
+               SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_PGFSM_STATUS, UVD_PGFSM_STATUS__UVDM_UVDU_PWR_ON, 0xFFFFFF, ret);
+       } else {
+               data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDIL_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDIR_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDW_PWR_CONFIG__SHIFT);
+               WREG32_SOC15(VCN, 0, mmUVD_PGFSM_CONFIG, data);
+               SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_PGFSM_STATUS, 0,  0xFFFFFFFF, ret);
+       }
+
+       /* polling UVD_PGFSM_STATUS to confirm UVDM_PWR_STATUS , UVDU_PWR_STATUS are 0 (power on) */
+
+       data = RREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS);
+       data &= ~0x103;
+       if (adev->pg_flags & AMD_PG_SUPPORT_VCN)
+               data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON | UVD_POWER_STATUS__UVD_PG_EN_MASK;
+
+       WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data);
+}
+
+static void vcn_1_0_enable_static_power_gating(struct amdgpu_device *adev)
+{
+       uint32_t data = 0;
+       int ret;
+
+       if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
+               /* Before power off, this indicator has to be turned on */
+               data = RREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS);
+               data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK;
+               data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF;
+               WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data);
+
+
+               data = (2 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDIL_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDIR_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDW_PWR_CONFIG__SHIFT);
+
+               WREG32_SOC15(VCN, 0, mmUVD_PGFSM_CONFIG, data);
+
+               data = (2 << UVD_PGFSM_STATUS__UVDM_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDU_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDF_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDC_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDB_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDIL_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDIR_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDTD_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDTE_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDE_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDW_PWR_STATUS__SHIFT);
+               SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_PGFSM_STATUS, data, 0xFFFFFFFF, ret);
+       }
+}
+
 /**
  * vcn_v1_0_start - start VCN block
  *
@@ -499,6 +587,7 @@ static int vcn_v1_0_start(struct amdgpu_device *adev)
 
        vcn_v1_0_mc_resume(adev);
 
+       vcn_1_0_disable_static_power_gating(adev);
        /* disable clock gating */
        vcn_v1_0_disable_clock_gating(adev);
 
@@ -681,8 +770,9 @@ static int vcn_v1_0_stop(struct amdgpu_device *adev)
                        ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
 
        /* enable clock gating */
-       vcn_v1_0_enable_clock_gating(adev);
 
+       vcn_v1_0_enable_clock_gating(adev);
+       vcn_1_0_enable_static_power_gating(adev);
        return 0;
 }