From 810ddc3ab52dd84f4cd28ee8673678aece457a59 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 23 Aug 2016 13:25:49 -0400 Subject: drm/amdgpu: rename suspend_kms and resume_kms The old names were dragged over from radeon. The new ones better match the naming conventions used in the driver. No functional change. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 ++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3cc2629..8494514 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2434,8 +2434,8 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv); void amdgpu_driver_preclose_kms(struct drm_device *dev, struct drm_file *file_priv); -int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon); -int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon); +int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon); +int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon); u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe); int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe); void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c38dc47..1ef4034 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1027,7 +1027,7 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero /* don't suspend or resume card normally */ dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; - amdgpu_resume_kms(dev, true, true); + amdgpu_device_resume(dev, true, true); dev->pdev->d3_delay = d3_delay; @@ -1037,7 +1037,7 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero printk(KERN_INFO "amdgpu: switched off\n"); drm_kms_helper_poll_disable(dev); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; - amdgpu_suspend_kms(dev, true, true); + amdgpu_device_suspend(dev, true, true); dev->switch_power_state = DRM_SWITCH_POWER_OFF; } } @@ -1774,7 +1774,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) * Suspend & resume. */ /** - * amdgpu_suspend_kms - initiate device suspend + * amdgpu_device_suspend - initiate device suspend * * @pdev: drm dev pointer * @state: suspend state @@ -1783,7 +1783,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) * Returns 0 for success or an error on failure. * Called at driver suspend. */ -int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) +int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) { struct amdgpu_device *adev; struct drm_crtc *crtc; @@ -1862,7 +1862,7 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) } /** - * amdgpu_resume_kms - initiate device resume + * amdgpu_device_resume - initiate device resume * * @pdev: drm dev pointer * @@ -1870,7 +1870,7 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) * Returns 0 for success or an error on failure. * Called at driver resume. */ -int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon) +int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) { struct drm_connector *connector; struct amdgpu_device *adev = dev->dev_private; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index a631c95..1b787d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -397,28 +397,28 @@ static int amdgpu_pmops_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - return amdgpu_suspend_kms(drm_dev, true, true); + return amdgpu_device_suspend(drm_dev, true, true); } static int amdgpu_pmops_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - return amdgpu_resume_kms(drm_dev, true, true); + return amdgpu_device_resume(drm_dev, true, true); } static int amdgpu_pmops_freeze(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - return amdgpu_suspend_kms(drm_dev, false, true); + return amdgpu_device_suspend(drm_dev, false, true); } static int amdgpu_pmops_thaw(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - return amdgpu_resume_kms(drm_dev, false, true); + return amdgpu_device_resume(drm_dev, false, true); } static int amdgpu_pmops_runtime_suspend(struct device *dev) @@ -436,7 +436,7 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev) drm_kms_helper_poll_disable(drm_dev); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); - ret = amdgpu_suspend_kms(drm_dev, false, false); + ret = amdgpu_device_suspend(drm_dev, false, false); pci_save_state(pdev); pci_disable_device(pdev); pci_ignore_hotplug(pdev); @@ -469,7 +469,7 @@ static int amdgpu_pmops_runtime_resume(struct device *dev) return ret; pci_set_master(pdev); - ret = amdgpu_resume_kms(drm_dev, false, false); + ret = amdgpu_device_resume(drm_dev, false, false); drm_kms_helper_poll_enable(drm_dev); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; -- cgit v1.1 From 75c65480ba7d56e2ee164057ce8ab879931a3978 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 24 Aug 2016 16:56:21 -0400 Subject: drm/amdgpu: track the number of vce rings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than using a hardcoded value. This allows different versions to expose more or less rings. No functional change. Reviewed-by: JimQu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 57 +++++++++++++++------------------ drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 37 +++++++++++---------- 4 files changed, 45 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 8494514..0cd1c93 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1686,6 +1686,7 @@ struct amdgpu_vce { unsigned harvest_config; struct amd_sched_entity entity; uint32_t srbm_soft_reset; + unsigned num_rings; }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index b78e740..f1b9e0f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -296,7 +296,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file break; case AMDGPU_HW_IP_VCE: type = AMD_IP_BLOCK_TYPE_VCE; - for (i = 0; i < AMDGPU_MAX_VCE_RINGS; i++) + for (i = 0; i < adev->vce.num_rings; i++) ring_mask |= ((adev->vce.ring[i].ready ? 1 : 0) << i); ib_start_alignment = AMDGPU_GPU_PAGE_SIZE; ib_size_alignment = 1; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index 5fa55b5..3fcc33f 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -193,6 +193,8 @@ static int vce_v2_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + adev->vce.num_rings = 2; + vce_v2_0_set_ring_funcs(adev); vce_v2_0_set_irq_funcs(adev); @@ -202,7 +204,7 @@ static int vce_v2_0_early_init(void *handle) static int vce_v2_0_sw_init(void *handle) { struct amdgpu_ring *ring; - int r; + int r, i; struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* VCE */ @@ -219,19 +221,14 @@ static int vce_v2_0_sw_init(void *handle) if (r) return r; - ring = &adev->vce.ring[0]; - sprintf(ring->name, "vce0"); - r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); - if (r) - return r; - - ring = &adev->vce.ring[1]; - sprintf(ring->name, "vce1"); - r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); - if (r) - return r; + for (i = 0; i < adev->vce.num_rings; i++) { + ring = &adev->vce.ring[i]; + sprintf(ring->name, "vce%d", i); + r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, + &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); + if (r) + return r; + } return r; } @@ -254,29 +251,23 @@ static int vce_v2_0_sw_fini(void *handle) static int vce_v2_0_hw_init(void *handle) { - struct amdgpu_ring *ring; - int r; + int r, i; struct amdgpu_device *adev = (struct amdgpu_device *)handle; r = vce_v2_0_start(adev); + /* this error mean vcpu not in running state, so just skip ring test, not stop driver initialize */ if (r) -/* this error mean vcpu not in running state, so just skip ring test, not stop driver initialize */ return 0; - ring = &adev->vce.ring[0]; - ring->ready = true; - r = amdgpu_ring_test_ring(ring); - if (r) { - ring->ready = false; - return r; - } + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].ready = false; - ring = &adev->vce.ring[1]; - ring->ready = true; - r = amdgpu_ring_test_ring(ring); - if (r) { - ring->ready = false; - return r; + for (i = 0; i < adev->vce.num_rings; i++) { + r = amdgpu_ring_test_ring(&adev->vce.ring[i]); + if (r) + return r; + else + adev->vce.ring[i].ready = true; } DRM_INFO("VCE initialized successfully.\n"); @@ -618,8 +609,10 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = { static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev) { - adev->vce.ring[0].funcs = &vce_v2_0_ring_funcs; - adev->vce.ring[1].funcs = &vce_v2_0_ring_funcs; + int i; + + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].funcs = &vce_v2_0_ring_funcs; } static const struct amdgpu_irq_src_funcs vce_v2_0_irq_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 615b8b1..27acd28 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -345,6 +345,8 @@ static int vce_v3_0_early_init(void *handle) (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) return -ENOENT; + adev->vce.num_rings = 2; + vce_v3_0_set_ring_funcs(adev); vce_v3_0_set_irq_funcs(adev); @@ -355,7 +357,7 @@ static int vce_v3_0_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_ring *ring; - int r; + int r, i; /* VCE */ r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq); @@ -371,19 +373,14 @@ static int vce_v3_0_sw_init(void *handle) if (r) return r; - ring = &adev->vce.ring[0]; - sprintf(ring->name, "vce0"); - r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); - if (r) - return r; - - ring = &adev->vce.ring[1]; - sprintf(ring->name, "vce1"); - r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); - if (r) - return r; + for (i = 0; i < adev->vce.num_rings; i++) { + ring = &adev->vce.ring[i]; + sprintf(ring->name, "vce%d", i); + r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, + &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); + if (r) + return r; + } return r; } @@ -413,10 +410,10 @@ static int vce_v3_0_hw_init(void *handle) if (r) return r; - adev->vce.ring[0].ready = false; - adev->vce.ring[1].ready = false; + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].ready = false; - for (i = 0; i < 2; i++) { + for (i = 0; i < adev->vce.num_rings; i++) { r = amdgpu_ring_test_ring(&adev->vce.ring[i]); if (r) return r; @@ -800,8 +797,10 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = { static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev) { - adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs; - adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs; + int i; + + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].funcs = &vce_v3_0_ring_funcs; } static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = { -- cgit v1.1 From 6f0359ff73076483902de0c17f9649bf55651e2a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 24 Aug 2016 17:15:33 -0400 Subject: drm/amdgpu/vce3: add support for third vce ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not of much use at the moment (we don't really use the second ring either), but may be useful later. Reviewed-by: JimQu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 22 ++++++++++++++++++---- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 0cd1c93..4cfcf9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -108,7 +108,7 @@ extern char *amdgpu_virtual_display; #define AMDGPU_MAX_RINGS 16 #define AMDGPU_MAX_GFX_RINGS 1 #define AMDGPU_MAX_COMPUTE_RINGS 8 -#define AMDGPU_MAX_VCE_RINGS 2 +#define AMDGPU_MAX_VCE_RINGS 3 /* max number of IP instances */ #define AMDGPU_MAX_SDMA_INSTANCES 2 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index da52af2..9b71d6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -850,8 +850,8 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) struct fence *fence = NULL; long r; - /* skip vce ring1 ib test for now, since it's not reliable */ - if (ring == &ring->adev->vce.ring[1]) + /* skip vce ring1/2 ib test for now, since it's not reliable */ + if (ring != &ring->adev->vce.ring[0]) return 0; r = amdgpu_vce_get_create_msg(ring, 1, NULL); diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 27acd28..d734ac9 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -70,8 +70,10 @@ static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring) if (ring == &adev->vce.ring[0]) return RREG32(mmVCE_RB_RPTR); - else + else if (ring == &adev->vce.ring[1]) return RREG32(mmVCE_RB_RPTR2); + else + return RREG32(mmVCE_RB_RPTR3); } /** @@ -87,8 +89,10 @@ static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring) if (ring == &adev->vce.ring[0]) return RREG32(mmVCE_RB_WPTR); - else + else if (ring == &adev->vce.ring[1]) return RREG32(mmVCE_RB_WPTR2); + else + return RREG32(mmVCE_RB_WPTR3); } /** @@ -104,8 +108,10 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring) if (ring == &adev->vce.ring[0]) WREG32(mmVCE_RB_WPTR, ring->wptr); - else + else if (ring == &adev->vce.ring[1]) WREG32(mmVCE_RB_WPTR2, ring->wptr); + else + WREG32(mmVCE_RB_WPTR3, ring->wptr); } static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override) @@ -229,6 +235,13 @@ static int vce_v3_0_start(struct amdgpu_device *adev) WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); + ring = &adev->vce.ring[2]; + WREG32(mmVCE_RB_RPTR3, ring->wptr); + WREG32(mmVCE_RB_WPTR3, ring->wptr); + WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr); + WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr)); + WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4); + mutex_lock(&adev->grbm_idx_mutex); for (idx = 0; idx < 2; ++idx) { if (adev->vce.harvest_config & (1 << idx)) @@ -345,7 +358,7 @@ static int vce_v3_0_early_init(void *handle) (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) return -ENOENT; - adev->vce.num_rings = 2; + adev->vce.num_rings = 3; vce_v3_0_set_ring_funcs(adev); vce_v3_0_set_irq_funcs(adev); @@ -671,6 +684,7 @@ static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, switch (entry->src_data) { case 0: case 1: + case 2: amdgpu_fence_process(&adev->vce.ring[entry->src_data]); break; default: -- cgit v1.1 From 0174df4e664dfc481b6ee3f9f4528c0b727b6fb0 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 18 Aug 2016 12:37:02 +0800 Subject: drm/amdgpu: refine function name for consistency Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index d734ac9..c25a096 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -696,7 +696,7 @@ static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, return 0; } -static void vce_v3_set_bypass_mode(struct amdgpu_device *adev, bool enable) +static void vce_v3_0_set_bypass_mode(struct amdgpu_device *adev, bool enable) { u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL); @@ -716,7 +716,7 @@ static int vce_v3_0_set_clockgating_state(void *handle, int i; if (adev->asic_type == CHIP_POLARIS10) - vce_v3_set_bypass_mode(adev, enable); + vce_v3_0_set_bypass_mode(adev, enable); if (!(adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) return 0; -- cgit v1.1 From cbb2fe8e967dbc88f236aa7da1bb3f79b61022f9 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 18 Aug 2016 13:02:46 +0800 Subject: drm/amd/powerplay: add bypass mode for vce 2.0. fix issue after vce encode, the eclk stay high. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index 3fcc33f..58af0da 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -30,10 +30,10 @@ #include "amdgpu.h" #include "amdgpu_vce.h" #include "cikd.h" - #include "vce/vce_2_0_d.h" #include "vce/vce_2_0_sh_mask.h" - +#include "smu/smu_7_0_1_d.h" +#include "smu/smu_7_0_1_sh_mask.h" #include "oss/oss_2_0_d.h" #include "oss/oss_2_0_sh_mask.h" @@ -539,11 +539,28 @@ static int vce_v2_0_process_interrupt(struct amdgpu_device *adev, return 0; } +static void vce_v2_0_set_bypass_mode(struct amdgpu_device *adev, bool enable) +{ + u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL); + + if (enable) + tmp |= GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK; + else + tmp &= ~GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK; + + WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp); +} + + static int vce_v2_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { bool gate = false; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + bool enable = (state == AMD_CG_STATE_GATE) ? true : false; + + + vce_v2_0_set_bypass_mode(adev, enable); if (state == AMD_CG_STATE_GATE) gate = true; -- cgit v1.1 From c04399f19436616875879ee2711c5b78a90dd1b0 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 18 Aug 2016 18:27:14 +0800 Subject: drm/amdgpu: add vce bypass mode for tonga. fix issue that encode test failed on the second time when vce dpm enabled on tonga. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index c25a096..b083c36 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -715,7 +715,8 @@ static int vce_v3_0_set_clockgating_state(void *handle, bool enable = (state == AMD_CG_STATE_GATE) ? true : false; int i; - if (adev->asic_type == CHIP_POLARIS10) + if ((adev->asic_type == CHIP_POLARIS10) || + (adev->asic_type == CHIP_TONGA)) vce_v3_0_set_bypass_mode(adev, enable); if (!(adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) -- cgit v1.1 From 2fef37c62cb6338ca15b30b05ec91b8bcc7b7dbe Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 22 Aug 2016 20:48:13 +0800 Subject: drm/amdgpu: add support for getting sub_device id and sub_vendor_id in cgs interface. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 6 ++++++ drivers/gpu/drm/amd/include/cgs_common.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index bc0440f..040993c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -848,6 +848,12 @@ static int amdgpu_cgs_query_system_info(struct cgs_device *cgs_device, case CGS_SYSTEM_INFO_GFX_SE_INFO: sys_info->value = adev->gfx.config.max_shader_engines; break; + case CGS_SYSTEM_INFO_PCIE_SUB_SYS_ID: + sys_info->value = adev->pdev->subsystem_device; + break; + case CGS_SYSTEM_INFO_PCIE_SUB_SYS_VENDOR_ID: + sys_info->value = adev->pdev->subsystem_vendor; + break; default: return -ENODEV; } diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index b86aba9..6aa8938 100644 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -119,6 +119,8 @@ enum cgs_system_info_id { CGS_SYSTEM_INFO_PG_FLAGS, CGS_SYSTEM_INFO_GFX_CU_INFO, CGS_SYSTEM_INFO_GFX_SE_INFO, + CGS_SYSTEM_INFO_PCIE_SUB_SYS_ID, + CGS_SYSTEM_INFO_PCIE_SUB_SYS_VENDOR_ID, CGS_SYSTEM_INFO_ID_MAXIMUM, }; -- cgit v1.1 From 38109efacd9c17e52ec3d9a43ea227a72623d9fd Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 22 Aug 2016 20:47:01 +0800 Subject: drm/amd/powerplay: get system info by cgs interface. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c | 24 ++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c index 98e01d1..9831871 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c @@ -3119,11 +3119,27 @@ int polaris10_patch_voltage_workaround(struct pp_hwmgr *hwmgr) struct phm_ppt_v1_voltage_lookup_table *lookup_table = table_info->vddc_lookup_table; uint32_t i; + uint32_t hw_revision, sub_vendor_id, sub_sys_id; + struct cgs_system_info sys_info = {0}; - if (hwmgr->chip_id == CHIP_POLARIS10 && hwmgr->hw_revision == 0xC7 && - ((hwmgr->sub_sys_id == 0xb37 && hwmgr->sub_vendor_id == 0x1002) || - (hwmgr->sub_sys_id == 0x4a8 && hwmgr->sub_vendor_id == 0x1043) || - (hwmgr->sub_sys_id == 0x9480 && hwmgr->sub_vendor_id == 0x1682))) { + sys_info.size = sizeof(struct cgs_system_info); + + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV; + cgs_query_system_info(hwmgr->device, &sys_info); + hw_revision = (uint32_t)sys_info.value; + + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_SUB_SYS_ID; + cgs_query_system_info(hwmgr->device, &sys_info); + sub_sys_id = (uint32_t)sys_info.value; + + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_SUB_SYS_VENDOR_ID; + cgs_query_system_info(hwmgr->device, &sys_info); + sub_vendor_id = (uint32_t)sys_info.value; + + if (hwmgr->chip_id == CHIP_POLARIS10 && hw_revision == 0xC7 && + ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) || + (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) || + (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) { if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000) return 0; -- cgit v1.1 From 075f101ceec0446b4a651ae4a22d4de11b7e7cd6 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 22 Aug 2016 20:47:28 +0800 Subject: drm/amd/powerplay: simplify struct amd_pp_init. delete the members not needed when amd_powerplay_init. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 4 ---- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 3 --- drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 3 --- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 3 --- drivers/gpu/drm/amd/powerplay/inc/smumgr.h | 1 - drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 1 - 6 files changed, 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index 5450744..ecc4141 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -52,10 +52,6 @@ static int amdgpu_powerplay_init(struct amdgpu_device *adev) pp_init->chip_family = adev->family; pp_init->chip_id = adev->asic_type; pp_init->device = amdgpu_cgs_create_device(adev); - pp_init->rev_id = adev->pdev->revision; - pp_init->sub_sys_id = adev->pdev->subsystem_device; - pp_init->sub_vendor_id = adev->pdev->subsystem_vendor; - ret = amd_powerplay_init(pp_init, amd_pp); kfree(pp_init); #endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index d829076..50d465d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -76,9 +76,6 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) hwmgr->device = pp_init->device; hwmgr->chip_family = pp_init->chip_family; hwmgr->chip_id = pp_init->chip_id; - hwmgr->hw_revision = pp_init->rev_id; - hwmgr->sub_sys_id = pp_init->sub_sys_id; - hwmgr->sub_vendor_id = pp_init->sub_vendor_id; hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; hwmgr->power_source = PP_PowerSource_AC; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 3f8172f..18f39e8 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -131,9 +131,6 @@ struct amd_pp_init { struct cgs_device *device; uint32_t chip_family; uint32_t chip_id; - uint32_t rev_id; - uint16_t sub_sys_id; - uint16_t sub_vendor_id; }; enum amd_pp_display_config_type{ diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 36b4ec9..aca94e0 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -579,9 +579,6 @@ struct phm_microcode_version_info { struct pp_hwmgr { uint32_t chip_family; uint32_t chip_id; - uint32_t hw_revision; - uint32_t sub_sys_id; - uint32_t sub_vendor_id; void *device; struct pp_smumgr *smumgr; diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h index 3c235f0..dede153 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h @@ -74,7 +74,6 @@ struct pp_smumgr_func { struct pp_smumgr { uint32_t chip_family; uint32_t chip_id; - uint32_t hw_revision; void *device; void *backend; uint32_t usec_timeout; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index cf3cabe..e6dc95d 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -48,7 +48,6 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle) smumgr->device = pp_init->device; smumgr->chip_family = pp_init->chip_family; smumgr->chip_id = pp_init->chip_id; - smumgr->hw_revision = pp_init->rev_id; smumgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; smumgr->reload_fw = 1; handle->smu_mgr = smumgr; -- cgit v1.1 From c08770eb8a442430420efd826981bbc3b2a1e341 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 24 Aug 2016 19:39:06 +0800 Subject: drm/amdgpu: refine uvd gate logic for CI. uvd dpm will be controlled by uvd. dpm just disable uvd dpm in case of suspend when play video. due to the new logic of uvd_begin_use/end_use, if disable uvd dpm in late init, will have no chance to enable uvd dpm after resume until play video again. Change-Id: I70e3d7efe63edad37f26e6c5ea089da1135c0ab5 Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index a0d63a2..1d8c375 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -5396,7 +5396,7 @@ static void ci_dpm_disable(struct amdgpu_device *adev) amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, AMDGPU_THERMAL_IRQ_HIGH_TO_LOW); - ci_dpm_powergate_uvd(adev, false); + ci_dpm_powergate_uvd(adev, true); if (!amdgpu_ci_is_smc_running(adev)) return; @@ -6036,7 +6036,7 @@ static int ci_dpm_init(struct amdgpu_device *adev) pi->caps_dynamic_ac_timing = true; - pi->uvd_power_gated = false; + pi->uvd_power_gated = true; /* make sure dc limits are valid */ if ((adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) || @@ -6179,8 +6179,6 @@ static int ci_dpm_late_init(void *handle) if (ret) return ret; - ci_dpm_powergate_uvd(adev, true); - return 0; } -- cgit v1.1 From cc945ce3ab563d7dd7657510e1990f6f606c9b46 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 25 Aug 2016 12:16:24 -0400 Subject: drm/amd/amdgpu: Fix memleak in cz_parse_power_table() If one of the entries fails to be allocated then free all of the previous entries before freeing the array which holds their pointers. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index 794c5f3..9c2ab73 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -350,6 +350,8 @@ static int cz_parse_power_table(struct amdgpu_device *adev) ps = kzalloc(sizeof(struct cz_ps), GFP_KERNEL); if (ps == NULL) { + for (j = 0; j < i; j++) + kfree(adev->pm.dpm.ps[j].ps_priv); kfree(adev->pm.dpm.ps); return -ENOMEM; } -- cgit v1.1 From e701f97ff34a3ec904c19d72a7ca81eed98d5ad9 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 25 Aug 2016 12:41:15 -0400 Subject: drm/amd/amdgpu: Clean up memory leak in cz_dpm_init(). If init fails free up any allocated memory. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index 9c2ab73..e7ea28c 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -44,6 +44,7 @@ static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate); static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate); +static void cz_dpm_fini(struct amdgpu_device *adev); static struct cz_ps *cz_get_ps(struct amdgpu_ps *rps) { @@ -411,11 +412,11 @@ static int cz_dpm_init(struct amdgpu_device *adev) ret = amdgpu_get_platform_caps(adev); if (ret) - return ret; + goto err; ret = amdgpu_parse_extended_power_table(adev); if (ret) - return ret; + goto err; pi->sram_end = SMC_RAM_END; @@ -469,23 +470,26 @@ static int cz_dpm_init(struct amdgpu_device *adev) ret = cz_parse_sys_info_table(adev); if (ret) - return ret; + goto err; cz_patch_voltage_values(adev); cz_construct_boot_state(adev); ret = cz_parse_power_table(adev); if (ret) - return ret; + goto err; ret = cz_process_firmware_header(adev); if (ret) - return ret; + goto err; pi->dpm_enabled = true; pi->uvd_dynamic_pg = false; return 0; +err: + cz_dpm_fini(adev); + return ret; } static void cz_dpm_fini(struct amdgpu_device *adev) -- cgit v1.1 From 15f441db96adcac1dc86196b301f4204452bfe0c Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 25 Aug 2016 13:02:06 -0400 Subject: drm/amd/amdgpu: Tidy up cz_dpm.c Various minor formatting changes. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cz_dpm.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index e7ea28c..f80a083 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -678,17 +678,12 @@ static void cz_reset_ap_mask(struct amdgpu_device *adev) struct cz_power_info *pi = cz_get_pi(adev); pi->active_process_mask = 0; - } static int cz_dpm_download_pptable_from_smu(struct amdgpu_device *adev, void **table) { - int ret = 0; - - ret = cz_smu_download_pptable(adev, table); - - return ret; + return cz_smu_download_pptable(adev, table); } static int cz_dpm_upload_pptable_to_smu(struct amdgpu_device *adev) @@ -828,9 +823,9 @@ static void cz_init_sclk_limit(struct amdgpu_device *adev) pi->sclk_dpm.hard_min_clk = 0; cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxSclkLevel); level = cz_get_argument(adev); - if (level < table->count) + if (level < table->count) { clock = table->entries[level].clk; - else { + } else { DRM_ERROR("Invalid SLCK Voltage Dependency table entry.\n"); clock = table->entries[table->count - 1].clk; } @@ -856,9 +851,9 @@ static void cz_init_uvd_limit(struct amdgpu_device *adev) pi->uvd_dpm.hard_min_clk = 0; cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxUvdLevel); level = cz_get_argument(adev); - if (level < table->count) + if (level < table->count) { clock = table->entries[level].vclk; - else { + } else { DRM_ERROR("Invalid UVD Voltage Dependency table entry.\n"); clock = table->entries[table->count - 1].vclk; } @@ -884,9 +879,9 @@ static void cz_init_vce_limit(struct amdgpu_device *adev) pi->vce_dpm.hard_min_clk = table->entries[0].ecclk; cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxEclkLevel); level = cz_get_argument(adev); - if (level < table->count) + if (level < table->count) { clock = table->entries[level].ecclk; - else { + } else { /* future BIOS would fix this error */ DRM_ERROR("Invalid VCE Voltage Dependency table entry.\n"); clock = table->entries[table->count - 1].ecclk; @@ -913,9 +908,9 @@ static void cz_init_acp_limit(struct amdgpu_device *adev) pi->acp_dpm.hard_min_clk = 0; cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxAclkLevel); level = cz_get_argument(adev); - if (level < table->count) + if (level < table->count) { clock = table->entries[level].clk; - else { + } else { DRM_ERROR("Invalid ACP Voltage Dependency table entry.\n"); clock = table->entries[table->count - 1].clk; } @@ -940,7 +935,6 @@ static void cz_init_sclk_threshold(struct amdgpu_device *adev) struct cz_power_info *pi = cz_get_pi(adev); pi->low_sclk_interrupt_threshold = 0; - } static void cz_dpm_setup_asic(struct amdgpu_device *adev) @@ -1213,7 +1207,7 @@ static int cz_enable_didt(struct amdgpu_device *adev, bool enable) int ret; if (pi->caps_sq_ramping || pi->caps_db_ramping || - pi->caps_td_ramping || pi->caps_tcp_ramping) { + pi->caps_td_ramping || pi->caps_tcp_ramping) { if (adev->gfx.gfx_current_status != AMDGPU_GFX_SAFE_MODE) { ret = cz_disable_cgpg(adev); if (ret) { @@ -1287,7 +1281,7 @@ static void cz_apply_state_adjust_rules(struct amdgpu_device *adev, ps->force_high = false; ps->need_dfs_bypass = true; pi->video_start = new_rps->dclk || new_rps->vclk || - new_rps->evclk || new_rps->ecclk; + new_rps->evclk || new_rps->ecclk; if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) @@ -1345,7 +1339,6 @@ static int cz_dpm_enable(struct amdgpu_device *adev) } cz_reset_acp_boot_level(adev); - cz_update_current_ps(adev, adev->pm.dpm.boot_ps); return 0; @@ -1675,7 +1668,6 @@ static void cz_dpm_post_set_power_state(struct amdgpu_device *adev) struct amdgpu_ps *ps = &pi->requested_rps; cz_update_current_ps(adev, ps); - } static int cz_dpm_force_highest(struct amdgpu_device *adev) @@ -2207,7 +2199,6 @@ static int cz_update_vce_dpm(struct amdgpu_device *adev) /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */ if (pi->caps_stable_power_state) { pi->vce_dpm.hard_min_clk = table->entries[table->count-1].ecclk; - } else { /* non-stable p-state cases. without vce.Arbiter.EcclkHardMin */ /* leave it as set by user */ /*pi->vce_dpm.hard_min_clk = table->entries[0].ecclk;*/ -- cgit v1.1 From 95844d20ae024b5d553c9923a0d3145c3956bf69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 17 Aug 2016 23:49:27 +0200 Subject: drm/amdgpu: throttle buffer migrations at CS using a fixed MBps limit (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old mechanism used a per-submission limit that didn't take previous submissions within the same time frame into account. It also filled VRAM slowly when VRAM usage dropped due to a big eviction or buffer deallocation. This new method establishes a configurable MBps limit that is obeyed when VRAM usage is very high. When VRAM usage is not very high, it gives the driver the freedom to fill it quickly. The result is more consistent performance. It can't keep the BO move rate low if lots of evictions are happening due to VRAM fragmentation, or if a big buffer is being migrated. The amdgpu.moverate parameter can be used to set a non-default limit. Measurements can be done to find out which amdgpu.moverate setting gives the best results. Mainly APUs and cards with small VRAM will benefit from this. For F1 2015, anything with 2 GB VRAM or less will benefit. Some benchmark results - F1 2015 (Tonga 2GB): Limit MinFPS AvgFPS Old code: 14 32.6 128 MB/s: 28 41 64 MB/s: 15.5 43 32 MB/s: 28.7 43.4 8 MB/s: 27.8 44.4 8 MB/s: 21.9 42.8 (different run) Random drops in Min FPS can still occur (due to fragmented VRAM?), but the average FPS is much better. 8 MB/s is probably a good limit for this game & the current VRAM management. The random FPS drops are still to be tackled. v2: use a spinlock Signed-off-by: Marek Olšák Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 9 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 152 ++++++++++++++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 + 4 files changed, 127 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 4cfcf9c..938ef1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -64,6 +64,7 @@ extern int amdgpu_modeset; extern int amdgpu_vram_limit; extern int amdgpu_gart_size; +extern int amdgpu_moverate; extern int amdgpu_benchmarking; extern int amdgpu_testing; extern int amdgpu_audio; @@ -2034,6 +2035,14 @@ struct amdgpu_device { atomic64_t num_evictions; atomic_t gpu_reset_counter; + /* data for buffer migration throttling */ + struct { + spinlock_t lock; + s64 last_update_us; + s64 accum_us; /* accumulated microseconds */ + u32 log2_max_MBps; + } mm_stats; + /* display */ bool enable_virtual_display; struct amdgpu_mode_info mode_info; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index d80e5d3..8292757 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -235,56 +235,115 @@ free_chunk: return ret; } -/* Returns how many bytes TTM can move per IB. +/* Convert microseconds to bytes. */ +static u64 us_to_bytes(struct amdgpu_device *adev, s64 us) +{ + if (us <= 0 || !adev->mm_stats.log2_max_MBps) + return 0; + + /* Since accum_us is incremented by a million per second, just + * multiply it by the number of MB/s to get the number of bytes. + */ + return us << adev->mm_stats.log2_max_MBps; +} + +static s64 bytes_to_us(struct amdgpu_device *adev, u64 bytes) +{ + if (!adev->mm_stats.log2_max_MBps) + return 0; + + return bytes >> adev->mm_stats.log2_max_MBps; +} + +/* Returns how many bytes TTM can move right now. If no bytes can be moved, + * it returns 0. If it returns non-zero, it's OK to move at least one buffer, + * which means it can go over the threshold once. If that happens, the driver + * will be in debt and no other buffer migrations can be done until that debt + * is repaid. + * + * This approach allows moving a buffer of any size (it's important to allow + * that). + * + * The currency is simply time in microseconds and it increases as the clock + * ticks. The accumulated microseconds (us) are converted to bytes and + * returned. */ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev) { - u64 real_vram_size = adev->mc.real_vram_size; - u64 vram_usage = atomic64_read(&adev->vram_usage); + s64 time_us, increment_us; + u64 max_bytes; + u64 free_vram, total_vram, used_vram; - /* This function is based on the current VRAM usage. + /* Allow a maximum of 200 accumulated ms. This is basically per-IB + * throttling. * - * - If all of VRAM is free, allow relocating the number of bytes that - * is equal to 1/4 of the size of VRAM for this IB. + * It means that in order to get full max MBps, at least 5 IBs per + * second must be submitted and not more than 200ms apart from each + * other. + */ + const s64 us_upper_bound = 200000; - * - If more than one half of VRAM is occupied, only allow relocating - * 1 MB of data for this IB. - * - * - From 0 to one half of used VRAM, the threshold decreases - * linearly. - * __________________ - * 1/4 of -|\ | - * VRAM | \ | - * | \ | - * | \ | - * | \ | - * | \ | - * | \ | - * | \________|1 MB - * |----------------| - * VRAM 0 % 100 % - * used used - * - * Note: It's a threshold, not a limit. The threshold must be crossed - * for buffer relocations to stop, so any buffer of an arbitrary size - * can be moved as long as the threshold isn't crossed before - * the relocation takes place. We don't want to disable buffer - * relocations completely. + if (!adev->mm_stats.log2_max_MBps) + return 0; + + total_vram = adev->mc.real_vram_size - adev->vram_pin_size; + used_vram = atomic64_read(&adev->vram_usage); + free_vram = used_vram >= total_vram ? 0 : total_vram - used_vram; + + spin_lock(&adev->mm_stats.lock); + + /* Increase the amount of accumulated us. */ + time_us = ktime_to_us(ktime_get()); + increment_us = time_us - adev->mm_stats.last_update_us; + adev->mm_stats.last_update_us = time_us; + adev->mm_stats.accum_us = min(adev->mm_stats.accum_us + increment_us, + us_upper_bound); + + /* This prevents the short period of low performance when the VRAM + * usage is low and the driver is in debt or doesn't have enough + * accumulated us to fill VRAM quickly. * - * The idea is that buffers should be placed in VRAM at creation time - * and TTM should only do a minimum number of relocations during - * command submission. In practice, you need to submit at least - * a dozen IBs to move all buffers to VRAM if they are in GTT. + * The situation can occur in these cases: + * - a lot of VRAM is freed by userspace + * - the presence of a big buffer causes a lot of evictions + * (solution: split buffers into smaller ones) * - * Also, things can get pretty crazy under memory pressure and actual - * VRAM usage can change a lot, so playing safe even at 50% does - * consistently increase performance. + * If 128 MB or 1/8th of VRAM is free, start filling it now by setting + * accum_us to a positive number. */ + if (free_vram >= 128 * 1024 * 1024 || free_vram >= total_vram / 8) { + s64 min_us; + + /* Be more aggresive on dGPUs. Try to fill a portion of free + * VRAM now. + */ + if (!(adev->flags & AMD_IS_APU)) + min_us = bytes_to_us(adev, free_vram / 4); + else + min_us = 0; /* Reset accum_us on APUs. */ + + adev->mm_stats.accum_us = max(min_us, adev->mm_stats.accum_us); + } - u64 half_vram = real_vram_size >> 1; - u64 half_free_vram = vram_usage >= half_vram ? 0 : half_vram - vram_usage; - u64 bytes_moved_threshold = half_free_vram >> 1; - return max(bytes_moved_threshold, 1024*1024ull); + /* This returns 0 if the driver is in debt to disallow (optional) + * buffer moves. + */ + max_bytes = us_to_bytes(adev, adev->mm_stats.accum_us); + + spin_unlock(&adev->mm_stats.lock); + return max_bytes; +} + +/* Report how many bytes have really been moved for the last command + * submission. This can result in a debt that can stop buffer migrations + * temporarily. + */ +static void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, + u64 num_bytes) +{ + spin_lock(&adev->mm_stats.lock); + adev->mm_stats.accum_us -= bytes_to_us(adev, num_bytes); + spin_unlock(&adev->mm_stats.lock); } static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, @@ -297,15 +356,10 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, if (bo->pin_count) return 0; - /* Avoid moving this one if we have moved too many buffers - * for this IB already. - * - * Note that this allows moving at least one buffer of - * any size, because it doesn't take the current "bo" - * into account. We don't want to disallow buffer moves - * completely. + /* Don't move this buffer if we have depleted our allowance + * to move it. Don't move anything if the threshold is zero. */ - if (p->bytes_moved <= p->bytes_moved_threshold) + if (p->bytes_moved < p->bytes_moved_threshold) domain = bo->prefered_domains; else domain = bo->allowed_domains; @@ -494,6 +548,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, goto error_validate; } + amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved); + fpriv->vm.last_eviction_counter = atomic64_read(&p->adev->num_evictions); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 1ef4034..847583d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1490,6 +1490,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, { int r, i; bool runtime = false; + u32 max_MBps; adev->shutdown = false; adev->dev = &pdev->dev; @@ -1549,6 +1550,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, spin_lock_init(&adev->didt_idx_lock); spin_lock_init(&adev->gc_cac_idx_lock); spin_lock_init(&adev->audio_endpt_idx_lock); + spin_lock_init(&adev->mm_stats.lock); INIT_LIST_HEAD(&adev->shadow_list); mutex_init(&adev->shadow_list_lock); @@ -1660,6 +1662,14 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->accel_working = true; + /* Initialize the buffer migration limit. */ + if (amdgpu_moverate >= 0) + max_MBps = amdgpu_moverate; + else + max_MBps = 8; /* Allow 8 MB/s. */ + /* Get a log2 for easy divisions. */ + adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps)); + amdgpu_fbdev_init(adev); r = amdgpu_ib_pool_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 1b787d9..6fed75454 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -62,6 +62,7 @@ int amdgpu_vram_limit = 0; int amdgpu_gart_size = -1; /* auto */ +int amdgpu_moverate = -1; /* auto */ int amdgpu_benchmarking = 0; int amdgpu_testing = 0; int amdgpu_audio = -1; @@ -100,6 +101,9 @@ module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc., -1 = auto)"); module_param_named(gartsize, amdgpu_gart_size, int, 0600); +MODULE_PARM_DESC(moverate, "Maximum buffer migration rate in MB/s. (32, 64, etc., -1=auto, 0=1=disabled)"); +module_param_named(moverate, amdgpu_moverate, int, 0600); + MODULE_PARM_DESC(benchmark, "Run benchmark"); module_param_named(benchmark, amdgpu_benchmarking, int, 0444); -- cgit v1.1 From b80b13f0cd775669828199ce9b3aee12b9cf8314 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 26 Aug 2016 10:29:19 -0400 Subject: drm/amd/powerplay: Fix CZ SMU firmware load check (v4) Remove an errant return in the middle of the check function as well as check for success in the start function. (v2) Add return check to smu_load_fw() (v3) Don't return early if SMU load check fails (v4) No returns! :-) Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c index 87c023e..e6464e2 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c @@ -195,9 +195,6 @@ static int cz_check_fw_load_finish(struct pp_smumgr *smumgr, if (smumgr == NULL || smumgr->device == NULL) return -EINVAL; - return cgs_read_register(smumgr->device, - mmSMU_MP1_SRBM2P_ARG_0); - cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX, index); for (i = 0; i < smumgr->usec_timeout; i++) { @@ -275,7 +272,10 @@ static int cz_start_smu(struct pp_smumgr *smumgr) if (smumgr->chip_id == CHIP_STONEY) fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK); - cz_request_smu_load_fw(smumgr); + ret = cz_request_smu_load_fw(smumgr); + if (ret) + printk(KERN_ERR "[ powerplay] SMU firmware load failed\n"); + cz_check_fw_load_finish(smumgr, fw_to_check); ret = cz_load_mec_firmware(smumgr); -- cgit v1.1 From a3477255b7e8cd38b5ae6a7ad9d7bec881822453 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 26 Aug 2016 12:42:36 -0400 Subject: drm/amd/powerplay: Tidy up cz SMU manager Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c index e6464e2..cc94c4f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c @@ -89,13 +89,8 @@ static int cz_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) if (result != 0) return result; - result = SMUM_WAIT_FIELD_UNEQUAL(smumgr, + return SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); - - if (result != 0) - return result; - - return 0; } static int cz_set_smc_sram_address(struct pp_smumgr *smumgr, @@ -177,11 +172,9 @@ static int cz_request_smu_load_fw(struct pp_smumgr *smumgr) cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, cz_smu->toc_entry_power_profiling_index); - result = cz_send_msg_to_smc_with_parameter(smumgr, + return cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, cz_smu->toc_entry_initialize_index); - - return result; } static int cz_check_fw_load_finish(struct pp_smumgr *smumgr, @@ -610,19 +603,12 @@ static int cz_smu_construct_toc(struct pp_smumgr *smumgr) struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; cz_smu->toc_entry_used_count = 0; - cz_smu_initialize_toc_empty_job_list(smumgr); - cz_smu_construct_toc_for_rlc_aram_save(smumgr); - cz_smu_construct_toc_for_vddgfx_enter(smumgr); - cz_smu_construct_toc_for_vddgfx_exit(smumgr); - cz_smu_construct_toc_for_power_profiling(smumgr); - cz_smu_construct_toc_for_bootup(smumgr); - cz_smu_construct_toc_for_clock_table(smumgr); return 0; -- cgit v1.1 From 610ecfd6b4989c9bad40f75d4693bfc5c1aac287 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 26 Aug 2016 12:43:14 -0400 Subject: drm/amd/powerplay: Fix up return codes in cz SMU manager Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c index cc94c4f..f51bd8d 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c @@ -101,12 +101,12 @@ static int cz_set_smc_sram_address(struct pp_smumgr *smumgr, if (0 != (3 & smc_address)) { printk(KERN_ERR "[ powerplay ] SMC address must be 4 byte aligned\n"); - return -1; + return -EINVAL; } if (limit <= (smc_address + 3)) { printk(KERN_ERR "[ powerplay ] SMC address beyond the SMC RAM area\n"); - return -1; + return -EINVAL; } cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX_0, @@ -124,9 +124,10 @@ static int cz_write_smc_sram_dword(struct pp_smumgr *smumgr, return -EINVAL; result = cz_set_smc_sram_address(smumgr, smc_address, limit); - cgs_write_register(smumgr->device, mmMP0PUB_IND_DATA_0, value); + if (!result) + cgs_write_register(smumgr->device, mmMP0PUB_IND_DATA_0, value); - return 0; + return result; } static int cz_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, -- cgit v1.1 From 83667ed69802532cd2f7933b770ddb2a10d5e480 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 26 Aug 2016 12:44:01 -0400 Subject: drm/amd/powerplay: Only load SDMA0/MEC firmware once on Stoney (v2) Only load the SDMA0/MEC1 firmware once in the Carrizo SMU manager driver. (v2) Avoid loading SDMA0 twice too. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c index f51bd8d..f839783 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c @@ -560,10 +560,7 @@ static int cz_smu_construct_toc_for_bootup(struct pp_smumgr *smumgr) cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); - if (smumgr->chip_id == CHIP_STONEY) - cz_smu_populate_single_ucode_load_task(smumgr, - CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); - else + if (smumgr->chip_id != CHIP_STONEY) cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false); cz_smu_populate_single_ucode_load_task(smumgr, @@ -574,10 +571,7 @@ static int cz_smu_construct_toc_for_bootup(struct pp_smumgr *smumgr) CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - if (smumgr->chip_id == CHIP_STONEY) - cz_smu_populate_single_ucode_load_task(smumgr, - CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - else + if (smumgr->chip_id != CHIP_STONEY) cz_smu_populate_single_ucode_load_task(smumgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); cz_smu_populate_single_ucode_load_task(smumgr, -- cgit v1.1 From 738d98c994e044cbe326dd27d9bee381b04c5b0a Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Fri, 26 Aug 2016 17:10:28 -0400 Subject: drm/amd/powerplay: Remove unused variable causing compile warning If treating warnings as errors this causes a build error Signed-off-by: Jordan Lazare Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c index f839783..5a44485 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c @@ -144,7 +144,6 @@ static int cz_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, static int cz_request_smu_load_fw(struct pp_smumgr *smumgr) { struct cz_smumgr *cz_smu = (struct cz_smumgr *)(smumgr->backend); - int result = 0; uint32_t smc_address; if (!smumgr->reload_fw) { -- cgit v1.1 From 6fc0deaf58f228cb2676453eac3667744477ab62 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Mon, 29 Aug 2016 08:39:29 -0400 Subject: drm/amd/amdgpu: debugfs SMC addresses are byte addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 847583d..71fe5c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2610,7 +2610,7 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, while (size) { uint32_t value; - value = RREG32_SMC(*pos >> 2); + value = RREG32_SMC(*pos); r = put_user(value, (uint32_t *)buf); if (r) return r; @@ -2641,7 +2641,7 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user * if (r) return r; - WREG32_SMC(*pos >> 2, value); + WREG32_SMC(*pos, value); result += 4; buf += 4; -- cgit v1.1 From c2167a659cc91075417018b88437da86633bb455 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Fri, 26 Aug 2016 14:12:37 +0800 Subject: drm/amdgpu:add switch buffer to end of CS (v2) sync switch buffer scheme with windows kmd for gfx v8, step1: append a switch_buffer to the end of CS v2:rebase on latest staging Signed-off-by: Monk Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 ++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 938ef1c..e31ffe8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -319,6 +319,7 @@ struct amdgpu_ring_funcs { /* note usage for clock and power gating */ void (*begin_use)(struct amdgpu_ring *ring); void (*end_use)(struct amdgpu_ring *ring); + void (*emit_switch_buffer) (struct amdgpu_ring *ring); }; /* @@ -2254,6 +2255,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_ring_emit_gds_switch(r, v, db, ds, wb, ws, ab, as) (r)->funcs->emit_gds_switch((r), (v), (db), (ds), (wb), (ws), (ab), (as)) #define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r)) #define amdgpu_ring_emit_hdp_invalidate(r) (r)->funcs->emit_hdp_invalidate((r)) +#define amdgpu_ring_emit_switch_buffer(r) (r)->funcs->emit_switch_buffer((r)) #define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib))) #define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r)) #define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index f5810f7..11f2fba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -210,6 +210,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, amdgpu_ring_patch_cond_exec(ring, patch_offset); ring->current_ctx = ctx; + if (ring->funcs->emit_switch_buffer) + amdgpu_ring_emit_switch_buffer(ring); amdgpu_ring_commit(ring); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 6022208..b8bc413 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6087,6 +6087,12 @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring, amdgpu_ring_write(ring, upper_32_bits(seq)); } +static void gfx_v8_ring_emit_sb(struct amdgpu_ring *ring) +{ + amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); + amdgpu_ring_write(ring, 0); +} + static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, enum amdgpu_interrupt_state state) { @@ -6268,6 +6274,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .test_ib = gfx_v8_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, + .emit_switch_buffer = gfx_v8_ring_emit_sb, }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { -- cgit v1.1 From 26d721c5f5f1d2b140c6df5a361dcebc8cbf090b Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 21 Jan 2016 17:00:06 +0800 Subject: drm/amdgpu: add SI asics types v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/amd_shared.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index db71041..c934b78c 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -29,7 +29,12 @@ * Supported ASIC types */ enum amd_asic_type { - CHIP_BONAIRE = 0, + CHIP_TAHITI = 0, + CHIP_PITCAIRN, + CHIP_VERDE, + CHIP_OLAND, + CHIP_HAINAN, + CHIP_BONAIRE, CHIP_KAVERI, CHIP_KABINI, CHIP_HAWAII, -- cgit v1.1 From 0f27e46258ee73e2fd149f91cb176475ce9b7537 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 13:53:10 +0800 Subject: drm/amdgpu: add si header files v4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v4: drop unused DCE6 macro Acked-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- .../drm/amd/include/asic_reg/si/clearstate_si.h | 941 ++++++++ drivers/gpu/drm/amd/include/asic_reg/si/si_reg.h | 105 + drivers/gpu/drm/amd/include/asic_reg/si/sid.h | 2408 ++++++++++++++++++++ 3 files changed, 3454 insertions(+) create mode 100644 drivers/gpu/drm/amd/include/asic_reg/si/clearstate_si.h create mode 100644 drivers/gpu/drm/amd/include/asic_reg/si/si_reg.h create mode 100644 drivers/gpu/drm/amd/include/asic_reg/si/sid.h diff --git a/drivers/gpu/drm/amd/include/asic_reg/si/clearstate_si.h b/drivers/gpu/drm/amd/include/asic_reg/si/clearstate_si.h new file mode 100644 index 0000000..66e39cd --- /dev/null +++ b/drivers/gpu/drm/amd/include/asic_reg/si/clearstate_si.h @@ -0,0 +1,941 @@ +/* + * Copyright 2013 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +static const u32 si_SECT_CONTEXT_def_1[] = +{ + 0x00000000, // DB_RENDER_CONTROL + 0x00000000, // DB_COUNT_CONTROL + 0x00000000, // DB_DEPTH_VIEW + 0x00000000, // DB_RENDER_OVERRIDE + 0x00000000, // DB_RENDER_OVERRIDE2 + 0x00000000, // DB_HTILE_DATA_BASE + 0, // HOLE + 0, // HOLE + 0x00000000, // DB_DEPTH_BOUNDS_MIN + 0x00000000, // DB_DEPTH_BOUNDS_MAX + 0x00000000, // DB_STENCIL_CLEAR + 0x00000000, // DB_DEPTH_CLEAR + 0x00000000, // PA_SC_SCREEN_SCISSOR_TL + 0x40004000, // PA_SC_SCREEN_SCISSOR_BR + 0, // HOLE + 0x00000000, // DB_DEPTH_INFO + 0x00000000, // DB_Z_INFO + 0x00000000, // DB_STENCIL_INFO + 0x00000000, // DB_Z_READ_BASE + 0x00000000, // DB_STENCIL_READ_BASE + 0x00000000, // DB_Z_WRITE_BASE + 0x00000000, // DB_STENCIL_WRITE_BASE + 0x00000000, // DB_DEPTH_SIZE + 0x00000000, // DB_DEPTH_SLICE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // TA_BC_BASE_ADDR + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // COHER_DEST_BASE_2 + 0x00000000, // COHER_DEST_BASE_3 + 0x00000000, // PA_SC_WINDOW_OFFSET + 0x80000000, // PA_SC_WINDOW_SCISSOR_TL + 0x40004000, // PA_SC_WINDOW_SCISSOR_BR + 0x0000ffff, // PA_SC_CLIPRECT_RULE + 0x00000000, // PA_SC_CLIPRECT_0_TL + 0x40004000, // PA_SC_CLIPRECT_0_BR + 0x00000000, // PA_SC_CLIPRECT_1_TL + 0x40004000, // PA_SC_CLIPRECT_1_BR + 0x00000000, // PA_SC_CLIPRECT_2_TL + 0x40004000, // PA_SC_CLIPRECT_2_BR + 0x00000000, // PA_SC_CLIPRECT_3_TL + 0x40004000, // PA_SC_CLIPRECT_3_BR + 0xaa99aaaa, // PA_SC_EDGERULE + 0x00000000, // PA_SU_HARDWARE_SCREEN_OFFSET + 0xffffffff, // CB_TARGET_MASK + 0xffffffff, // CB_SHADER_MASK + 0x80000000, // PA_SC_GENERIC_SCISSOR_TL + 0x40004000, // PA_SC_GENERIC_SCISSOR_BR + 0x00000000, // COHER_DEST_BASE_0 + 0x00000000, // COHER_DEST_BASE_1 + 0x80000000, // PA_SC_VPORT_SCISSOR_0_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_0_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_1_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_1_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_2_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_2_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_3_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_3_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_4_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_4_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_5_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_5_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_6_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_6_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_7_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_7_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_8_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_8_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_9_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_9_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_10_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_10_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_11_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_11_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_12_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_12_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_13_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_13_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_14_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_14_BR + 0x80000000, // PA_SC_VPORT_SCISSOR_15_TL + 0x40004000, // PA_SC_VPORT_SCISSOR_15_BR + 0x00000000, // PA_SC_VPORT_ZMIN_0 + 0x3f800000, // PA_SC_VPORT_ZMAX_0 + 0x00000000, // PA_SC_VPORT_ZMIN_1 + 0x3f800000, // PA_SC_VPORT_ZMAX_1 + 0x00000000, // PA_SC_VPORT_ZMIN_2 + 0x3f800000, // PA_SC_VPORT_ZMAX_2 + 0x00000000, // PA_SC_VPORT_ZMIN_3 + 0x3f800000, // PA_SC_VPORT_ZMAX_3 + 0x00000000, // PA_SC_VPORT_ZMIN_4 + 0x3f800000, // PA_SC_VPORT_ZMAX_4 + 0x00000000, // PA_SC_VPORT_ZMIN_5 + 0x3f800000, // PA_SC_VPORT_ZMAX_5 + 0x00000000, // PA_SC_VPORT_ZMIN_6 + 0x3f800000, // PA_SC_VPORT_ZMAX_6 + 0x00000000, // PA_SC_VPORT_ZMIN_7 + 0x3f800000, // PA_SC_VPORT_ZMAX_7 + 0x00000000, // PA_SC_VPORT_ZMIN_8 + 0x3f800000, // PA_SC_VPORT_ZMAX_8 + 0x00000000, // PA_SC_VPORT_ZMIN_9 + 0x3f800000, // PA_SC_VPORT_ZMAX_9 + 0x00000000, // PA_SC_VPORT_ZMIN_10 + 0x3f800000, // PA_SC_VPORT_ZMAX_10 + 0x00000000, // PA_SC_VPORT_ZMIN_11 + 0x3f800000, // PA_SC_VPORT_ZMAX_11 + 0x00000000, // PA_SC_VPORT_ZMIN_12 + 0x3f800000, // PA_SC_VPORT_ZMAX_12 + 0x00000000, // PA_SC_VPORT_ZMIN_13 + 0x3f800000, // PA_SC_VPORT_ZMAX_13 + 0x00000000, // PA_SC_VPORT_ZMIN_14 + 0x3f800000, // PA_SC_VPORT_ZMAX_14 + 0x00000000, // PA_SC_VPORT_ZMIN_15 + 0x3f800000, // PA_SC_VPORT_ZMAX_15 +}; +static const u32 si_SECT_CONTEXT_def_2[] = +{ + 0x00000000, // CP_PERFMON_CNTX_CNTL + 0x00000000, // CP_RINGID + 0x00000000, // CP_VMID + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0xffffffff, // VGT_MAX_VTX_INDX + 0x00000000, // VGT_MIN_VTX_INDX + 0x00000000, // VGT_INDX_OFFSET + 0x00000000, // VGT_MULTI_PRIM_IB_RESET_INDX + 0, // HOLE + 0x00000000, // CB_BLEND_RED + 0x00000000, // CB_BLEND_GREEN + 0x00000000, // CB_BLEND_BLUE + 0x00000000, // CB_BLEND_ALPHA + 0, // HOLE + 0, // HOLE + 0x00000000, // DB_STENCIL_CONTROL + 0x00000000, // DB_STENCILREFMASK + 0x00000000, // DB_STENCILREFMASK_BF + 0, // HOLE + 0x00000000, // PA_CL_VPORT_XSCALE + 0x00000000, // PA_CL_VPORT_XOFFSET + 0x00000000, // PA_CL_VPORT_YSCALE + 0x00000000, // PA_CL_VPORT_YOFFSET + 0x00000000, // PA_CL_VPORT_ZSCALE + 0x00000000, // PA_CL_VPORT_ZOFFSET + 0x00000000, // PA_CL_VPORT_XSCALE_1 + 0x00000000, // PA_CL_VPORT_XOFFSET_1 + 0x00000000, // PA_CL_VPORT_YSCALE_1 + 0x00000000, // PA_CL_VPORT_YOFFSET_1 + 0x00000000, // PA_CL_VPORT_ZSCALE_1 + 0x00000000, // PA_CL_VPORT_ZOFFSET_1 + 0x00000000, // PA_CL_VPORT_XSCALE_2 + 0x00000000, // PA_CL_VPORT_XOFFSET_2 + 0x00000000, // PA_CL_VPORT_YSCALE_2 + 0x00000000, // PA_CL_VPORT_YOFFSET_2 + 0x00000000, // PA_CL_VPORT_ZSCALE_2 + 0x00000000, // PA_CL_VPORT_ZOFFSET_2 + 0x00000000, // PA_CL_VPORT_XSCALE_3 + 0x00000000, // PA_CL_VPORT_XOFFSET_3 + 0x00000000, // PA_CL_VPORT_YSCALE_3 + 0x00000000, // PA_CL_VPORT_YOFFSET_3 + 0x00000000, // PA_CL_VPORT_ZSCALE_3 + 0x00000000, // PA_CL_VPORT_ZOFFSET_3 + 0x00000000, // PA_CL_VPORT_XSCALE_4 + 0x00000000, // PA_CL_VPORT_XOFFSET_4 + 0x00000000, // PA_CL_VPORT_YSCALE_4 + 0x00000000, // PA_CL_VPORT_YOFFSET_4 + 0x00000000, // PA_CL_VPORT_ZSCALE_4 + 0x00000000, // PA_CL_VPORT_ZOFFSET_4 + 0x00000000, // PA_CL_VPORT_XSCALE_5 + 0x00000000, // PA_CL_VPORT_XOFFSET_5 + 0x00000000, // PA_CL_VPORT_YSCALE_5 + 0x00000000, // PA_CL_VPORT_YOFFSET_5 + 0x00000000, // PA_CL_VPORT_ZSCALE_5 + 0x00000000, // PA_CL_VPORT_ZOFFSET_5 + 0x00000000, // PA_CL_VPORT_XSCALE_6 + 0x00000000, // PA_CL_VPORT_XOFFSET_6 + 0x00000000, // PA_CL_VPORT_YSCALE_6 + 0x00000000, // PA_CL_VPORT_YOFFSET_6 + 0x00000000, // PA_CL_VPORT_ZSCALE_6 + 0x00000000, // PA_CL_VPORT_ZOFFSET_6 + 0x00000000, // PA_CL_VPORT_XSCALE_7 + 0x00000000, // PA_CL_VPORT_XOFFSET_7 + 0x00000000, // PA_CL_VPORT_YSCALE_7 + 0x00000000, // PA_CL_VPORT_YOFFSET_7 + 0x00000000, // PA_CL_VPORT_ZSCALE_7 + 0x00000000, // PA_CL_VPORT_ZOFFSET_7 + 0x00000000, // PA_CL_VPORT_XSCALE_8 + 0x00000000, // PA_CL_VPORT_XOFFSET_8 + 0x00000000, // PA_CL_VPORT_YSCALE_8 + 0x00000000, // PA_CL_VPORT_YOFFSET_8 + 0x00000000, // PA_CL_VPORT_ZSCALE_8 + 0x00000000, // PA_CL_VPORT_ZOFFSET_8 + 0x00000000, // PA_CL_VPORT_XSCALE_9 + 0x00000000, // PA_CL_VPORT_XOFFSET_9 + 0x00000000, // PA_CL_VPORT_YSCALE_9 + 0x00000000, // PA_CL_VPORT_YOFFSET_9 + 0x00000000, // PA_CL_VPORT_ZSCALE_9 + 0x00000000, // PA_CL_VPORT_ZOFFSET_9 + 0x00000000, // PA_CL_VPORT_XSCALE_10 + 0x00000000, // PA_CL_VPORT_XOFFSET_10 + 0x00000000, // PA_CL_VPORT_YSCALE_10 + 0x00000000, // PA_CL_VPORT_YOFFSET_10 + 0x00000000, // PA_CL_VPORT_ZSCALE_10 + 0x00000000, // PA_CL_VPORT_ZOFFSET_10 + 0x00000000, // PA_CL_VPORT_XSCALE_11 + 0x00000000, // PA_CL_VPORT_XOFFSET_11 + 0x00000000, // PA_CL_VPORT_YSCALE_11 + 0x00000000, // PA_CL_VPORT_YOFFSET_11 + 0x00000000, // PA_CL_VPORT_ZSCALE_11 + 0x00000000, // PA_CL_VPORT_ZOFFSET_11 + 0x00000000, // PA_CL_VPORT_XSCALE_12 + 0x00000000, // PA_CL_VPORT_XOFFSET_12 + 0x00000000, // PA_CL_VPORT_YSCALE_12 + 0x00000000, // PA_CL_VPORT_YOFFSET_12 + 0x00000000, // PA_CL_VPORT_ZSCALE_12 + 0x00000000, // PA_CL_VPORT_ZOFFSET_12 + 0x00000000, // PA_CL_VPORT_XSCALE_13 + 0x00000000, // PA_CL_VPORT_XOFFSET_13 + 0x00000000, // PA_CL_VPORT_YSCALE_13 + 0x00000000, // PA_CL_VPORT_YOFFSET_13 + 0x00000000, // PA_CL_VPORT_ZSCALE_13 + 0x00000000, // PA_CL_VPORT_ZOFFSET_13 + 0x00000000, // PA_CL_VPORT_XSCALE_14 + 0x00000000, // PA_CL_VPORT_XOFFSET_14 + 0x00000000, // PA_CL_VPORT_YSCALE_14 + 0x00000000, // PA_CL_VPORT_YOFFSET_14 + 0x00000000, // PA_CL_VPORT_ZSCALE_14 + 0x00000000, // PA_CL_VPORT_ZOFFSET_14 + 0x00000000, // PA_CL_VPORT_XSCALE_15 + 0x00000000, // PA_CL_VPORT_XOFFSET_15 + 0x00000000, // PA_CL_VPORT_YSCALE_15 + 0x00000000, // PA_CL_VPORT_YOFFSET_15 + 0x00000000, // PA_CL_VPORT_ZSCALE_15 + 0x00000000, // PA_CL_VPORT_ZOFFSET_15 + 0x00000000, // PA_CL_UCP_0_X + 0x00000000, // PA_CL_UCP_0_Y + 0x00000000, // PA_CL_UCP_0_Z + 0x00000000, // PA_CL_UCP_0_W + 0x00000000, // PA_CL_UCP_1_X + 0x00000000, // PA_CL_UCP_1_Y + 0x00000000, // PA_CL_UCP_1_Z + 0x00000000, // PA_CL_UCP_1_W + 0x00000000, // PA_CL_UCP_2_X + 0x00000000, // PA_CL_UCP_2_Y + 0x00000000, // PA_CL_UCP_2_Z + 0x00000000, // PA_CL_UCP_2_W + 0x00000000, // PA_CL_UCP_3_X + 0x00000000, // PA_CL_UCP_3_Y + 0x00000000, // PA_CL_UCP_3_Z + 0x00000000, // PA_CL_UCP_3_W + 0x00000000, // PA_CL_UCP_4_X + 0x00000000, // PA_CL_UCP_4_Y + 0x00000000, // PA_CL_UCP_4_Z + 0x00000000, // PA_CL_UCP_4_W + 0x00000000, // PA_CL_UCP_5_X + 0x00000000, // PA_CL_UCP_5_Y + 0x00000000, // PA_CL_UCP_5_Z + 0x00000000, // PA_CL_UCP_5_W + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // SPI_PS_INPUT_CNTL_0 + 0x00000000, // SPI_PS_INPUT_CNTL_1 + 0x00000000, // SPI_PS_INPUT_CNTL_2 + 0x00000000, // SPI_PS_INPUT_CNTL_3 + 0x00000000, // SPI_PS_INPUT_CNTL_4 + 0x00000000, // SPI_PS_INPUT_CNTL_5 + 0x00000000, // SPI_PS_INPUT_CNTL_6 + 0x00000000, // SPI_PS_INPUT_CNTL_7 + 0x00000000, // SPI_PS_INPUT_CNTL_8 + 0x00000000, // SPI_PS_INPUT_CNTL_9 + 0x00000000, // SPI_PS_INPUT_CNTL_10 + 0x00000000, // SPI_PS_INPUT_CNTL_11 + 0x00000000, // SPI_PS_INPUT_CNTL_12 + 0x00000000, // SPI_PS_INPUT_CNTL_13 + 0x00000000, // SPI_PS_INPUT_CNTL_14 + 0x00000000, // SPI_PS_INPUT_CNTL_15 + 0x00000000, // SPI_PS_INPUT_CNTL_16 + 0x00000000, // SPI_PS_INPUT_CNTL_17 + 0x00000000, // SPI_PS_INPUT_CNTL_18 + 0x00000000, // SPI_PS_INPUT_CNTL_19 + 0x00000000, // SPI_PS_INPUT_CNTL_20 + 0x00000000, // SPI_PS_INPUT_CNTL_21 + 0x00000000, // SPI_PS_INPUT_CNTL_22 + 0x00000000, // SPI_PS_INPUT_CNTL_23 + 0x00000000, // SPI_PS_INPUT_CNTL_24 + 0x00000000, // SPI_PS_INPUT_CNTL_25 + 0x00000000, // SPI_PS_INPUT_CNTL_26 + 0x00000000, // SPI_PS_INPUT_CNTL_27 + 0x00000000, // SPI_PS_INPUT_CNTL_28 + 0x00000000, // SPI_PS_INPUT_CNTL_29 + 0x00000000, // SPI_PS_INPUT_CNTL_30 + 0x00000000, // SPI_PS_INPUT_CNTL_31 + 0x00000000, // SPI_VS_OUT_CONFIG + 0, // HOLE + 0x00000000, // SPI_PS_INPUT_ENA + 0x00000000, // SPI_PS_INPUT_ADDR + 0x00000000, // SPI_INTERP_CONTROL_0 + 0x00000002, // SPI_PS_IN_CONTROL + 0, // HOLE + 0x00000000, // SPI_BARYC_CNTL + 0, // HOLE + 0x00000000, // SPI_TMPRING_SIZE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // SPI_WAVE_MGMT_1 + 0x00000000, // SPI_WAVE_MGMT_2 + 0x00000000, // SPI_SHADER_POS_FORMAT + 0x00000000, // SPI_SHADER_Z_FORMAT + 0x00000000, // SPI_SHADER_COL_FORMAT + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // CB_BLEND0_CONTROL + 0x00000000, // CB_BLEND1_CONTROL + 0x00000000, // CB_BLEND2_CONTROL + 0x00000000, // CB_BLEND3_CONTROL + 0x00000000, // CB_BLEND4_CONTROL + 0x00000000, // CB_BLEND5_CONTROL + 0x00000000, // CB_BLEND6_CONTROL + 0x00000000, // CB_BLEND7_CONTROL +}; +static const u32 si_SECT_CONTEXT_def_3[] = +{ + 0x00000000, // PA_CL_POINT_X_RAD + 0x00000000, // PA_CL_POINT_Y_RAD + 0x00000000, // PA_CL_POINT_SIZE + 0x00000000, // PA_CL_POINT_CULL_RAD + 0x00000000, // VGT_DMA_BASE_HI + 0x00000000, // VGT_DMA_BASE +}; +static const u32 si_SECT_CONTEXT_def_4[] = +{ + 0x00000000, // DB_DEPTH_CONTROL + 0x00000000, // DB_EQAA + 0x00000000, // CB_COLOR_CONTROL + 0x00000000, // DB_SHADER_CONTROL + 0x00090000, // PA_CL_CLIP_CNTL + 0x00000004, // PA_SU_SC_MODE_CNTL + 0x00000000, // PA_CL_VTE_CNTL + 0x00000000, // PA_CL_VS_OUT_CNTL + 0x00000000, // PA_CL_NANINF_CNTL + 0x00000000, // PA_SU_LINE_STIPPLE_CNTL + 0x00000000, // PA_SU_LINE_STIPPLE_SCALE + 0x00000000, // PA_SU_PRIM_FILTER_CNTL + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // PA_SU_POINT_SIZE + 0x00000000, // PA_SU_POINT_MINMAX + 0x00000000, // PA_SU_LINE_CNTL + 0x00000000, // PA_SC_LINE_STIPPLE + 0x00000000, // VGT_OUTPUT_PATH_CNTL + 0x00000000, // VGT_HOS_CNTL + 0x00000000, // VGT_HOS_MAX_TESS_LEVEL + 0x00000000, // VGT_HOS_MIN_TESS_LEVEL + 0x00000000, // VGT_HOS_REUSE_DEPTH + 0x00000000, // VGT_GROUP_PRIM_TYPE + 0x00000000, // VGT_GROUP_FIRST_DECR + 0x00000000, // VGT_GROUP_DECR + 0x00000000, // VGT_GROUP_VECT_0_CNTL + 0x00000000, // VGT_GROUP_VECT_1_CNTL + 0x00000000, // VGT_GROUP_VECT_0_FMT_CNTL + 0x00000000, // VGT_GROUP_VECT_1_FMT_CNTL + 0x00000000, // VGT_GS_MODE + 0, // HOLE + 0x00000000, // PA_SC_MODE_CNTL_0 + 0x00000000, // PA_SC_MODE_CNTL_1 + 0x00000000, // VGT_ENHANCE + 0x00000100, // VGT_GS_PER_ES + 0x00000080, // VGT_ES_PER_GS + 0x00000002, // VGT_GS_PER_VS + 0x00000000, // VGT_GSVS_RING_OFFSET_1 + 0x00000000, // VGT_GSVS_RING_OFFSET_2 + 0x00000000, // VGT_GSVS_RING_OFFSET_3 + 0x00000000, // VGT_GS_OUT_PRIM_TYPE + 0x00000000, // IA_ENHANCE +}; +static const u32 si_SECT_CONTEXT_def_5[] = +{ + 0x00000000, // VGT_PRIMITIVEID_EN +}; +static const u32 si_SECT_CONTEXT_def_6[] = +{ + 0x00000000, // VGT_PRIMITIVEID_RESET +}; +static const u32 si_SECT_CONTEXT_def_7[] = +{ + 0x00000000, // VGT_MULTI_PRIM_IB_RESET_EN + 0, // HOLE + 0, // HOLE + 0x00000000, // VGT_INSTANCE_STEP_RATE_0 + 0x00000000, // VGT_INSTANCE_STEP_RATE_1 + 0x000000ff, // IA_MULTI_VGT_PARAM + 0x00000000, // VGT_ESGS_RING_ITEMSIZE + 0x00000000, // VGT_GSVS_RING_ITEMSIZE + 0x00000000, // VGT_REUSE_OFF + 0x00000000, // VGT_VTX_CNT_EN + 0x00000000, // DB_HTILE_SURFACE + 0x00000000, // DB_SRESULTS_COMPARE_STATE0 + 0x00000000, // DB_SRESULTS_COMPARE_STATE1 + 0x00000000, // DB_PRELOAD_CONTROL + 0, // HOLE + 0x00000000, // VGT_STRMOUT_BUFFER_SIZE_0 + 0x00000000, // VGT_STRMOUT_VTX_STRIDE_0 + 0, // HOLE + 0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_0 + 0x00000000, // VGT_STRMOUT_BUFFER_SIZE_1 + 0x00000000, // VGT_STRMOUT_VTX_STRIDE_1 + 0, // HOLE + 0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_1 + 0x00000000, // VGT_STRMOUT_BUFFER_SIZE_2 + 0x00000000, // VGT_STRMOUT_VTX_STRIDE_2 + 0, // HOLE + 0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_2 + 0x00000000, // VGT_STRMOUT_BUFFER_SIZE_3 + 0x00000000, // VGT_STRMOUT_VTX_STRIDE_3 + 0, // HOLE + 0x00000000, // VGT_STRMOUT_BUFFER_OFFSET_3 + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_OFFSET + 0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE + 0x00000000, // VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE + 0, // HOLE + 0x00000000, // VGT_GS_MAX_VERT_OUT + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // VGT_SHADER_STAGES_EN + 0x00000000, // VGT_LS_HS_CONFIG + 0x00000000, // VGT_GS_VERT_ITEMSIZE + 0x00000000, // VGT_GS_VERT_ITEMSIZE_1 + 0x00000000, // VGT_GS_VERT_ITEMSIZE_2 + 0x00000000, // VGT_GS_VERT_ITEMSIZE_3 + 0x00000000, // VGT_TF_PARAM + 0x00000000, // DB_ALPHA_TO_MASK + 0, // HOLE + 0x00000000, // PA_SU_POLY_OFFSET_DB_FMT_CNTL + 0x00000000, // PA_SU_POLY_OFFSET_CLAMP + 0x00000000, // PA_SU_POLY_OFFSET_FRONT_SCALE + 0x00000000, // PA_SU_POLY_OFFSET_FRONT_OFFSET + 0x00000000, // PA_SU_POLY_OFFSET_BACK_SCALE + 0x00000000, // PA_SU_POLY_OFFSET_BACK_OFFSET + 0x00000000, // VGT_GS_INSTANCE_CNT + 0x00000000, // VGT_STRMOUT_CONFIG + 0x00000000, // VGT_STRMOUT_BUFFER_CONFIG + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x00000000, // PA_SC_CENTROID_PRIORITY_0 + 0x00000000, // PA_SC_CENTROID_PRIORITY_1 + 0x00001000, // PA_SC_LINE_CNTL + 0x00000000, // PA_SC_AA_CONFIG + 0x00000005, // PA_SU_VTX_CNTL + 0x3f800000, // PA_CL_GB_VERT_CLIP_ADJ + 0x3f800000, // PA_CL_GB_VERT_DISC_ADJ + 0x3f800000, // PA_CL_GB_HORZ_CLIP_ADJ + 0x3f800000, // PA_CL_GB_HORZ_DISC_ADJ + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2 + 0x00000000, // PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3 + 0xffffffff, // PA_SC_AA_MASK_X0Y0_X1Y0 + 0xffffffff, // PA_SC_AA_MASK_X0Y1_X1Y1 + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0, // HOLE + 0x0000000e, // VGT_VERTEX_REUSE_BLOCK_CNTL + 0x00000010, // VGT_OUT_DEALLOC_CNTL + 0x00000000, // CB_COLOR0_BASE + 0x00000000, // CB_COLOR0_PITCH + 0x00000000, // CB_COLOR0_SLICE + 0x00000000, // CB_COLOR0_VIEW + 0x00000000, // CB_COLOR0_INFO + 0x00000000, // CB_COLOR0_ATTRIB + 0, // HOLE + 0x00000000, // CB_COLOR0_CMASK + 0x00000000, // CB_COLOR0_CMASK_SLICE + 0x00000000, // CB_COLOR0_FMASK + 0x00000000, // CB_COLOR0_FMASK_SLICE + 0x00000000, // CB_COLOR0_CLEAR_WORD0 + 0x00000000, // CB_COLOR0_CLEAR_WORD1 + 0, // HOLE + 0, // HOLE + 0x00000000, // CB_COLOR1_BASE + 0x00000000, // CB_COLOR1_PITCH + 0x00000000, // CB_COLOR1_SLICE + 0x00000000, // CB_COLOR1_VIEW + 0x00000000, // CB_COLOR1_INFO + 0x00000000, // CB_COLOR1_ATTRIB + 0, // HOLE + 0x00000000, // CB_COLOR1_CMASK + 0x00000000, // CB_COLOR1_CMASK_SLICE + 0x00000000, // CB_COLOR1_FMASK + 0x00000000, // CB_COLOR1_FMASK_SLICE + 0x00000000, // CB_COLOR1_CLEAR_WORD0 + 0x00000000, // CB_COLOR1_CLEAR_WORD1 + 0, // HOLE + 0, // HOLE + 0x00000000, // CB_COLOR2_BASE + 0x00000000, // CB_COLOR2_PITCH + 0x00000000, // CB_COLOR2_SLICE + 0x00000000, // CB_COLOR2_VIEW + 0x00000000, // CB_COLOR2_INFO + 0x00000000, // CB_COLOR2_ATTRIB + 0, // HOLE + 0x00000000, // CB_COLOR2_CMASK + 0x00000000, // CB_COLOR2_CMASK_SLICE + 0x00000000, // CB_COLOR2_FMASK + 0x00000000, // CB_COLOR2_FMASK_SLICE + 0x00000000, // CB_COLOR2_CLEAR_WORD0 + 0x00000000, // CB_COLOR2_CLEAR_WORD1 + 0, // HOLE + 0, // HOLE + 0x00000000, // CB_COLOR3_BASE + 0x00000000, // CB_COLOR3_PITCH + 0x00000000, // CB_COLOR3_SLICE + 0x00000000, // CB_COLOR3_VIEW + 0x00000000, // CB_COLOR3_INFO + 0x00000000, // CB_COLOR3_ATTRIB + 0, // HOLE + 0x00000000, // CB_COLOR3_CMASK + 0x00000000, // CB_COLOR3_CMASK_SLICE + 0x00000000, // CB_COLOR3_FMASK + 0x00000000, // CB_COLOR3_FMASK_SLICE + 0x00000000, // CB_COLOR3_CLEAR_WORD0 + 0x00000000, // CB_COLOR3_CLEAR_WORD1 + 0, // HOLE + 0, // HOLE + 0x00000000, // CB_COLOR4_BASE + 0x00000000, // CB_COLOR4_PITCH + 0x00000000, // CB_COLOR4_SLICE + 0x00000000, // CB_COLOR4_VIEW + 0x00000000, // CB_COLOR4_INFO + 0x00000000, // CB_COLOR4_ATTRIB + 0, // HOLE + 0x00000000, // CB_COLOR4_CMASK + 0x00000000, // CB_COLOR4_CMASK_SLICE + 0x00000000, // CB_COLOR4_FMASK + 0x00000000, // CB_COLOR4_FMASK_SLICE + 0x00000000, // CB_COLOR4_CLEAR_WORD0 + 0x00000000, // CB_COLOR4_CLEAR_WORD1 + 0, // HOLE + 0, // HOLE + 0x00000000, // CB_COLOR5_BASE + 0x00000000, // CB_COLOR5_PITCH + 0x00000000, // CB_COLOR5_SLICE + 0x00000000, // CB_COLOR5_VIEW + 0x00000000, // CB_COLOR5_INFO + 0x00000000, // CB_COLOR5_ATTRIB + 0, // HOLE + 0x00000000, // CB_COLOR5_CMASK + 0x00000000, // CB_COLOR5_CMASK_SLICE + 0x00000000, // CB_COLOR5_FMASK + 0x00000000, // CB_COLOR5_FMASK_SLICE + 0x00000000, // CB_COLOR5_CLEAR_WORD0 + 0x00000000, // CB_COLOR5_CLEAR_WORD1 + 0, // HOLE + 0, // HOLE + 0x00000000, // CB_COLOR6_BASE + 0x00000000, // CB_COLOR6_PITCH + 0x00000000, // CB_COLOR6_SLICE + 0x00000000, // CB_COLOR6_VIEW + 0x00000000, // CB_COLOR6_INFO + 0x00000000, // CB_COLOR6_ATTRIB + 0, // HOLE + 0x00000000, // CB_COLOR6_CMASK + 0x00000000, // CB_COLOR6_CMASK_SLICE + 0x00000000, // CB_COLOR6_FMASK + 0x00000000, // CB_COLOR6_FMASK_SLICE + 0x00000000, // CB_COLOR6_CLEAR_WORD0 + 0x00000000, // CB_COLOR6_CLEAR_WORD1 + 0, // HOLE + 0, // HOLE + 0x00000000, // CB_COLOR7_BASE + 0x00000000, // CB_COLOR7_PITCH + 0x00000000, // CB_COLOR7_SLICE + 0x00000000, // CB_COLOR7_VIEW + 0x00000000, // CB_COLOR7_INFO + 0x00000000, // CB_COLOR7_ATTRIB + 0, // HOLE + 0x00000000, // CB_COLOR7_CMASK + 0x00000000, // CB_COLOR7_CMASK_SLICE + 0x00000000, // CB_COLOR7_FMASK + 0x00000000, // CB_COLOR7_FMASK_SLICE + 0x00000000, // CB_COLOR7_CLEAR_WORD0 + 0x00000000, // CB_COLOR7_CLEAR_WORD1 +}; +static const struct cs_extent_def si_SECT_CONTEXT_defs[] = +{ + {si_SECT_CONTEXT_def_1, 0x0000a000, 212 }, + {si_SECT_CONTEXT_def_2, 0x0000a0d8, 272 }, + {si_SECT_CONTEXT_def_3, 0x0000a1f5, 6 }, + {si_SECT_CONTEXT_def_4, 0x0000a200, 157 }, + {si_SECT_CONTEXT_def_5, 0x0000a2a1, 1 }, + {si_SECT_CONTEXT_def_6, 0x0000a2a3, 1 }, + {si_SECT_CONTEXT_def_7, 0x0000a2a5, 233 }, + { NULL, 0, 0 } +}; +static const struct cs_section_def si_cs_data[] = { + { si_SECT_CONTEXT_defs, SECT_CONTEXT }, + { NULL, SECT_NONE } +}; diff --git a/drivers/gpu/drm/amd/include/asic_reg/si/si_reg.h b/drivers/gpu/drm/amd/include/asic_reg/si/si_reg.h new file mode 100644 index 0000000..895c8e2 --- /dev/null +++ b/drivers/gpu/drm/amd/include/asic_reg/si/si_reg.h @@ -0,0 +1,105 @@ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ +#ifndef __SI_REG_H__ +#define __SI_REG_H__ + +/* SI */ +#define SI_DC_GPIO_HPD_MASK 0x196c +#define SI_DC_GPIO_HPD_A 0x196d +#define SI_DC_GPIO_HPD_EN 0x196e +#define SI_DC_GPIO_HPD_Y 0x196f + +#define SI_GRPH_CONTROL 0x1a01 +# define SI_GRPH_DEPTH(x) (((x) & 0x3) << 0) +# define SI_GRPH_DEPTH_8BPP 0 +# define SI_GRPH_DEPTH_16BPP 1 +# define SI_GRPH_DEPTH_32BPP 2 +# define SI_GRPH_NUM_BANKS(x) (((x) & 0x3) << 2) +# define SI_ADDR_SURF_2_BANK 0 +# define SI_ADDR_SURF_4_BANK 1 +# define SI_ADDR_SURF_8_BANK 2 +# define SI_ADDR_SURF_16_BANK 3 +# define SI_GRPH_Z(x) (((x) & 0x3) << 4) +# define SI_GRPH_BANK_WIDTH(x) (((x) & 0x3) << 6) +# define SI_ADDR_SURF_BANK_WIDTH_1 0 +# define SI_ADDR_SURF_BANK_WIDTH_2 1 +# define SI_ADDR_SURF_BANK_WIDTH_4 2 +# define SI_ADDR_SURF_BANK_WIDTH_8 3 +# define SI_GRPH_FORMAT(x) (((x) & 0x7) << 8) +/* 8 BPP */ +# define SI_GRPH_FORMAT_INDEXED 0 +/* 16 BPP */ +# define SI_GRPH_FORMAT_ARGB1555 0 +# define SI_GRPH_FORMAT_ARGB565 1 +# define SI_GRPH_FORMAT_ARGB4444 2 +# define SI_GRPH_FORMAT_AI88 3 +# define SI_GRPH_FORMAT_MONO16 4 +# define SI_GRPH_FORMAT_BGRA5551 5 +/* 32 BPP */ +# define SI_GRPH_FORMAT_ARGB8888 0 +# define SI_GRPH_FORMAT_ARGB2101010 1 +# define SI_GRPH_FORMAT_32BPP_DIG 2 +# define SI_GRPH_FORMAT_8B_ARGB2101010 3 +# define SI_GRPH_FORMAT_BGRA1010102 4 +# define SI_GRPH_FORMAT_8B_BGRA1010102 5 +# define SI_GRPH_FORMAT_RGB111110 6 +# define SI_GRPH_FORMAT_BGR101111 7 +# define SI_GRPH_BANK_HEIGHT(x) (((x) & 0x3) << 11) +# define SI_ADDR_SURF_BANK_HEIGHT_1 0 +# define SI_ADDR_SURF_BANK_HEIGHT_2 1 +# define SI_ADDR_SURF_BANK_HEIGHT_4 2 +# define SI_ADDR_SURF_BANK_HEIGHT_8 3 +# define SI_GRPH_TILE_SPLIT(x) (((x) & 0x7) << 13) +# define SI_ADDR_SURF_TILE_SPLIT_64B 0 +# define SI_ADDR_SURF_TILE_SPLIT_128B 1 +# define SI_ADDR_SURF_TILE_SPLIT_256B 2 +# define SI_ADDR_SURF_TILE_SPLIT_512B 3 +# define SI_ADDR_SURF_TILE_SPLIT_1KB 4 +# define SI_ADDR_SURF_TILE_SPLIT_2KB 5 +# define SI_ADDR_SURF_TILE_SPLIT_4KB 6 +# define SI_GRPH_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 18) +# define SI_ADDR_SURF_MACRO_TILE_ASPECT_1 0 +# define SI_ADDR_SURF_MACRO_TILE_ASPECT_2 1 +# define SI_ADDR_SURF_MACRO_TILE_ASPECT_4 2 +# define SI_ADDR_SURF_MACRO_TILE_ASPECT_8 3 +# define SI_GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20) +# define SI_GRPH_ARRAY_LINEAR_GENERAL 0 +# define SI_GRPH_ARRAY_LINEAR_ALIGNED 1 +# define SI_GRPH_ARRAY_1D_TILED_THIN1 2 +# define SI_GRPH_ARRAY_2D_TILED_THIN1 4 +# define SI_GRPH_PIPE_CONFIG(x) (((x) & 0x1f) << 24) +# define SI_ADDR_SURF_P2 0 +# define SI_ADDR_SURF_P4_8x16 4 +# define SI_ADDR_SURF_P4_16x16 5 +# define SI_ADDR_SURF_P4_16x32 6 +# define SI_ADDR_SURF_P4_32x32 7 +# define SI_ADDR_SURF_P8_16x16_8x16 8 +# define SI_ADDR_SURF_P8_16x32_8x16 9 +# define SI_ADDR_SURF_P8_32x32_8x16 10 +# define SI_ADDR_SURF_P8_16x32_16x16 11 +# define SI_ADDR_SURF_P8_32x32_16x16 12 +# define SI_ADDR_SURF_P8_32x32_16x32 13 +# define SI_ADDR_SURF_P8_32x64_32x32 14 + +#endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/si/sid.h b/drivers/gpu/drm/amd/include/asic_reg/si/sid.h new file mode 100644 index 0000000..15358cd --- /dev/null +++ b/drivers/gpu/drm/amd/include/asic_reg/si/sid.h @@ -0,0 +1,2408 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ +#ifndef SI_H +#define SI_H + +#define TAHITI_RB_BITMAP_WIDTH_PER_SH 2 + +#define TAHITI_GB_ADDR_CONFIG_GOLDEN 0x12011003 +#define VERDE_GB_ADDR_CONFIG_GOLDEN 0x12010002 +#define HAINAN_GB_ADDR_CONFIG_GOLDEN 0x02010001 + +#define SI_MAX_SH_GPRS 256 +#define SI_MAX_TEMP_GPRS 16 +#define SI_MAX_SH_THREADS 256 +#define SI_MAX_SH_STACK_ENTRIES 4096 +#define SI_MAX_FRC_EOV_CNT 16384 +#define SI_MAX_BACKENDS 8 +#define SI_MAX_BACKENDS_MASK 0xFF +#define SI_MAX_BACKENDS_PER_SE_MASK 0x0F +#define SI_MAX_SIMDS 12 +#define SI_MAX_SIMDS_MASK 0x0FFF +#define SI_MAX_SIMDS_PER_SE_MASK 0x00FF +#define SI_MAX_PIPES 8 +#define SI_MAX_PIPES_MASK 0xFF +#define SI_MAX_PIPES_PER_SIMD_MASK 0x3F +#define SI_MAX_LDS_NUM 0xFFFF +#define SI_MAX_TCC 16 +#define SI_MAX_TCC_MASK 0xFFFF + +#define AMDGPU_NUM_OF_VMIDS 8 + +/* SMC IND accessor regs */ +#define SMC_IND_INDEX_0 0x80 +#define SMC_IND_DATA_0 0x81 + +#define SMC_IND_ACCESS_CNTL 0x8A +# define AUTO_INCREMENT_IND_0 (1 << 0) +#define SMC_MESSAGE_0 0x8B +#define SMC_RESP_0 0x8C + +/* CG IND registers are accessed via SMC indirect space + SMC_CG_IND_START */ +#define SMC_CG_IND_START 0xc0030000 +#define SMC_CG_IND_END 0xc0040000 + +#define CG_CGTT_LOCAL_0 0x400 +#define CG_CGTT_LOCAL_1 0x401 + +/* SMC IND registers */ +#define SMC_SYSCON_RESET_CNTL 0x80000000 +# define RST_REG (1 << 0) +#define SMC_SYSCON_CLOCK_CNTL_0 0x80000004 +# define CK_DISABLE (1 << 0) +# define CKEN (1 << 24) + +#define VGA_HDP_CONTROL 0xCA +#define VGA_MEMORY_DISABLE (1 << 4) + +#define DCCG_DISP_SLOW_SELECT_REG 0x13F +#define DCCG_DISP1_SLOW_SELECT(x) ((x) << 0) +#define DCCG_DISP1_SLOW_SELECT_MASK (7 << 0) +#define DCCG_DISP1_SLOW_SELECT_SHIFT 0 +#define DCCG_DISP2_SLOW_SELECT(x) ((x) << 4) +#define DCCG_DISP2_SLOW_SELECT_MASK (7 << 4) +#define DCCG_DISP2_SLOW_SELECT_SHIFT 4 + +#define CG_SPLL_FUNC_CNTL 0x180 +#define SPLL_RESET (1 << 0) +#define SPLL_SLEEP (1 << 1) +#define SPLL_BYPASS_EN (1 << 3) +#define SPLL_REF_DIV(x) ((x) << 4) +#define SPLL_REF_DIV_MASK (0x3f << 4) +#define SPLL_PDIV_A(x) ((x) << 20) +#define SPLL_PDIV_A_MASK (0x7f << 20) +#define SPLL_PDIV_A_SHIFT 20 +#define CG_SPLL_FUNC_CNTL_2 0x181 +#define SCLK_MUX_SEL(x) ((x) << 0) +#define SCLK_MUX_SEL_MASK (0x1ff << 0) +#define SPLL_CTLREQ_CHG (1 << 23) +#define SCLK_MUX_UPDATE (1 << 26) +#define CG_SPLL_FUNC_CNTL_3 0x182 +#define SPLL_FB_DIV(x) ((x) << 0) +#define SPLL_FB_DIV_MASK (0x3ffffff << 0) +#define SPLL_FB_DIV_SHIFT 0 +#define SPLL_DITHEN (1 << 28) +#define CG_SPLL_FUNC_CNTL_4 0x183 + +#define SPLL_STATUS 0x185 +#define SPLL_CHG_STATUS (1 << 1) +#define SPLL_CNTL_MODE 0x186 +#define SPLL_SW_DIR_CONTROL (1 << 0) +# define SPLL_REFCLK_SEL(x) ((x) << 26) +# define SPLL_REFCLK_SEL_MASK (3 << 26) + +#define CG_SPLL_SPREAD_SPECTRUM 0x188 +#define SSEN (1 << 0) +#define CLK_S(x) ((x) << 4) +#define CLK_S_MASK (0xfff << 4) +#define CLK_S_SHIFT 4 +#define CG_SPLL_SPREAD_SPECTRUM_2 0x189 +#define CLK_V(x) ((x) << 0) +#define CLK_V_MASK (0x3ffffff << 0) +#define CLK_V_SHIFT 0 + +#define CG_SPLL_AUTOSCALE_CNTL 0x18b +# define AUTOSCALE_ON_SS_CLEAR (1 << 9) + +/* discrete uvd clocks */ +#define CG_UPLL_FUNC_CNTL 0x18d +# define UPLL_RESET_MASK 0x00000001 +# define UPLL_SLEEP_MASK 0x00000002 +# define UPLL_BYPASS_EN_MASK 0x00000004 +# define UPLL_CTLREQ_MASK 0x00000008 +# define UPLL_VCO_MODE_MASK 0x00000600 +# define UPLL_REF_DIV_MASK 0x003F0000 +# define UPLL_CTLACK_MASK 0x40000000 +# define UPLL_CTLACK2_MASK 0x80000000 +#define CG_UPLL_FUNC_CNTL_2 0x18e +# define UPLL_PDIV_A(x) ((x) << 0) +# define UPLL_PDIV_A_MASK 0x0000007F +# define UPLL_PDIV_B(x) ((x) << 8) +# define UPLL_PDIV_B_MASK 0x00007F00 +# define VCLK_SRC_SEL(x) ((x) << 20) +# define VCLK_SRC_SEL_MASK 0x01F00000 +# define DCLK_SRC_SEL(x) ((x) << 25) +# define DCLK_SRC_SEL_MASK 0x3E000000 +#define CG_UPLL_FUNC_CNTL_3 0x18f +# define UPLL_FB_DIV(x) ((x) << 0) +# define UPLL_FB_DIV_MASK 0x01FFFFFF +#define CG_UPLL_FUNC_CNTL_4 0x191 +# define UPLL_SPARE_ISPARE9 0x00020000 +#define CG_UPLL_FUNC_CNTL_5 0x192 +# define RESET_ANTI_MUX_MASK 0x00000200 +#define CG_UPLL_SPREAD_SPECTRUM 0x194 +# define SSEN_MASK 0x00000001 + +#define MPLL_BYPASSCLK_SEL 0x197 +# define MPLL_CLKOUT_SEL(x) ((x) << 8) +# define MPLL_CLKOUT_SEL_MASK 0xFF00 + +#define CG_CLKPIN_CNTL 0x198 +# define XTALIN_DIVIDE (1 << 1) +# define BCLK_AS_XCLK (1 << 2) +#define CG_CLKPIN_CNTL_2 0x199 +# define FORCE_BIF_REFCLK_EN (1 << 3) +# define MUX_TCLK_TO_XCLK (1 << 8) + +#define THM_CLK_CNTL 0x19b +# define CMON_CLK_SEL(x) ((x) << 0) +# define CMON_CLK_SEL_MASK 0xFF +# define TMON_CLK_SEL(x) ((x) << 8) +# define TMON_CLK_SEL_MASK 0xFF00 +#define MISC_CLK_CNTL 0x19c +# define DEEP_SLEEP_CLK_SEL(x) ((x) << 0) +# define DEEP_SLEEP_CLK_SEL_MASK 0xFF +# define ZCLK_SEL(x) ((x) << 8) +# define ZCLK_SEL_MASK 0xFF00 + +#define CG_THERMAL_CTRL 0x1c0 +#define DPM_EVENT_SRC(x) ((x) << 0) +#define DPM_EVENT_SRC_MASK (7 << 0) +#define DIG_THERM_DPM(x) ((x) << 14) +#define DIG_THERM_DPM_MASK 0x003FC000 +#define DIG_THERM_DPM_SHIFT 14 +#define CG_THERMAL_STATUS 0x1c1 +#define FDO_PWM_DUTY(x) ((x) << 9) +#define FDO_PWM_DUTY_MASK (0xff << 9) +#define FDO_PWM_DUTY_SHIFT 9 +#define CG_THERMAL_INT 0x1c2 +#define DIG_THERM_INTH(x) ((x) << 8) +#define DIG_THERM_INTH_MASK 0x0000FF00 +#define DIG_THERM_INTH_SHIFT 8 +#define DIG_THERM_INTL(x) ((x) << 16) +#define DIG_THERM_INTL_MASK 0x00FF0000 +#define DIG_THERM_INTL_SHIFT 16 +#define THERM_INT_MASK_HIGH (1 << 24) +#define THERM_INT_MASK_LOW (1 << 25) + +#define CG_MULT_THERMAL_CTRL 0x1c4 +#define TEMP_SEL(x) ((x) << 20) +#define TEMP_SEL_MASK (0xff << 20) +#define TEMP_SEL_SHIFT 20 +#define CG_MULT_THERMAL_STATUS 0x1c5 +#define ASIC_MAX_TEMP(x) ((x) << 0) +#define ASIC_MAX_TEMP_MASK 0x000001ff +#define ASIC_MAX_TEMP_SHIFT 0 +#define CTF_TEMP(x) ((x) << 9) +#define CTF_TEMP_MASK 0x0003fe00 +#define CTF_TEMP_SHIFT 9 + +#define CG_FDO_CTRL0 0x1d5 +#define FDO_STATIC_DUTY(x) ((x) << 0) +#define FDO_STATIC_DUTY_MASK 0x000000FF +#define FDO_STATIC_DUTY_SHIFT 0 +#define CG_FDO_CTRL1 0x1d6 +#define FMAX_DUTY100(x) ((x) << 0) +#define FMAX_DUTY100_MASK 0x000000FF +#define FMAX_DUTY100_SHIFT 0 +#define CG_FDO_CTRL2 0x1d7 +#define TMIN(x) ((x) << 0) +#define TMIN_MASK 0x000000FF +#define TMIN_SHIFT 0 +#define FDO_PWM_MODE(x) ((x) << 11) +#define FDO_PWM_MODE_MASK (7 << 11) +#define FDO_PWM_MODE_SHIFT 11 +#define TACH_PWM_RESP_RATE(x) ((x) << 25) +#define TACH_PWM_RESP_RATE_MASK (0x7f << 25) +#define TACH_PWM_RESP_RATE_SHIFT 25 + +#define CG_TACH_CTRL 0x1dc +# define EDGE_PER_REV(x) ((x) << 0) +# define EDGE_PER_REV_MASK (0x7 << 0) +# define EDGE_PER_REV_SHIFT 0 +# define TARGET_PERIOD(x) ((x) << 3) +# define TARGET_PERIOD_MASK 0xfffffff8 +# define TARGET_PERIOD_SHIFT 3 +#define CG_TACH_STATUS 0x1dd +# define TACH_PERIOD(x) ((x) << 0) +# define TACH_PERIOD_MASK 0xffffffff +# define TACH_PERIOD_SHIFT 0 + +#define GENERAL_PWRMGT 0x1e0 +# define GLOBAL_PWRMGT_EN (1 << 0) +# define STATIC_PM_EN (1 << 1) +# define THERMAL_PROTECTION_DIS (1 << 2) +# define THERMAL_PROTECTION_TYPE (1 << 3) +# define SW_SMIO_INDEX(x) ((x) << 6) +# define SW_SMIO_INDEX_MASK (1 << 6) +# define SW_SMIO_INDEX_SHIFT 6 +# define VOLT_PWRMGT_EN (1 << 10) +# define DYN_SPREAD_SPECTRUM_EN (1 << 23) +#define CG_TPC 0x1e1 +#define SCLK_PWRMGT_CNTL 0x1e2 +# define SCLK_PWRMGT_OFF (1 << 0) +# define SCLK_LOW_D1 (1 << 1) +# define FIR_RESET (1 << 4) +# define FIR_FORCE_TREND_SEL (1 << 5) +# define FIR_TREND_MODE (1 << 6) +# define DYN_GFX_CLK_OFF_EN (1 << 7) +# define GFX_CLK_FORCE_ON (1 << 8) +# define GFX_CLK_REQUEST_OFF (1 << 9) +# define GFX_CLK_FORCE_OFF (1 << 10) +# define GFX_CLK_OFF_ACPI_D1 (1 << 11) +# define GFX_CLK_OFF_ACPI_D2 (1 << 12) +# define GFX_CLK_OFF_ACPI_D3 (1 << 13) +# define DYN_LIGHT_SLEEP_EN (1 << 14) + +#define TARGET_AND_CURRENT_PROFILE_INDEX 0x1e6 +# define CURRENT_STATE_INDEX_MASK (0xf << 4) +# define CURRENT_STATE_INDEX_SHIFT 4 + +#define CG_FTV 0x1ef + +#define CG_FFCT_0 0x1f0 +# define UTC_0(x) ((x) << 0) +# define UTC_0_MASK (0x3ff << 0) +# define DTC_0(x) ((x) << 10) +# define DTC_0_MASK (0x3ff << 10) + +#define CG_BSP 0x1ff +# define BSP(x) ((x) << 0) +# define BSP_MASK (0xffff << 0) +# define BSU(x) ((x) << 16) +# define BSU_MASK (0xf << 16) +#define CG_AT 0x200 +# define CG_R(x) ((x) << 0) +# define CG_R_MASK (0xffff << 0) +# define CG_L(x) ((x) << 16) +# define CG_L_MASK (0xffff << 16) + +#define CG_GIT 0x201 +# define CG_GICST(x) ((x) << 0) +# define CG_GICST_MASK (0xffff << 0) +# define CG_GIPOT(x) ((x) << 16) +# define CG_GIPOT_MASK (0xffff << 16) + +#define CG_SSP 0x203 +# define SST(x) ((x) << 0) +# define SST_MASK (0xffff << 0) +# define SSTU(x) ((x) << 16) +# define SSTU_MASK (0xf << 16) + +#define CG_DISPLAY_GAP_CNTL 0x20a +# define DISP1_GAP(x) ((x) << 0) +# define DISP1_GAP_MASK (3 << 0) +# define DISP2_GAP(x) ((x) << 2) +# define DISP2_GAP_MASK (3 << 2) +# define VBI_TIMER_COUNT(x) ((x) << 4) +# define VBI_TIMER_COUNT_MASK (0x3fff << 4) +# define VBI_TIMER_UNIT(x) ((x) << 20) +# define VBI_TIMER_UNIT_MASK (7 << 20) +# define DISP1_GAP_MCHG(x) ((x) << 24) +# define DISP1_GAP_MCHG_MASK (3 << 24) +# define DISP2_GAP_MCHG(x) ((x) << 26) +# define DISP2_GAP_MCHG_MASK (3 << 26) + +#define CG_ULV_CONTROL 0x21e +#define CG_ULV_PARAMETER 0x21f + +#define SMC_SCRATCH0 0x221 + +#define CG_CAC_CTRL 0x22e +# define CAC_WINDOW(x) ((x) << 0) +# define CAC_WINDOW_MASK 0x00ffffff + +#define DMIF_ADDR_CONFIG 0x2F5 + +#define DMIF_ADDR_CALC 0x300 + +#define PIPE0_DMIF_BUFFER_CONTROL 0x0328 +# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) +# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) + +#define SRBM_STATUS 0x394 +#define GRBM_RQ_PENDING (1 << 5) +#define VMC_BUSY (1 << 8) +#define MCB_BUSY (1 << 9) +#define MCB_NON_DISPLAY_BUSY (1 << 10) +#define MCC_BUSY (1 << 11) +#define MCD_BUSY (1 << 12) +#define SEM_BUSY (1 << 14) +#define IH_BUSY (1 << 17) + +#define SRBM_SOFT_RESET 0x398 +#define SOFT_RESET_BIF (1 << 1) +#define SOFT_RESET_DC (1 << 5) +#define SOFT_RESET_DMA1 (1 << 6) +#define SOFT_RESET_GRBM (1 << 8) +#define SOFT_RESET_HDP (1 << 9) +#define SOFT_RESET_IH (1 << 10) +#define SOFT_RESET_MC (1 << 11) +#define SOFT_RESET_ROM (1 << 14) +#define SOFT_RESET_SEM (1 << 15) +#define SOFT_RESET_VMC (1 << 17) +#define SOFT_RESET_DMA (1 << 20) +#define SOFT_RESET_TST (1 << 21) +#define SOFT_RESET_REGBB (1 << 22) +#define SOFT_RESET_ORB (1 << 23) + +#define CC_SYS_RB_BACKEND_DISABLE 0x3A0 +#define GC_USER_SYS_RB_BACKEND_DISABLE 0x3A1 + +#define SRBM_READ_ERROR 0x3A6 +#define SRBM_INT_CNTL 0x3A8 +#define SRBM_INT_ACK 0x3AA + +#define SRBM_STATUS2 0x3B1 +#define DMA_BUSY (1 << 5) +#define DMA1_BUSY (1 << 6) + +#define VM_L2_CNTL 0x500 +#define ENABLE_L2_CACHE (1 << 0) +#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) +#define L2_CACHE_PTE_ENDIAN_SWAP_MODE(x) ((x) << 2) +#define L2_CACHE_PDE_ENDIAN_SWAP_MODE(x) ((x) << 4) +#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) +#define ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE (1 << 10) +#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 15) +#define CONTEXT1_IDENTITY_ACCESS_MODE(x) (((x) & 3) << 19) +#define VM_L2_CNTL2 0x501 +#define INVALIDATE_ALL_L1_TLBS (1 << 0) +#define INVALIDATE_L2_CACHE (1 << 1) +#define INVALIDATE_CACHE_MODE(x) ((x) << 26) +#define INVALIDATE_PTE_AND_PDE_CACHES 0 +#define INVALIDATE_ONLY_PTE_CACHES 1 +#define INVALIDATE_ONLY_PDE_CACHES 2 +#define VM_L2_CNTL3 0x502 +#define BANK_SELECT(x) ((x) << 0) +#define L2_CACHE_UPDATE_MODE(x) ((x) << 6) +#define L2_CACHE_BIGK_FRAGMENT_SIZE(x) ((x) << 15) +#define L2_CACHE_BIGK_ASSOCIATIVITY (1 << 20) +#define VM_L2_STATUS 0x503 +#define L2_BUSY (1 << 0) +#define VM_CONTEXT0_CNTL 0x504 +#define ENABLE_CONTEXT (1 << 0) +#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) +#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) +#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) +#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) +#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) +#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) +#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) +#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) +#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) +#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) +#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) +#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) +#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) +#define PAGE_TABLE_BLOCK_SIZE(x) (((x) & 0xF) << 24) +#define VM_CONTEXT1_CNTL 0x505 +#define VM_CONTEXT0_CNTL2 0x50C +#define VM_CONTEXT1_CNTL2 0x50D +#define VM_CONTEXT8_PAGE_TABLE_BASE_ADDR 0x50E +#define VM_CONTEXT9_PAGE_TABLE_BASE_ADDR 0x50F +#define VM_CONTEXT10_PAGE_TABLE_BASE_ADDR 0x510 +#define VM_CONTEXT11_PAGE_TABLE_BASE_ADDR 0x511 +#define VM_CONTEXT12_PAGE_TABLE_BASE_ADDR 0x512 +#define VM_CONTEXT13_PAGE_TABLE_BASE_ADDR 0x513 +#define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR 0x514 +#define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR 0x515 + +#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x53f +#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x537 +#define PROTECTIONS_MASK (0xf << 0) +#define PROTECTIONS_SHIFT 0 + /* bit 0: range + * bit 1: pde0 + * bit 2: valid + * bit 3: read + * bit 4: write + */ +#define MEMORY_CLIENT_ID_MASK (0xff << 12) +#define MEMORY_CLIENT_ID_SHIFT 12 +#define MEMORY_CLIENT_RW_MASK (1 << 24) +#define MEMORY_CLIENT_RW_SHIFT 24 +#define FAULT_VMID_MASK (0xf << 25) +#define FAULT_VMID_SHIFT 25 + +#define VM_INVALIDATE_REQUEST 0x51E +#define VM_INVALIDATE_RESPONSE 0x51F + +#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x546 +#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x547 + +#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x54F +#define VM_CONTEXT1_PAGE_TABLE_BASE_ADDR 0x550 +#define VM_CONTEXT2_PAGE_TABLE_BASE_ADDR 0x551 +#define VM_CONTEXT3_PAGE_TABLE_BASE_ADDR 0x552 +#define VM_CONTEXT4_PAGE_TABLE_BASE_ADDR 0x553 +#define VM_CONTEXT5_PAGE_TABLE_BASE_ADDR 0x554 +#define VM_CONTEXT6_PAGE_TABLE_BASE_ADDR 0x555 +#define VM_CONTEXT7_PAGE_TABLE_BASE_ADDR 0x556 +#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x557 +#define VM_CONTEXT1_PAGE_TABLE_START_ADDR 0x558 + +#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x55F +#define VM_CONTEXT1_PAGE_TABLE_END_ADDR 0x560 + +#define VM_L2_CG 0x570 +#define MC_CG_ENABLE (1 << 18) +#define MC_LS_ENABLE (1 << 19) + +#define MC_SHARED_CHMAP 0x801 +#define NOOFCHAN_SHIFT 12 +#define NOOFCHAN_MASK 0x0000f000 +#define MC_SHARED_CHREMAP 0x802 + +#define MC_VM_FB_LOCATION 0x809 +#define MC_VM_AGP_TOP 0x80A +#define MC_VM_AGP_BOT 0x80B +#define MC_VM_AGP_BASE 0x80C +#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x80D +#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x80E +#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x80F + +#define MC_VM_MX_L1_TLB_CNTL 0x819 +#define ENABLE_L1_TLB (1 << 0) +#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) +#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) +#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) +#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) +#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) +#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) +#define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6) + +#define MC_SHARED_BLACKOUT_CNTL 0x82B + +#define MC_HUB_MISC_HUB_CG 0x82E +#define MC_HUB_MISC_VM_CG 0x82F + +#define MC_HUB_MISC_SIP_CG 0x830 + +#define MC_XPB_CLK_GAT 0x91E + +#define MC_CITF_MISC_RD_CG 0x992 +#define MC_CITF_MISC_WR_CG 0x993 +#define MC_CITF_MISC_VM_CG 0x994 + +#define MC_ARB_RAMCFG 0x9D8 +#define NOOFBANK_SHIFT 0 +#define NOOFBANK_MASK 0x00000003 +#define NOOFRANK_SHIFT 2 +#define NOOFRANK_MASK 0x00000004 +#define NOOFROWS_SHIFT 3 +#define NOOFROWS_MASK 0x00000038 +#define NOOFCOLS_SHIFT 6 +#define NOOFCOLS_MASK 0x000000C0 +#define CHANSIZE_SHIFT 8 +#define CHANSIZE_MASK 0x00000100 +#define CHANSIZE_OVERRIDE (1 << 11) +#define NOOFGROUPS_SHIFT 12 +#define NOOFGROUPS_MASK 0x00001000 + +#define MC_ARB_DRAM_TIMING 0x9DD +#define MC_ARB_DRAM_TIMING2 0x9DE + +#define MC_ARB_BURST_TIME 0xA02 +#define STATE0(x) ((x) << 0) +#define STATE0_MASK (0x1f << 0) +#define STATE0_SHIFT 0 +#define STATE1(x) ((x) << 5) +#define STATE1_MASK (0x1f << 5) +#define STATE1_SHIFT 5 +#define STATE2(x) ((x) << 10) +#define STATE2_MASK (0x1f << 10) +#define STATE2_SHIFT 10 +#define STATE3(x) ((x) << 15) +#define STATE3_MASK (0x1f << 15) +#define STATE3_SHIFT 15 + +#define MC_SEQ_TRAIN_WAKEUP_CNTL 0xA3A +#define TRAIN_DONE_D0 (1 << 30) +#define TRAIN_DONE_D1 (1 << 31) + +#define MC_SEQ_SUP_CNTL 0xA32 +#define RUN_MASK (1 << 0) +#define MC_SEQ_SUP_PGM 0xA33 +#define MC_PMG_AUTO_CMD 0xA34 + +#define MC_IO_PAD_CNTL_D0 0xA74 +#define MEM_FALL_OUT_CMD (1 << 8) + +#define MC_SEQ_RAS_TIMING 0xA28 +#define MC_SEQ_CAS_TIMING 0xA29 +#define MC_SEQ_MISC_TIMING 0xA2A +#define MC_SEQ_MISC_TIMING2 0xA2B +#define MC_SEQ_PMG_TIMING 0xA2C +#define MC_SEQ_RD_CTL_D0 0xA2D +#define MC_SEQ_RD_CTL_D1 0xA2E +#define MC_SEQ_WR_CTL_D0 0xA2F +#define MC_SEQ_WR_CTL_D1 0xA30 + +#define MC_SEQ_MISC0 0xA80 +#define MC_SEQ_MISC0_VEN_ID_SHIFT 8 +#define MC_SEQ_MISC0_VEN_ID_MASK 0x00000f00 +#define MC_SEQ_MISC0_VEN_ID_VALUE 3 +#define MC_SEQ_MISC0_REV_ID_SHIFT 12 +#define MC_SEQ_MISC0_REV_ID_MASK 0x0000f000 +#define MC_SEQ_MISC0_REV_ID_VALUE 1 +#define MC_SEQ_MISC0_GDDR5_SHIFT 28 +#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000 +#define MC_SEQ_MISC0_GDDR5_VALUE 5 +#define MC_SEQ_MISC1 0xA81 +#define MC_SEQ_RESERVE_M 0xA82 +#define MC_PMG_CMD_EMRS 0xA83 + +#define MC_SEQ_IO_DEBUG_INDEX 0xA91 +#define MC_SEQ_IO_DEBUG_DATA 0xA92 + +#define MC_SEQ_MISC5 0xA95 +#define MC_SEQ_MISC6 0xA96 + +#define MC_SEQ_MISC7 0xA99 + +#define MC_SEQ_RAS_TIMING_LP 0xA9B +#define MC_SEQ_CAS_TIMING_LP 0xA9C +#define MC_SEQ_MISC_TIMING_LP 0xA9D +#define MC_SEQ_MISC_TIMING2_LP 0xA9E +#define MC_SEQ_WR_CTL_D0_LP 0xA9F +#define MC_SEQ_WR_CTL_D1_LP 0xAA0 +#define MC_SEQ_PMG_CMD_EMRS_LP 0xAA1 +#define MC_SEQ_PMG_CMD_MRS_LP 0xAA2 + +#define MC_PMG_CMD_MRS 0xAAB + +#define MC_SEQ_RD_CTL_D0_LP 0xAC7 +#define MC_SEQ_RD_CTL_D1_LP 0xAC8 + +#define MC_PMG_CMD_MRS1 0xAD1 +#define MC_SEQ_PMG_CMD_MRS1_LP 0xAD2 +#define MC_SEQ_PMG_TIMING_LP 0xAD3 + +#define MC_SEQ_WR_CTL_2 0xAD5 +#define MC_SEQ_WR_CTL_2_LP 0xAD6 +#define MC_PMG_CMD_MRS2 0xAD7 +#define MC_SEQ_PMG_CMD_MRS2_LP 0xAD8 + +#define MCLK_PWRMGT_CNTL 0xAE8 +# define DLL_SPEED(x) ((x) << 0) +# define DLL_SPEED_MASK (0x1f << 0) +# define DLL_READY (1 << 6) +# define MC_INT_CNTL (1 << 7) +# define MRDCK0_PDNB (1 << 8) +# define MRDCK1_PDNB (1 << 9) +# define MRDCK0_RESET (1 << 16) +# define MRDCK1_RESET (1 << 17) +# define DLL_READY_READ (1 << 24) +#define DLL_CNTL 0xAE9 +# define MRDCK0_BYPASS (1 << 24) +# define MRDCK1_BYPASS (1 << 25) + +#define MPLL_CNTL_MODE 0xAEC +# define MPLL_MCLK_SEL (1 << 11) +#define MPLL_FUNC_CNTL 0xAED +#define BWCTRL(x) ((x) << 20) +#define BWCTRL_MASK (0xff << 20) +#define MPLL_FUNC_CNTL_1 0xAEE +#define VCO_MODE(x) ((x) << 0) +#define VCO_MODE_MASK (3 << 0) +#define CLKFRAC(x) ((x) << 4) +#define CLKFRAC_MASK (0xfff << 4) +#define CLKF(x) ((x) << 16) +#define CLKF_MASK (0xfff << 16) +#define MPLL_FUNC_CNTL_2 0xAEF +#define MPLL_AD_FUNC_CNTL 0xAF0 +#define YCLK_POST_DIV(x) ((x) << 0) +#define YCLK_POST_DIV_MASK (7 << 0) +#define MPLL_DQ_FUNC_CNTL 0xAF1 +#define YCLK_SEL(x) ((x) << 4) +#define YCLK_SEL_MASK (1 << 4) + +#define MPLL_SS1 0xAF3 +#define CLKV(x) ((x) << 0) +#define CLKV_MASK (0x3ffffff << 0) +#define MPLL_SS2 0xAF4 +#define CLKS(x) ((x) << 0) +#define CLKS_MASK (0xfff << 0) + +#define HDP_HOST_PATH_CNTL 0xB00 +#define CLOCK_GATING_DIS (1 << 23) +#define HDP_NONSURFACE_BASE 0xB01 +#define HDP_NONSURFACE_INFO 0xB02 +#define HDP_NONSURFACE_SIZE 0xB03 + +#define HDP_ADDR_CONFIG 0xBD2 +#define HDP_MISC_CNTL 0xBD3 +#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) +#define HDP_MEM_POWER_LS 0xBD4 +#define HDP_LS_ENABLE (1 << 0) + +#define ATC_MISC_CG 0xCD4 + +#define IH_RB_CNTL 0xF80 +# define IH_RB_ENABLE (1 << 0) +# define IH_IB_SIZE(x) ((x) << 1) /* log2 */ +# define IH_RB_FULL_DRAIN_ENABLE (1 << 6) +# define IH_WPTR_WRITEBACK_ENABLE (1 << 8) +# define IH_WPTR_WRITEBACK_TIMER(x) ((x) << 9) /* log2 */ +# define IH_WPTR_OVERFLOW_ENABLE (1 << 16) +# define IH_WPTR_OVERFLOW_CLEAR (1 << 31) +#define IH_RB_BASE 0xF81 +#define IH_RB_RPTR 0xF82 +#define IH_RB_WPTR 0xF83 +# define RB_OVERFLOW (1 << 0) +# define WPTR_OFFSET_MASK 0x3fffc +#define IH_RB_WPTR_ADDR_HI 0xF84 +#define IH_RB_WPTR_ADDR_LO 0xF85 +#define IH_CNTL 0xF86 +# define ENABLE_INTR (1 << 0) +# define IH_MC_SWAP(x) ((x) << 1) +# define IH_MC_SWAP_NONE 0 +# define IH_MC_SWAP_16BIT 1 +# define IH_MC_SWAP_32BIT 2 +# define IH_MC_SWAP_64BIT 3 +# define RPTR_REARM (1 << 4) +# define MC_WRREQ_CREDIT(x) ((x) << 15) +# define MC_WR_CLEAN_CNT(x) ((x) << 20) +# define MC_VMID(x) ((x) << 25) + +#define CONFIG_MEMSIZE 0x150A + +#define INTERRUPT_CNTL 0x151A +# define IH_DUMMY_RD_OVERRIDE (1 << 0) +# define IH_DUMMY_RD_EN (1 << 1) +# define IH_REQ_NONSNOOP_EN (1 << 3) +# define GEN_IH_INT_EN (1 << 8) +#define INTERRUPT_CNTL2 0x151B + +#define HDP_MEM_COHERENCY_FLUSH_CNTL 0x1520 + +#define BIF_FB_EN 0x1524 +#define FB_READ_EN (1 << 0) +#define FB_WRITE_EN (1 << 1) + +#define HDP_REG_COHERENCY_FLUSH_CNTL 0x1528 + +/* DCE6 ELD audio interface */ +#define AZ_F0_CODEC_ENDPOINT_INDEX 0x1780 +# define AZ_ENDPOINT_REG_INDEX(x) (((x) & 0xff) << 0) +# define AZ_ENDPOINT_REG_WRITE_EN (1 << 8) +#define AZ_F0_CODEC_ENDPOINT_DATA 0x1781 + +#define AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER 0x25 +#define SPEAKER_ALLOCATION(x) (((x) & 0x7f) << 0) +#define SPEAKER_ALLOCATION_MASK (0x7f << 0) +#define SPEAKER_ALLOCATION_SHIFT 0 +#define HDMI_CONNECTION (1 << 16) +#define DP_CONNECTION (1 << 17) + +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 0x28 /* LPCM */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1 0x29 /* AC3 */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2 0x2A /* MPEG1 */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3 0x2B /* MP3 */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4 0x2C /* MPEG2 */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5 0x2D /* AAC */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6 0x2E /* DTS */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7 0x2F /* ATRAC */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8 0x30 /* one bit audio - leave at 0 (default) */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9 0x31 /* Dolby Digital */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10 0x32 /* DTS-HD */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11 0x33 /* MAT-MLP */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12 0x34 /* DTS */ +#define AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13 0x35 /* WMA Pro */ +# define MAX_CHANNELS(x) (((x) & 0x7) << 0) +/* max channels minus one. 7 = 8 channels */ +# define SUPPORTED_FREQUENCIES(x) (((x) & 0xff) << 8) +# define DESCRIPTOR_BYTE_2(x) (((x) & 0xff) << 16) +# define SUPPORTED_FREQUENCIES_STEREO(x) (((x) & 0xff) << 24) /* LPCM only */ +/* SUPPORTED_FREQUENCIES, SUPPORTED_FREQUENCIES_STEREO + * bit0 = 32 kHz + * bit1 = 44.1 kHz + * bit2 = 48 kHz + * bit3 = 88.2 kHz + * bit4 = 96 kHz + * bit5 = 176.4 kHz + * bit6 = 192 kHz + */ + +#define AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC 0x37 +# define VIDEO_LIPSYNC(x) (((x) & 0xff) << 0) +# define AUDIO_LIPSYNC(x) (((x) & 0xff) << 8) +/* VIDEO_LIPSYNC, AUDIO_LIPSYNC + * 0 = invalid + * x = legal delay value + * 255 = sync not supported + */ +#define AZ_F0_CODEC_PIN_CONTROL_RESPONSE_HBR 0x38 +# define HBR_CAPABLE (1 << 0) /* enabled by default */ + +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO0 0x3a +# define MANUFACTURER_ID(x) (((x) & 0xffff) << 0) +# define PRODUCT_ID(x) (((x) & 0xffff) << 16) +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO1 0x3b +# define SINK_DESCRIPTION_LEN(x) (((x) & 0xff) << 0) +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO2 0x3c +# define PORT_ID0(x) (((x) & 0xffffffff) << 0) +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO3 0x3d +# define PORT_ID1(x) (((x) & 0xffffffff) << 0) +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO4 0x3e +# define DESCRIPTION0(x) (((x) & 0xff) << 0) +# define DESCRIPTION1(x) (((x) & 0xff) << 8) +# define DESCRIPTION2(x) (((x) & 0xff) << 16) +# define DESCRIPTION3(x) (((x) & 0xff) << 24) +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO5 0x3f +# define DESCRIPTION4(x) (((x) & 0xff) << 0) +# define DESCRIPTION5(x) (((x) & 0xff) << 8) +# define DESCRIPTION6(x) (((x) & 0xff) << 16) +# define DESCRIPTION7(x) (((x) & 0xff) << 24) +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO6 0x40 +# define DESCRIPTION8(x) (((x) & 0xff) << 0) +# define DESCRIPTION9(x) (((x) & 0xff) << 8) +# define DESCRIPTION10(x) (((x) & 0xff) << 16) +# define DESCRIPTION11(x) (((x) & 0xff) << 24) +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO7 0x41 +# define DESCRIPTION12(x) (((x) & 0xff) << 0) +# define DESCRIPTION13(x) (((x) & 0xff) << 8) +# define DESCRIPTION14(x) (((x) & 0xff) << 16) +# define DESCRIPTION15(x) (((x) & 0xff) << 24) +#define AZ_F0_CODEC_PIN_CONTROL_SINK_INFO8 0x42 +# define DESCRIPTION16(x) (((x) & 0xff) << 0) +# define DESCRIPTION17(x) (((x) & 0xff) << 8) + +#define AZ_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL 0x54 +# define AUDIO_ENABLED (1 << 31) + +#define AZ_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 0x56 +#define PORT_CONNECTIVITY_MASK (3 << 30) +#define PORT_CONNECTIVITY_SHIFT 30 + +#define DC_LB_MEMORY_SPLIT 0x1AC3 +#define DC_LB_MEMORY_CONFIG(x) ((x) << 20) + +#define PRIORITY_A_CNT 0x1AC6 +#define PRIORITY_MARK_MASK 0x7fff +#define PRIORITY_OFF (1 << 16) +#define PRIORITY_ALWAYS_ON (1 << 20) +#define PRIORITY_B_CNT 0x1AC7 + +#define DPG_PIPE_ARBITRATION_CONTROL3 0x1B32 +# define LATENCY_WATERMARK_MASK(x) ((x) << 16) +#define DPG_PIPE_LATENCY_CONTROL 0x1B33 +# define LATENCY_LOW_WATERMARK(x) ((x) << 0) +# define LATENCY_HIGH_WATERMARK(x) ((x) << 16) + +/* 0x6bb8, 0x77b8, 0x103b8, 0x10fb8, 0x11bb8, 0x127b8 */ +#define VLINE_STATUS 0x1AEE +# define VLINE_OCCURRED (1 << 0) +# define VLINE_ACK (1 << 4) +# define VLINE_STAT (1 << 12) +# define VLINE_INTERRUPT (1 << 16) +# define VLINE_INTERRUPT_TYPE (1 << 17) +/* 0x6bbc, 0x77bc, 0x103bc, 0x10fbc, 0x11bbc, 0x127bc */ +#define VBLANK_STATUS 0x1AEF +# define VBLANK_OCCURRED (1 << 0) +# define VBLANK_ACK (1 << 4) +# define VBLANK_STAT (1 << 12) +# define VBLANK_INTERRUPT (1 << 16) +# define VBLANK_INTERRUPT_TYPE (1 << 17) + +/* 0x6b40, 0x7740, 0x10340, 0x10f40, 0x11b40, 0x12740 */ +#define INT_MASK 0x1AD0 +# define VBLANK_INT_MASK (1 << 0) +# define VLINE_INT_MASK (1 << 4) + +#define DISP_INTERRUPT_STATUS 0x183D +# define LB_D1_VLINE_INTERRUPT (1 << 2) +# define LB_D1_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD1_INTERRUPT (1 << 17) +# define DC_HPD1_RX_INTERRUPT (1 << 18) +# define DACA_AUTODETECT_INTERRUPT (1 << 22) +# define DACB_AUTODETECT_INTERRUPT (1 << 23) +# define DC_I2C_SW_DONE_INTERRUPT (1 << 24) +# define DC_I2C_HW_DONE_INTERRUPT (1 << 25) +#define DISP_INTERRUPT_STATUS_CONTINUE 0x183E +# define LB_D2_VLINE_INTERRUPT (1 << 2) +# define LB_D2_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD2_INTERRUPT (1 << 17) +# define DC_HPD2_RX_INTERRUPT (1 << 18) +# define DISP_TIMER_INTERRUPT (1 << 24) +#define DISP_INTERRUPT_STATUS_CONTINUE2 0x183F +# define LB_D3_VLINE_INTERRUPT (1 << 2) +# define LB_D3_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD3_INTERRUPT (1 << 17) +# define DC_HPD3_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE3 0x1840 +# define LB_D4_VLINE_INTERRUPT (1 << 2) +# define LB_D4_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD4_INTERRUPT (1 << 17) +# define DC_HPD4_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE4 0x1853 +# define LB_D5_VLINE_INTERRUPT (1 << 2) +# define LB_D5_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD5_INTERRUPT (1 << 17) +# define DC_HPD5_RX_INTERRUPT (1 << 18) +#define DISP_INTERRUPT_STATUS_CONTINUE5 0x1854 +# define LB_D6_VLINE_INTERRUPT (1 << 2) +# define LB_D6_VBLANK_INTERRUPT (1 << 3) +# define DC_HPD6_INTERRUPT (1 << 17) +# define DC_HPD6_RX_INTERRUPT (1 << 18) + +/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */ +#define GRPH_INT_STATUS 0x1A16 +# define GRPH_PFLIP_INT_OCCURRED (1 << 0) +# define GRPH_PFLIP_INT_CLEAR (1 << 8) +/* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */ +#define GRPH_INT_CONTROL 0x1A17 +# define GRPH_PFLIP_INT_MASK (1 << 0) +# define GRPH_PFLIP_INT_TYPE (1 << 8) + +#define DAC_AUTODETECT_INT_CONTROL 0x19F2 + +#define DC_HPD1_INT_STATUS 0x1807 +#define DC_HPD2_INT_STATUS 0x180A +#define DC_HPD3_INT_STATUS 0x180D +#define DC_HPD4_INT_STATUS 0x1810 +#define DC_HPD5_INT_STATUS 0x1813 +#define DC_HPD6_INT_STATUS 0x1816 +# define DC_HPDx_INT_STATUS (1 << 0) +# define DC_HPDx_SENSE (1 << 1) +# define DC_HPDx_RX_INT_STATUS (1 << 8) + +#define DC_HPD1_INT_CONTROL 0x1808 +#define DC_HPD2_INT_CONTROL 0x180B +#define DC_HPD3_INT_CONTROL 0x180E +#define DC_HPD4_INT_CONTROL 0x1811 +#define DC_HPD5_INT_CONTROL 0x1814 +#define DC_HPD6_INT_CONTROL 0x1817 +# define DC_HPDx_INT_ACK (1 << 0) +# define DC_HPDx_INT_POLARITY (1 << 8) +# define DC_HPDx_INT_EN (1 << 16) +# define DC_HPDx_RX_INT_ACK (1 << 20) +# define DC_HPDx_RX_INT_EN (1 << 24) + +#define DC_HPD1_CONTROL 0x1809 +#define DC_HPD2_CONTROL 0x180C +#define DC_HPD3_CONTROL 0x180F +#define DC_HPD4_CONTROL 0x1812 +#define DC_HPD5_CONTROL 0x1815 +#define DC_HPD6_CONTROL 0x1818 +# define DC_HPDx_CONNECTION_TIMER(x) ((x) << 0) +# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16) +# define DC_HPDx_EN (1 << 28) + +#define DPG_PIPE_STUTTER_CONTROL 0x1B35 +# define STUTTER_ENABLE (1 << 0) + +/* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */ +#define CRTC_STATUS_FRAME_COUNT 0x1BA6 + +/* Audio clocks */ +#define DCCG_AUDIO_DTO_SOURCE 0x05ac +# define DCCG_AUDIO_DTO0_SOURCE_SEL(x) ((x) << 0) /* crtc0 - crtc5 */ +# define DCCG_AUDIO_DTO_SEL (1 << 4) /* 0=dto0 1=dto1 */ + +#define DCCG_AUDIO_DTO0_PHASE 0x05b0 +#define DCCG_AUDIO_DTO0_MODULE 0x05b4 +#define DCCG_AUDIO_DTO1_PHASE 0x05c0 +#define DCCG_AUDIO_DTO1_MODULE 0x05c4 + +#define AFMT_AUDIO_SRC_CONTROL 0x1c4f +#define AFMT_AUDIO_SRC_SELECT(x) (((x) & 7) << 0) +/* AFMT_AUDIO_SRC_SELECT + * 0 = stream0 + * 1 = stream1 + * 2 = stream2 + * 3 = stream3 + * 4 = stream4 + * 5 = stream5 + */ + +#define GRBM_CNTL 0x2000 +#define GRBM_READ_TIMEOUT(x) ((x) << 0) + +#define GRBM_STATUS2 0x2002 +#define RLC_RQ_PENDING (1 << 0) +#define RLC_BUSY (1 << 8) +#define TC_BUSY (1 << 9) + +#define GRBM_STATUS 0x2004 +#define CMDFIFO_AVAIL_MASK 0x0000000F +#define RING2_RQ_PENDING (1 << 4) +#define SRBM_RQ_PENDING (1 << 5) +#define RING1_RQ_PENDING (1 << 6) +#define CF_RQ_PENDING (1 << 7) +#define PF_RQ_PENDING (1 << 8) +#define GDS_DMA_RQ_PENDING (1 << 9) +#define GRBM_EE_BUSY (1 << 10) +#define DB_CLEAN (1 << 12) +#define CB_CLEAN (1 << 13) +#define TA_BUSY (1 << 14) +#define GDS_BUSY (1 << 15) +#define VGT_BUSY (1 << 17) +#define IA_BUSY_NO_DMA (1 << 18) +#define IA_BUSY (1 << 19) +#define SX_BUSY (1 << 20) +#define SPI_BUSY (1 << 22) +#define BCI_BUSY (1 << 23) +#define SC_BUSY (1 << 24) +#define PA_BUSY (1 << 25) +#define DB_BUSY (1 << 26) +#define CP_COHERENCY_BUSY (1 << 28) +#define CP_BUSY (1 << 29) +#define CB_BUSY (1 << 30) +#define GUI_ACTIVE (1 << 31) +#define GRBM_STATUS_SE0 0x2005 +#define GRBM_STATUS_SE1 0x2006 +#define SE_DB_CLEAN (1 << 1) +#define SE_CB_CLEAN (1 << 2) +#define SE_BCI_BUSY (1 << 22) +#define SE_VGT_BUSY (1 << 23) +#define SE_PA_BUSY (1 << 24) +#define SE_TA_BUSY (1 << 25) +#define SE_SX_BUSY (1 << 26) +#define SE_SPI_BUSY (1 << 27) +#define SE_SC_BUSY (1 << 29) +#define SE_DB_BUSY (1 << 30) +#define SE_CB_BUSY (1 << 31) + +#define GRBM_SOFT_RESET 0x2008 +#define SOFT_RESET_CP (1 << 0) +#define SOFT_RESET_CB (1 << 1) +#define SOFT_RESET_RLC (1 << 2) +#define SOFT_RESET_DB (1 << 3) +#define SOFT_RESET_GDS (1 << 4) +#define SOFT_RESET_PA (1 << 5) +#define SOFT_RESET_SC (1 << 6) +#define SOFT_RESET_BCI (1 << 7) +#define SOFT_RESET_SPI (1 << 8) +#define SOFT_RESET_SX (1 << 10) +#define SOFT_RESET_TC (1 << 11) +#define SOFT_RESET_TA (1 << 12) +#define SOFT_RESET_VGT (1 << 14) +#define SOFT_RESET_IA (1 << 15) + +#define GRBM_GFX_INDEX 0x200B +#define INSTANCE_INDEX(x) ((x) << 0) +#define SH_INDEX(x) ((x) << 8) +#define SE_INDEX(x) ((x) << 16) +#define SH_BROADCAST_WRITES (1 << 29) +#define INSTANCE_BROADCAST_WRITES (1 << 30) +#define SE_BROADCAST_WRITES (1 << 31) + +#define GRBM_INT_CNTL 0x2018 +# define RDERR_INT_ENABLE (1 << 0) +# define GUI_IDLE_INT_ENABLE (1 << 19) + +#define CP_STRMOUT_CNTL 0x213F +#define SCRATCH_REG0 0x2140 +#define SCRATCH_REG1 0x2141 +#define SCRATCH_REG2 0x2142 +#define SCRATCH_REG3 0x2143 +#define SCRATCH_REG4 0x2144 +#define SCRATCH_REG5 0x2145 +#define SCRATCH_REG6 0x2146 +#define SCRATCH_REG7 0x2147 + +#define SCRATCH_UMSK 0x2150 +#define SCRATCH_ADDR 0x2151 + +#define CP_SEM_WAIT_TIMER 0x216F + +#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x2172 + +#define CP_ME_CNTL 0x21B6 +#define CP_CE_HALT (1 << 24) +#define CP_PFP_HALT (1 << 26) +#define CP_ME_HALT (1 << 28) + +#define CP_COHER_CNTL2 0x217A + +#define CP_RB2_RPTR 0x21BE +#define CP_RB1_RPTR 0x21BF +#define CP_RB0_RPTR 0x21C0 +#define CP_RB_WPTR_DELAY 0x21C1 + +#define CP_QUEUE_THRESHOLDS 0x21D8 +#define ROQ_IB1_START(x) ((x) << 0) +#define ROQ_IB2_START(x) ((x) << 8) +#define CP_MEQ_THRESHOLDS 0x21D9 +#define MEQ1_START(x) ((x) << 0) +#define MEQ2_START(x) ((x) << 8) + +#define CP_PERFMON_CNTL 0x21FF + +#define VGT_VTX_VECT_EJECT_REG 0x222C + +#define VGT_CACHE_INVALIDATION 0x2231 +#define CACHE_INVALIDATION(x) ((x) << 0) +#define VC_ONLY 0 +#define TC_ONLY 1 +#define VC_AND_TC 2 +#define AUTO_INVLD_EN(x) ((x) << 6) +#define NO_AUTO 0 +#define ES_AUTO 1 +#define GS_AUTO 2 +#define ES_AND_GS_AUTO 3 +#define VGT_ESGS_RING_SIZE 0x2232 +#define VGT_GSVS_RING_SIZE 0x2233 + +#define VGT_GS_VERTEX_REUSE 0x2235 + +#define VGT_PRIMITIVE_TYPE 0x2256 +#define VGT_INDEX_TYPE 0x2257 + +#define VGT_NUM_INDICES 0x225C +#define VGT_NUM_INSTANCES 0x225D + +#define VGT_TF_RING_SIZE 0x2262 + +#define VGT_HS_OFFCHIP_PARAM 0x226C + +#define VGT_TF_MEMORY_BASE 0x226E + +#define CC_GC_SHADER_ARRAY_CONFIG 0x226F +#define INACTIVE_CUS_MASK 0xFFFF0000 +#define INACTIVE_CUS_SHIFT 16 +#define GC_USER_SHADER_ARRAY_CONFIG 0x2270 + +#define PA_CL_ENHANCE 0x2285 +#define CLIP_VTX_REORDER_ENA (1 << 0) +#define NUM_CLIP_SEQ(x) ((x) << 1) + +#define PA_SU_LINE_STIPPLE_VALUE 0x2298 + +#define PA_SC_LINE_STIPPLE_STATE 0x22C4 + +#define PA_SC_FORCE_EOV_MAX_CNTS 0x22C9 +#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) +#define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) + +#define PA_SC_FIFO_SIZE 0x22F3 +#define SC_FRONTEND_PRIM_FIFO_SIZE(x) ((x) << 0) +#define SC_BACKEND_PRIM_FIFO_SIZE(x) ((x) << 6) +#define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 15) +#define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 23) + +#define PA_SC_ENHANCE 0x22FC + +#define SQ_CONFIG 0x2300 + +#define SQC_CACHES 0x2302 + +#define SQ_POWER_THROTTLE 0x2396 +#define MIN_POWER(x) ((x) << 0) +#define MIN_POWER_MASK (0x3fff << 0) +#define MIN_POWER_SHIFT 0 +#define MAX_POWER(x) ((x) << 16) +#define MAX_POWER_MASK (0x3fff << 16) +#define MAX_POWER_SHIFT 0 +#define SQ_POWER_THROTTLE2 0x2397 +#define MAX_POWER_DELTA(x) ((x) << 0) +#define MAX_POWER_DELTA_MASK (0x3fff << 0) +#define MAX_POWER_DELTA_SHIFT 0 +#define STI_SIZE(x) ((x) << 16) +#define STI_SIZE_MASK (0x3ff << 16) +#define STI_SIZE_SHIFT 16 +#define LTI_RATIO(x) ((x) << 27) +#define LTI_RATIO_MASK (0xf << 27) +#define LTI_RATIO_SHIFT 27 + +#define SX_DEBUG_1 0x2418 + +#define SPI_STATIC_THREAD_MGMT_1 0x2438 +#define SPI_STATIC_THREAD_MGMT_2 0x2439 +#define SPI_STATIC_THREAD_MGMT_3 0x243A +#define SPI_PS_MAX_WAVE_ID 0x243B + +#define SPI_CONFIG_CNTL 0x2440 + +#define SPI_CONFIG_CNTL_1 0x244F +#define VTX_DONE_DELAY(x) ((x) << 0) +#define INTERP_ONE_PRIM_PER_ROW (1 << 4) + +#define CGTS_TCC_DISABLE 0x2452 +#define CGTS_USER_TCC_DISABLE 0x2453 +#define TCC_DISABLE_MASK 0xFFFF0000 +#define TCC_DISABLE_SHIFT 16 +#define CGTS_SM_CTRL_REG 0x2454 +#define OVERRIDE (1 << 21) +#define LS_OVERRIDE (1 << 22) + +#define SPI_LB_CU_MASK 0x24D5 + +#define TA_CNTL_AUX 0x2542 + +#define CC_RB_BACKEND_DISABLE 0x263D +#define BACKEND_DISABLE(x) ((x) << 16) +#define GB_ADDR_CONFIG 0x263E +#define NUM_PIPES(x) ((x) << 0) +#define NUM_PIPES_MASK 0x00000007 +#define NUM_PIPES_SHIFT 0 +#define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) +#define PIPE_INTERLEAVE_SIZE_MASK 0x00000070 +#define PIPE_INTERLEAVE_SIZE_SHIFT 4 +#define NUM_SHADER_ENGINES(x) ((x) << 12) +#define NUM_SHADER_ENGINES_MASK 0x00003000 +#define NUM_SHADER_ENGINES_SHIFT 12 +#define SHADER_ENGINE_TILE_SIZE(x) ((x) << 16) +#define SHADER_ENGINE_TILE_SIZE_MASK 0x00070000 +#define SHADER_ENGINE_TILE_SIZE_SHIFT 16 +#define NUM_GPUS(x) ((x) << 20) +#define NUM_GPUS_MASK 0x00700000 +#define NUM_GPUS_SHIFT 20 +#define MULTI_GPU_TILE_SIZE(x) ((x) << 24) +#define MULTI_GPU_TILE_SIZE_MASK 0x03000000 +#define MULTI_GPU_TILE_SIZE_SHIFT 24 +#define ROW_SIZE(x) ((x) << 28) +#define ROW_SIZE_MASK 0x30000000 +#define ROW_SIZE_SHIFT 28 + +#define GB_TILE_MODE0 0x2644 +# define MICRO_TILE_MODE(x) ((x) << 0) +# define ADDR_SURF_DISPLAY_MICRO_TILING 0 +# define ADDR_SURF_THIN_MICRO_TILING 1 +# define ADDR_SURF_DEPTH_MICRO_TILING 2 +# define ARRAY_MODE(x) ((x) << 2) +# define ARRAY_LINEAR_GENERAL 0 +# define ARRAY_LINEAR_ALIGNED 1 +# define ARRAY_1D_TILED_THIN1 2 +# define ARRAY_2D_TILED_THIN1 4 +# define PIPE_CONFIG(x) ((x) << 6) +# define ADDR_SURF_P2 0 +# define ADDR_SURF_P4_8x16 4 +# define ADDR_SURF_P4_16x16 5 +# define ADDR_SURF_P4_16x32 6 +# define ADDR_SURF_P4_32x32 7 +# define ADDR_SURF_P8_16x16_8x16 8 +# define ADDR_SURF_P8_16x32_8x16 9 +# define ADDR_SURF_P8_32x32_8x16 10 +# define ADDR_SURF_P8_16x32_16x16 11 +# define ADDR_SURF_P8_32x32_16x16 12 +# define ADDR_SURF_P8_32x32_16x32 13 +# define ADDR_SURF_P8_32x64_32x32 14 +# define TILE_SPLIT(x) ((x) << 11) +# define ADDR_SURF_TILE_SPLIT_64B 0 +# define ADDR_SURF_TILE_SPLIT_128B 1 +# define ADDR_SURF_TILE_SPLIT_256B 2 +# define ADDR_SURF_TILE_SPLIT_512B 3 +# define ADDR_SURF_TILE_SPLIT_1KB 4 +# define ADDR_SURF_TILE_SPLIT_2KB 5 +# define ADDR_SURF_TILE_SPLIT_4KB 6 +# define BANK_WIDTH(x) ((x) << 14) +# define ADDR_SURF_BANK_WIDTH_1 0 +# define ADDR_SURF_BANK_WIDTH_2 1 +# define ADDR_SURF_BANK_WIDTH_4 2 +# define ADDR_SURF_BANK_WIDTH_8 3 +# define BANK_HEIGHT(x) ((x) << 16) +# define ADDR_SURF_BANK_HEIGHT_1 0 +# define ADDR_SURF_BANK_HEIGHT_2 1 +# define ADDR_SURF_BANK_HEIGHT_4 2 +# define ADDR_SURF_BANK_HEIGHT_8 3 +# define MACRO_TILE_ASPECT(x) ((x) << 18) +# define ADDR_SURF_MACRO_ASPECT_1 0 +# define ADDR_SURF_MACRO_ASPECT_2 1 +# define ADDR_SURF_MACRO_ASPECT_4 2 +# define ADDR_SURF_MACRO_ASPECT_8 3 +# define NUM_BANKS(x) ((x) << 20) +# define ADDR_SURF_2_BANK 0 +# define ADDR_SURF_4_BANK 1 +# define ADDR_SURF_8_BANK 2 +# define ADDR_SURF_16_BANK 3 + +#define CB_PERFCOUNTER0_SELECT0 0x2688 +#define CB_PERFCOUNTER0_SELECT1 0x2689 +#define CB_PERFCOUNTER1_SELECT0 0x268A +#define CB_PERFCOUNTER1_SELECT1 0x268B +#define CB_PERFCOUNTER2_SELECT0 0x268C +#define CB_PERFCOUNTER2_SELECT1 0x268D +#define CB_PERFCOUNTER3_SELECT0 0x268E +#define CB_PERFCOUNTER3_SELECT1 0x268F + +#define CB_CGTT_SCLK_CTRL 0x2698 + +#define GC_USER_RB_BACKEND_DISABLE 0x26DF +#define BACKEND_DISABLE_MASK 0x00FF0000 +#define BACKEND_DISABLE_SHIFT 16 + +#define TCP_CHAN_STEER_LO 0x2B03 +#define TCP_CHAN_STEER_HI 0x2B94 + +#define CP_RB0_BASE 0x3040 +#define CP_RB0_CNTL 0x3041 +#define RB_BUFSZ(x) ((x) << 0) +#define RB_BLKSZ(x) ((x) << 8) +#define BUF_SWAP_32BIT (2 << 16) +#define RB_NO_UPDATE (1 << 27) +#define RB_RPTR_WR_ENA (1 << 31) + +#define CP_RB0_RPTR_ADDR 0x3043 +#define CP_RB0_RPTR_ADDR_HI 0x3044 +#define CP_RB0_WPTR 0x3045 + +#define CP_PFP_UCODE_ADDR 0x3054 +#define CP_PFP_UCODE_DATA 0x3055 +#define CP_ME_RAM_RADDR 0x3056 +#define CP_ME_RAM_WADDR 0x3057 +#define CP_ME_RAM_DATA 0x3058 + +#define CP_CE_UCODE_ADDR 0x305A +#define CP_CE_UCODE_DATA 0x305B + +#define CP_RB1_BASE 0x3060 +#define CP_RB1_CNTL 0x3061 +#define CP_RB1_RPTR_ADDR 0x3062 +#define CP_RB1_RPTR_ADDR_HI 0x3063 +#define CP_RB1_WPTR 0x3064 +#define CP_RB2_BASE 0x3065 +#define CP_RB2_CNTL 0x3066 +#define CP_RB2_RPTR_ADDR 0x3067 +#define CP_RB2_RPTR_ADDR_HI 0x3068 +#define CP_RB2_WPTR 0x3069 +#define CP_INT_CNTL_RING0 0x306A +#define CP_INT_CNTL_RING1 0x306B +#define CP_INT_CNTL_RING2 0x306C +# define CNTX_BUSY_INT_ENABLE (1 << 19) +# define CNTX_EMPTY_INT_ENABLE (1 << 20) +# define WAIT_MEM_SEM_INT_ENABLE (1 << 21) +# define TIME_STAMP_INT_ENABLE (1 << 26) +# define CP_RINGID2_INT_ENABLE (1 << 29) +# define CP_RINGID1_INT_ENABLE (1 << 30) +# define CP_RINGID0_INT_ENABLE (1 << 31) +#define CP_INT_STATUS_RING0 0x306D +#define CP_INT_STATUS_RING1 0x306E +#define CP_INT_STATUS_RING2 0x306F +# define WAIT_MEM_SEM_INT_STAT (1 << 21) +# define TIME_STAMP_INT_STAT (1 << 26) +# define CP_RINGID2_INT_STAT (1 << 29) +# define CP_RINGID1_INT_STAT (1 << 30) +# define CP_RINGID0_INT_STAT (1 << 31) + +#define CP_MEM_SLP_CNTL 0x3079 +# define CP_MEM_LS_EN (1 << 0) + +#define CP_DEBUG 0x307F + +#define RLC_CNTL 0x30C0 +# define RLC_ENABLE (1 << 0) +#define RLC_RL_BASE 0x30C1 +#define RLC_RL_SIZE 0x30C2 +#define RLC_LB_CNTL 0x30C3 +# define LOAD_BALANCE_ENABLE (1 << 0) +#define RLC_SAVE_AND_RESTORE_BASE 0x30C4 +#define RLC_LB_CNTR_MAX 0x30C5 +#define RLC_LB_CNTR_INIT 0x30C6 + +#define RLC_CLEAR_STATE_RESTORE_BASE 0x30C8 + +#define RLC_UCODE_ADDR 0x30CB +#define RLC_UCODE_DATA 0x30CC + +#define RLC_GPU_CLOCK_COUNT_LSB 0x30CE +#define RLC_GPU_CLOCK_COUNT_MSB 0x30CF +#define RLC_CAPTURE_GPU_CLOCK_COUNT 0x30D0 +#define RLC_MC_CNTL 0x30D1 +#define RLC_UCODE_CNTL 0x30D2 +#define RLC_STAT 0x30D3 +# define RLC_BUSY_STATUS (1 << 0) +# define GFX_POWER_STATUS (1 << 1) +# define GFX_CLOCK_STATUS (1 << 2) +# define GFX_LS_STATUS (1 << 3) + +#define RLC_PG_CNTL 0x30D7 +# define GFX_PG_ENABLE (1 << 0) +# define GFX_PG_SRC (1 << 1) + +#define RLC_CGTT_MGCG_OVERRIDE 0x3100 +#define RLC_CGCG_CGLS_CTRL 0x3101 +# define CGCG_EN (1 << 0) +# define CGLS_EN (1 << 1) + +#define RLC_TTOP_D 0x3105 +# define RLC_PUD(x) ((x) << 0) +# define RLC_PUD_MASK (0xff << 0) +# define RLC_PDD(x) ((x) << 8) +# define RLC_PDD_MASK (0xff << 8) +# define RLC_TTPD(x) ((x) << 16) +# define RLC_TTPD_MASK (0xff << 16) +# define RLC_MSD(x) ((x) << 24) +# define RLC_MSD_MASK (0xff << 24) + +#define RLC_LB_INIT_CU_MASK 0x3107 + +#define RLC_PG_AO_CU_MASK 0x310B +#define RLC_MAX_PG_CU 0x310C +# define MAX_PU_CU(x) ((x) << 0) +# define MAX_PU_CU_MASK (0xff << 0) +#define RLC_AUTO_PG_CTRL 0x310C +# define AUTO_PG_EN (1 << 0) +# define GRBM_REG_SGIT(x) ((x) << 3) +# define GRBM_REG_SGIT_MASK (0xffff << 3) +# define PG_AFTER_GRBM_REG_ST(x) ((x) << 19) +# define PG_AFTER_GRBM_REG_ST_MASK (0x1fff << 19) + +#define RLC_SERDES_WR_MASTER_MASK_0 0x3115 +#define RLC_SERDES_WR_MASTER_MASK_1 0x3116 +#define RLC_SERDES_WR_CTRL 0x3117 + +#define RLC_SERDES_MASTER_BUSY_0 0x3119 +#define RLC_SERDES_MASTER_BUSY_1 0x311A + +#define RLC_GCPM_GENERAL_3 0x311E + +#define DB_RENDER_CONTROL 0xA000 + +#define DB_DEPTH_INFO 0xA00F + +#define PA_SC_RASTER_CONFIG 0xA0D4 +# define RASTER_CONFIG_RB_MAP_0 0 +# define RASTER_CONFIG_RB_MAP_1 1 +# define RASTER_CONFIG_RB_MAP_2 2 +# define RASTER_CONFIG_RB_MAP_3 3 + +#define VGT_EVENT_INITIATOR 0xA2A4 +# define SAMPLE_STREAMOUTSTATS1 (1 << 0) +# define SAMPLE_STREAMOUTSTATS2 (2 << 0) +# define SAMPLE_STREAMOUTSTATS3 (3 << 0) +# define CACHE_FLUSH_TS (4 << 0) +# define CACHE_FLUSH (6 << 0) +# define CS_PARTIAL_FLUSH (7 << 0) +# define VGT_STREAMOUT_RESET (10 << 0) +# define END_OF_PIPE_INCR_DE (11 << 0) +# define END_OF_PIPE_IB_END (12 << 0) +# define RST_PIX_CNT (13 << 0) +# define VS_PARTIAL_FLUSH (15 << 0) +# define PS_PARTIAL_FLUSH (16 << 0) +# define CACHE_FLUSH_AND_INV_TS_EVENT (20 << 0) +# define ZPASS_DONE (21 << 0) +# define CACHE_FLUSH_AND_INV_EVENT (22 << 0) +# define PERFCOUNTER_START (23 << 0) +# define PERFCOUNTER_STOP (24 << 0) +# define PIPELINESTAT_START (25 << 0) +# define PIPELINESTAT_STOP (26 << 0) +# define PERFCOUNTER_SAMPLE (27 << 0) +# define SAMPLE_PIPELINESTAT (30 << 0) +# define SAMPLE_STREAMOUTSTATS (32 << 0) +# define RESET_VTX_CNT (33 << 0) +# define VGT_FLUSH (36 << 0) +# define BOTTOM_OF_PIPE_TS (40 << 0) +# define DB_CACHE_FLUSH_AND_INV (42 << 0) +# define FLUSH_AND_INV_DB_DATA_TS (43 << 0) +# define FLUSH_AND_INV_DB_META (44 << 0) +# define FLUSH_AND_INV_CB_DATA_TS (45 << 0) +# define FLUSH_AND_INV_CB_META (46 << 0) +# define CS_DONE (47 << 0) +# define PS_DONE (48 << 0) +# define FLUSH_AND_INV_CB_PIXEL_DATA (49 << 0) +# define THREAD_TRACE_START (51 << 0) +# define THREAD_TRACE_STOP (52 << 0) +# define THREAD_TRACE_FLUSH (54 << 0) +# define THREAD_TRACE_FINISH (55 << 0) + +/* PIF PHY0 registers idx/data 0x8/0xc */ +#define PB0_PIF_CNTL 0x10 +# define LS2_EXIT_TIME(x) ((x) << 17) +# define LS2_EXIT_TIME_MASK (0x7 << 17) +# define LS2_EXIT_TIME_SHIFT 17 +#define PB0_PIF_PAIRING 0x11 +# define MULTI_PIF (1 << 25) +#define PB0_PIF_PWRDOWN_0 0x12 +# define PLL_POWER_STATE_IN_TXS2_0(x) ((x) << 7) +# define PLL_POWER_STATE_IN_TXS2_0_MASK (0x7 << 7) +# define PLL_POWER_STATE_IN_TXS2_0_SHIFT 7 +# define PLL_POWER_STATE_IN_OFF_0(x) ((x) << 10) +# define PLL_POWER_STATE_IN_OFF_0_MASK (0x7 << 10) +# define PLL_POWER_STATE_IN_OFF_0_SHIFT 10 +# define PLL_RAMP_UP_TIME_0(x) ((x) << 24) +# define PLL_RAMP_UP_TIME_0_MASK (0x7 << 24) +# define PLL_RAMP_UP_TIME_0_SHIFT 24 +#define PB0_PIF_PWRDOWN_1 0x13 +# define PLL_POWER_STATE_IN_TXS2_1(x) ((x) << 7) +# define PLL_POWER_STATE_IN_TXS2_1_MASK (0x7 << 7) +# define PLL_POWER_STATE_IN_TXS2_1_SHIFT 7 +# define PLL_POWER_STATE_IN_OFF_1(x) ((x) << 10) +# define PLL_POWER_STATE_IN_OFF_1_MASK (0x7 << 10) +# define PLL_POWER_STATE_IN_OFF_1_SHIFT 10 +# define PLL_RAMP_UP_TIME_1(x) ((x) << 24) +# define PLL_RAMP_UP_TIME_1_MASK (0x7 << 24) +# define PLL_RAMP_UP_TIME_1_SHIFT 24 + +#define PB0_PIF_PWRDOWN_2 0x17 +# define PLL_POWER_STATE_IN_TXS2_2(x) ((x) << 7) +# define PLL_POWER_STATE_IN_TXS2_2_MASK (0x7 << 7) +# define PLL_POWER_STATE_IN_TXS2_2_SHIFT 7 +# define PLL_POWER_STATE_IN_OFF_2(x) ((x) << 10) +# define PLL_POWER_STATE_IN_OFF_2_MASK (0x7 << 10) +# define PLL_POWER_STATE_IN_OFF_2_SHIFT 10 +# define PLL_RAMP_UP_TIME_2(x) ((x) << 24) +# define PLL_RAMP_UP_TIME_2_MASK (0x7 << 24) +# define PLL_RAMP_UP_TIME_2_SHIFT 24 +#define PB0_PIF_PWRDOWN_3 0x18 +# define PLL_POWER_STATE_IN_TXS2_3(x) ((x) << 7) +# define PLL_POWER_STATE_IN_TXS2_3_MASK (0x7 << 7) +# define PLL_POWER_STATE_IN_TXS2_3_SHIFT 7 +# define PLL_POWER_STATE_IN_OFF_3(x) ((x) << 10) +# define PLL_POWER_STATE_IN_OFF_3_MASK (0x7 << 10) +# define PLL_POWER_STATE_IN_OFF_3_SHIFT 10 +# define PLL_RAMP_UP_TIME_3(x) ((x) << 24) +# define PLL_RAMP_UP_TIME_3_MASK (0x7 << 24) +# define PLL_RAMP_UP_TIME_3_SHIFT 24 +/* PIF PHY1 registers idx/data 0x10/0x14 */ +#define PB1_PIF_CNTL 0x10 +#define PB1_PIF_PAIRING 0x11 +#define PB1_PIF_PWRDOWN_0 0x12 +#define PB1_PIF_PWRDOWN_1 0x13 + +#define PB1_PIF_PWRDOWN_2 0x17 +#define PB1_PIF_PWRDOWN_3 0x18 +/* PCIE registers idx/data 0x30/0x34 */ +#define PCIE_CNTL2 0x1c /* PCIE */ +# define SLV_MEM_LS_EN (1 << 16) +# define SLV_MEM_AGGRESSIVE_LS_EN (1 << 17) +# define MST_MEM_LS_EN (1 << 18) +# define REPLAY_MEM_LS_EN (1 << 19) +#define PCIE_LC_STATUS1 0x28 /* PCIE */ +# define LC_REVERSE_RCVR (1 << 0) +# define LC_REVERSE_XMIT (1 << 1) +# define LC_OPERATING_LINK_WIDTH_MASK (0x7 << 2) +# define LC_OPERATING_LINK_WIDTH_SHIFT 2 +# define LC_DETECTED_LINK_WIDTH_MASK (0x7 << 5) +# define LC_DETECTED_LINK_WIDTH_SHIFT 5 + +#define PCIE_P_CNTL 0x40 /* PCIE */ +# define P_IGNORE_EDB_ERR (1 << 6) + +/* PCIE PORT registers idx/data 0x38/0x3c */ +#define PCIE_LC_CNTL 0xa0 +# define LC_L0S_INACTIVITY(x) ((x) << 8) +# define LC_L0S_INACTIVITY_MASK (0xf << 8) +# define LC_L0S_INACTIVITY_SHIFT 8 +# define LC_L1_INACTIVITY(x) ((x) << 12) +# define LC_L1_INACTIVITY_MASK (0xf << 12) +# define LC_L1_INACTIVITY_SHIFT 12 +# define LC_PMI_TO_L1_DIS (1 << 16) +# define LC_ASPM_TO_L1_DIS (1 << 24) +#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */ +# define LC_LINK_WIDTH_SHIFT 0 +# define LC_LINK_WIDTH_MASK 0x7 +# define LC_LINK_WIDTH_X0 0 +# define LC_LINK_WIDTH_X1 1 +# define LC_LINK_WIDTH_X2 2 +# define LC_LINK_WIDTH_X4 3 +# define LC_LINK_WIDTH_X8 4 +# define LC_LINK_WIDTH_X16 6 +# define LC_LINK_WIDTH_RD_SHIFT 4 +# define LC_LINK_WIDTH_RD_MASK 0x70 +# define LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7) +# define LC_RECONFIG_NOW (1 << 8) +# define LC_RENEGOTIATION_SUPPORT (1 << 9) +# define LC_RENEGOTIATE_EN (1 << 10) +# define LC_SHORT_RECONFIG_EN (1 << 11) +# define LC_UPCONFIGURE_SUPPORT (1 << 12) +# define LC_UPCONFIGURE_DIS (1 << 13) +# define LC_DYN_LANES_PWR_STATE(x) ((x) << 21) +# define LC_DYN_LANES_PWR_STATE_MASK (0x3 << 21) +# define LC_DYN_LANES_PWR_STATE_SHIFT 21 +#define PCIE_LC_N_FTS_CNTL 0xa3 /* PCIE_P */ +# define LC_XMIT_N_FTS(x) ((x) << 0) +# define LC_XMIT_N_FTS_MASK (0xff << 0) +# define LC_XMIT_N_FTS_SHIFT 0 +# define LC_XMIT_N_FTS_OVERRIDE_EN (1 << 8) +# define LC_N_FTS_MASK (0xff << 24) +#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */ +# define LC_GEN2_EN_STRAP (1 << 0) +# define LC_GEN3_EN_STRAP (1 << 1) +# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 2) +# define LC_TARGET_LINK_SPEED_OVERRIDE_MASK (0x3 << 3) +# define LC_TARGET_LINK_SPEED_OVERRIDE_SHIFT 3 +# define LC_FORCE_EN_SW_SPEED_CHANGE (1 << 5) +# define LC_FORCE_DIS_SW_SPEED_CHANGE (1 << 6) +# define LC_FORCE_EN_HW_SPEED_CHANGE (1 << 7) +# define LC_FORCE_DIS_HW_SPEED_CHANGE (1 << 8) +# define LC_INITIATE_LINK_SPEED_CHANGE (1 << 9) +# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 10) +# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 10 +# define LC_CURRENT_DATA_RATE_MASK (0x3 << 13) /* 0/1/2 = gen1/2/3 */ +# define LC_CURRENT_DATA_RATE_SHIFT 13 +# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 16) +# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 18) +# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 19) +# define LC_OTHER_SIDE_EVER_SENT_GEN3 (1 << 20) +# define LC_OTHER_SIDE_SUPPORTS_GEN3 (1 << 21) + +#define PCIE_LC_CNTL2 0xb1 +# define LC_ALLOW_PDWN_IN_L1 (1 << 17) +# define LC_ALLOW_PDWN_IN_L23 (1 << 18) + +#define PCIE_LC_CNTL3 0xb5 /* PCIE_P */ +# define LC_GO_TO_RECOVERY (1 << 30) +#define PCIE_LC_CNTL4 0xb6 /* PCIE_P */ +# define LC_REDO_EQ (1 << 5) +# define LC_SET_QUIESCE (1 << 13) + +/* + * UVD + */ +#define UVD_UDEC_ADDR_CONFIG 0x3bd3 +#define UVD_UDEC_DB_ADDR_CONFIG 0x3bd4 +#define UVD_UDEC_DBW_ADDR_CONFIG 0x3bd5 +#define UVD_RBC_RB_RPTR 0x3da4 +#define UVD_RBC_RB_WPTR 0x3da5 +#define UVD_STATUS 0x3daf + +#define UVD_CGC_CTRL 0x3dc2 +# define DCM (1 << 0) +# define CG_DT(x) ((x) << 2) +# define CG_DT_MASK (0xf << 2) +# define CLK_OD(x) ((x) << 6) +# define CLK_OD_MASK (0x1f << 6) + + /* UVD CTX indirect */ +#define UVD_CGC_MEM_CTRL 0xC0 +#define UVD_CGC_CTRL2 0xC1 +# define DYN_OR_EN (1 << 0) +# define DYN_RR_EN (1 << 1) +# define G_DIV_ID(x) ((x) << 2) +# define G_DIV_ID_MASK (0x7 << 2) + +/* + * PM4 + */ +#define PACKET0(reg, n) ((RADEON_PACKET_TYPE0 << 30) | \ + (((reg) >> 2) & 0xFFFF) | \ + ((n) & 0x3FFF) << 16) +#define CP_PACKET2 0x80000000 +#define PACKET2_PAD_SHIFT 0 +#define PACKET2_PAD_MASK (0x3fffffff << 0) + +#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) +#define RADEON_PACKET_TYPE3 3 +#define PACKET3(op, n) ((RADEON_PACKET_TYPE3 << 30) | \ + (((op) & 0xFF) << 8) | \ + ((n) & 0x3FFF) << 16) + +#define PACKET3_COMPUTE(op, n) (PACKET3(op, n) | 1 << 1) + +/* Packet 3 types */ +#define PACKET3_NOP 0x10 +#define PACKET3_SET_BASE 0x11 +#define PACKET3_BASE_INDEX(x) ((x) << 0) +#define GDS_PARTITION_BASE 2 +#define CE_PARTITION_BASE 3 +#define PACKET3_CLEAR_STATE 0x12 +#define PACKET3_INDEX_BUFFER_SIZE 0x13 +#define PACKET3_DISPATCH_DIRECT 0x15 +#define PACKET3_DISPATCH_INDIRECT 0x16 +#define PACKET3_ALLOC_GDS 0x1B +#define PACKET3_WRITE_GDS_RAM 0x1C +#define PACKET3_ATOMIC_GDS 0x1D +#define PACKET3_ATOMIC 0x1E +#define PACKET3_OCCLUSION_QUERY 0x1F +#define PACKET3_SET_PREDICATION 0x20 +#define PACKET3_REG_RMW 0x21 +#define PACKET3_COND_EXEC 0x22 +#define PACKET3_PRED_EXEC 0x23 +#define PACKET3_DRAW_INDIRECT 0x24 +#define PACKET3_DRAW_INDEX_INDIRECT 0x25 +#define PACKET3_INDEX_BASE 0x26 +#define PACKET3_DRAW_INDEX_2 0x27 +#define PACKET3_CONTEXT_CONTROL 0x28 +#define PACKET3_INDEX_TYPE 0x2A +#define PACKET3_DRAW_INDIRECT_MULTI 0x2C +#define PACKET3_DRAW_INDEX_AUTO 0x2D +#define PACKET3_DRAW_INDEX_IMMD 0x2E +#define PACKET3_NUM_INSTANCES 0x2F +#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30 +#define PACKET3_INDIRECT_BUFFER_CONST 0x31 +#define PACKET3_INDIRECT_BUFFER 0x3F +#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 +#define PACKET3_DRAW_INDEX_OFFSET_2 0x35 +#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 +#define PACKET3_WRITE_DATA 0x37 +#define WRITE_DATA_DST_SEL(x) ((x) << 8) + /* 0 - register + * 1 - memory (sync - via GRBM) + * 2 - tc/l2 + * 3 - gds + * 4 - reserved + * 5 - memory (async - direct) + */ +#define WR_ONE_ADDR (1 << 16) +#define WR_CONFIRM (1 << 20) +#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30) + /* 0 - me + * 1 - pfp + * 2 - ce + */ +#define PACKET3_DRAW_INDEX_INDIRECT_MULTI 0x38 +#define PACKET3_MEM_SEMAPHORE 0x39 +#define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B +#define PACKET3_WAIT_REG_MEM 0x3C +#define WAIT_REG_MEM_FUNCTION(x) ((x) << 0) + /* 0 - always + * 1 - < + * 2 - <= + * 3 - == + * 4 - != + * 5 - >= + * 6 - > + */ +#define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4) + /* 0 - reg + * 1 - mem + */ +#define WAIT_REG_MEM_ENGINE(x) ((x) << 8) + /* 0 - me + * 1 - pfp + */ +#define PACKET3_MEM_WRITE 0x3D +#define PACKET3_COPY_DATA 0x40 +#define PACKET3_CP_DMA 0x41 +/* 1. header + * 2. SRC_ADDR_LO or DATA [31:0] + * 3. CP_SYNC [31] | SRC_SEL [30:29] | ENGINE [27] | DST_SEL [21:20] | + * SRC_ADDR_HI [7:0] + * 4. DST_ADDR_LO [31:0] + * 5. DST_ADDR_HI [7:0] + * 6. COMMAND [30:21] | BYTE_COUNT [20:0] + */ +# define PACKET3_CP_DMA_DST_SEL(x) ((x) << 20) + /* 0 - DST_ADDR + * 1 - GDS + */ +# define PACKET3_CP_DMA_ENGINE(x) ((x) << 27) + /* 0 - ME + * 1 - PFP + */ +# define PACKET3_CP_DMA_SRC_SEL(x) ((x) << 29) + /* 0 - SRC_ADDR + * 1 - GDS + * 2 - DATA + */ +# define PACKET3_CP_DMA_CP_SYNC (1 << 31) +/* COMMAND */ +# define PACKET3_CP_DMA_DIS_WC (1 << 21) +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_CP_DMA_CMD_DST_SWAP(x) ((x) << 24) + /* 0 - none + * 1 - 8 in 16 + * 2 - 8 in 32 + * 3 - 8 in 64 + */ +# define PACKET3_CP_DMA_CMD_SAS (1 << 26) + /* 0 - memory + * 1 - register + */ +# define PACKET3_CP_DMA_CMD_DAS (1 << 27) + /* 0 - memory + * 1 - register + */ +# define PACKET3_CP_DMA_CMD_SAIC (1 << 28) +# define PACKET3_CP_DMA_CMD_DAIC (1 << 29) +# define PACKET3_CP_DMA_CMD_RAW_WAIT (1 << 30) +#define PACKET3_PFP_SYNC_ME 0x42 +#define PACKET3_SURFACE_SYNC 0x43 +# define PACKET3_DEST_BASE_0_ENA (1 << 0) +# define PACKET3_DEST_BASE_1_ENA (1 << 1) +# define PACKET3_CB0_DEST_BASE_ENA (1 << 6) +# define PACKET3_CB1_DEST_BASE_ENA (1 << 7) +# define PACKET3_CB2_DEST_BASE_ENA (1 << 8) +# define PACKET3_CB3_DEST_BASE_ENA (1 << 9) +# define PACKET3_CB4_DEST_BASE_ENA (1 << 10) +# define PACKET3_CB5_DEST_BASE_ENA (1 << 11) +# define PACKET3_CB6_DEST_BASE_ENA (1 << 12) +# define PACKET3_CB7_DEST_BASE_ENA (1 << 13) +# define PACKET3_DB_DEST_BASE_ENA (1 << 14) +# define PACKET3_DEST_BASE_2_ENA (1 << 19) +# define PACKET3_DEST_BASE_3_ENA (1 << 21) +# define PACKET3_TCL1_ACTION_ENA (1 << 22) +# define PACKET3_TC_ACTION_ENA (1 << 23) +# define PACKET3_CB_ACTION_ENA (1 << 25) +# define PACKET3_DB_ACTION_ENA (1 << 26) +# define PACKET3_SH_KCACHE_ACTION_ENA (1 << 27) +# define PACKET3_SH_ICACHE_ACTION_ENA (1 << 29) +#define PACKET3_ME_INITIALIZE 0x44 +#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) +#define PACKET3_COND_WRITE 0x45 +#define PACKET3_EVENT_WRITE 0x46 +#define EVENT_TYPE(x) ((x) << 0) +#define EVENT_INDEX(x) ((x) << 8) + /* 0 - any non-TS event + * 1 - ZPASS_DONE + * 2 - SAMPLE_PIPELINESTAT + * 3 - SAMPLE_STREAMOUTSTAT* + * 4 - *S_PARTIAL_FLUSH + * 5 - EOP events + * 6 - EOS events + * 7 - CACHE_FLUSH, CACHE_FLUSH_AND_INV_EVENT + */ +#define INV_L2 (1 << 20) + /* INV TC L2 cache when EVENT_INDEX = 7 */ +#define PACKET3_EVENT_WRITE_EOP 0x47 +#define DATA_SEL(x) ((x) << 29) + /* 0 - discard + * 1 - send low 32bit data + * 2 - send 64bit data + * 3 - send 64bit counter value + */ +#define INT_SEL(x) ((x) << 24) + /* 0 - none + * 1 - interrupt only (DATA_SEL = 0) + * 2 - interrupt when data write is confirmed + */ +#define PACKET3_EVENT_WRITE_EOS 0x48 +#define PACKET3_PREAMBLE_CNTL 0x4A +# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) +# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28) +#define PACKET3_ONE_REG_WRITE 0x57 +#define PACKET3_LOAD_CONFIG_REG 0x5F +#define PACKET3_LOAD_CONTEXT_REG 0x60 +#define PACKET3_LOAD_SH_REG 0x61 +#define PACKET3_SET_CONFIG_REG 0x68 +#define PACKET3_SET_CONFIG_REG_START 0x00002000 +#define PACKET3_SET_CONFIG_REG_END 0x00002c00 +#define PACKET3_SET_CONTEXT_REG 0x69 +#define PACKET3_SET_CONTEXT_REG_START 0x000a000 +#define PACKET3_SET_CONTEXT_REG_END 0x000a400 +#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73 +#define PACKET3_SET_RESOURCE_INDIRECT 0x74 +#define PACKET3_SET_SH_REG 0x76 +#define PACKET3_SET_SH_REG_START 0x00002c00 +#define PACKET3_SET_SH_REG_END 0x00003000 +#define PACKET3_SET_SH_REG_OFFSET 0x77 +#define PACKET3_ME_WRITE 0x7A +#define PACKET3_SCRATCH_RAM_WRITE 0x7D +#define PACKET3_SCRATCH_RAM_READ 0x7E +#define PACKET3_CE_WRITE 0x7F +#define PACKET3_LOAD_CONST_RAM 0x80 +#define PACKET3_WRITE_CONST_RAM 0x81 +#define PACKET3_WRITE_CONST_RAM_OFFSET 0x82 +#define PACKET3_DUMP_CONST_RAM 0x83 +#define PACKET3_INCREMENT_CE_COUNTER 0x84 +#define PACKET3_INCREMENT_DE_COUNTER 0x85 +#define PACKET3_WAIT_ON_CE_COUNTER 0x86 +#define PACKET3_WAIT_ON_DE_COUNTER 0x87 +#define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 +#define PACKET3_SET_CE_DE_COUNTERS 0x89 +#define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A +#define PACKET3_SWITCH_BUFFER 0x8B + +/* ASYNC DMA - first instance at 0xd000, second at 0xd800 */ +#define DMA0_REGISTER_OFFSET 0x0 /* not a register */ +#define DMA1_REGISTER_OFFSET 0x200 /* not a register */ + +#define DMA_RB_CNTL 0x3400 +# define DMA_RB_ENABLE (1 << 0) +# define DMA_RB_SIZE(x) ((x) << 1) /* log2 */ +# define DMA_RB_SWAP_ENABLE (1 << 9) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_ENABLE (1 << 12) +# define DMA_RPTR_WRITEBACK_SWAP_ENABLE (1 << 13) /* 8IN32 */ +# define DMA_RPTR_WRITEBACK_TIMER(x) ((x) << 16) /* log2 */ +#define DMA_RB_BASE 0x3401 +#define DMA_RB_RPTR 0x3402 +#define DMA_RB_WPTR 0x3403 + +#define DMA_RB_RPTR_ADDR_HI 0x3407 +#define DMA_RB_RPTR_ADDR_LO 0x3408 + +#define DMA_IB_CNTL 0x3409 +# define DMA_IB_ENABLE (1 << 0) +# define DMA_IB_SWAP_ENABLE (1 << 4) +# define CMD_VMID_FORCE (1 << 31) +#define DMA_IB_RPTR 0x340a +#define DMA_CNTL 0x340b +# define TRAP_ENABLE (1 << 0) +# define SEM_INCOMPLETE_INT_ENABLE (1 << 1) +# define SEM_WAIT_INT_ENABLE (1 << 2) +# define DATA_SWAP_ENABLE (1 << 3) +# define FENCE_SWAP_ENABLE (1 << 4) +# define CTXEMPTY_INT_ENABLE (1 << 28) +#define DMA_STATUS_REG 0x340d +# define DMA_IDLE (1 << 0) +#define DMA_TILING_CONFIG 0x342e + +#define DMA_POWER_CNTL 0x342f +# define MEM_POWER_OVERRIDE (1 << 8) +#define DMA_CLK_CTRL 0x3430 + +#define DMA_PG 0x3435 +# define PG_CNTL_ENABLE (1 << 0) +#define DMA_PGFSM_CONFIG 0x3436 +#define DMA_PGFSM_WRITE 0x3437 + +#define DMA_PACKET(cmd, b, t, s, n) ((((cmd) & 0xF) << 28) | \ + (((b) & 0x1) << 26) | \ + (((t) & 0x1) << 23) | \ + (((s) & 0x1) << 22) | \ + (((n) & 0xFFFFF) << 0)) + +#define DMA_IB_PACKET(cmd, vmid, n) ((((cmd) & 0xF) << 28) | \ + (((vmid) & 0xF) << 20) | \ + (((n) & 0xFFFFF) << 0)) + +#define DMA_PTE_PDE_PACKET(n) ((2 << 28) | \ + (1 << 26) | \ + (1 << 21) | \ + (((n) & 0xFFFFF) << 0)) + +/* async DMA Packet types */ +#define DMA_PACKET_WRITE 0x2 +#define DMA_PACKET_COPY 0x3 +#define DMA_PACKET_INDIRECT_BUFFER 0x4 +#define DMA_PACKET_SEMAPHORE 0x5 +#define DMA_PACKET_FENCE 0x6 +#define DMA_PACKET_TRAP 0x7 +#define DMA_PACKET_SRBM_WRITE 0x9 +#define DMA_PACKET_CONSTANT_FILL 0xd +#define DMA_PACKET_POLL_REG_MEM 0xe +#define DMA_PACKET_NOP 0xf + +#define VCE_STATUS 0x20004 +#define VCE_VCPU_CNTL 0x20014 +#define VCE_CLK_EN (1 << 0) +#define VCE_VCPU_CACHE_OFFSET0 0x20024 +#define VCE_VCPU_CACHE_SIZE0 0x20028 +#define VCE_VCPU_CACHE_OFFSET1 0x2002c +#define VCE_VCPU_CACHE_SIZE1 0x20030 +#define VCE_VCPU_CACHE_OFFSET2 0x20034 +#define VCE_VCPU_CACHE_SIZE2 0x20038 +#define VCE_SOFT_RESET 0x20120 +#define VCE_ECPU_SOFT_RESET (1 << 0) +#define VCE_FME_SOFT_RESET (1 << 2) +#define VCE_RB_BASE_LO2 0x2016c +#define VCE_RB_BASE_HI2 0x20170 +#define VCE_RB_SIZE2 0x20174 +#define VCE_RB_RPTR2 0x20178 +#define VCE_RB_WPTR2 0x2017c +#define VCE_RB_BASE_LO 0x20180 +#define VCE_RB_BASE_HI 0x20184 +#define VCE_RB_SIZE 0x20188 +#define VCE_RB_RPTR 0x2018c +#define VCE_RB_WPTR 0x20190 +#define VCE_CLOCK_GATING_A 0x202f8 +#define VCE_CLOCK_GATING_B 0x202fc +#define VCE_UENC_CLOCK_GATING 0x205bc +#define VCE_UENC_REG_CLOCK_GATING 0x205c0 +#define VCE_FW_REG_STATUS 0x20e10 +# define VCE_FW_REG_STATUS_BUSY (1 << 0) +# define VCE_FW_REG_STATUS_PASS (1 << 3) +# define VCE_FW_REG_STATUS_DONE (1 << 11) +#define VCE_LMI_FW_START_KEYSEL 0x20e18 +#define VCE_LMI_FW_PERIODIC_CTRL 0x20e20 +#define VCE_LMI_CTRL2 0x20e74 +#define VCE_LMI_CTRL 0x20e98 +#define VCE_LMI_VM_CTRL 0x20ea0 +#define VCE_LMI_SWAP_CNTL 0x20eb4 +#define VCE_LMI_SWAP_CNTL1 0x20eb8 +#define VCE_LMI_CACHE_CTRL 0x20ef4 + +#define VCE_CMD_NO_OP 0x00000000 +#define VCE_CMD_END 0x00000001 +#define VCE_CMD_IB 0x00000002 +#define VCE_CMD_FENCE 0x00000003 +#define VCE_CMD_TRAP 0x00000004 +#define VCE_CMD_IB_AUTO 0x00000005 +#define VCE_CMD_SEMAPHORE 0x00000006 + + +//#dce stupp +/* display controller offsets used for crtc/cur/lut/grph/viewport/etc. */ +#define SI_CRTC0_REGISTER_OFFSET 0 //(0x6df0 - 0x6df0)/4 +#define SI_CRTC1_REGISTER_OFFSET 0x300 //(0x79f0 - 0x6df0)/4 +#define SI_CRTC2_REGISTER_OFFSET 0x2600 //(0x105f0 - 0x6df0)/4 +#define SI_CRTC3_REGISTER_OFFSET 0x2900 //(0x111f0 - 0x6df0)/4 +#define SI_CRTC4_REGISTER_OFFSET 0x2c00 //(0x11df0 - 0x6df0)/4 +#define SI_CRTC5_REGISTER_OFFSET 0x2f00 //(0x129f0 - 0x6df0)/4 + +#define CURSOR_WIDTH 64 +#define CURSOR_HEIGHT 64 +#define AMDGPU_MM_INDEX 0x0000 +#define AMDGPU_MM_DATA 0x0001 + +#define VERDE_NUM_CRTC 6 +#define BLACKOUT_MODE_MASK 0x00000007 +#define VGA_RENDER_CONTROL 0xC0 +#define R_000300_VGA_RENDER_CONTROL 0xC0 +#define C_000300_VGA_VSTATUS_CNTL 0xFFFCFFFF +#define EVERGREEN_CRTC_STATUS 0x1BA3 +#define EVERGREEN_CRTC_V_BLANK (1 << 0) +#define EVERGREEN_CRTC_STATUS_POSITION 0x1BA4 +/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */ +#define EVERGREEN_CRTC_V_BLANK_START_END 0x1b8d +#define EVERGREEN_CRTC_CONTROL 0x1b9c +#define EVERGREEN_CRTC_MASTER_EN (1 << 0) +#define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) +#define EVERGREEN_CRTC_BLANK_CONTROL 0x1b9d +#define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) +#define EVERGREEN_CRTC_V_BLANK (1 << 0) +#define EVERGREEN_CRTC_STATUS_HV_COUNT 0x1ba8 +#define EVERGREEN_CRTC_UPDATE_LOCK 0x1bb5 +#define EVERGREEN_MASTER_UPDATE_LOCK 0x1bbd +#define EVERGREEN_MASTER_UPDATE_MODE 0x1bbe +#define EVERGREEN_GRPH_UPDATE_LOCK (1 << 16) +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1a07 +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1a08 +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS 0x1a04 +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS 0x1a05 +#define EVERGREEN_GRPH_UPDATE 0x1a11 +#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0xc4 +#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0xc9 +#define EVERGREEN_GRPH_SURFACE_UPDATE_PENDING (1 << 2) + +#define EVERGREEN_DATA_FORMAT 0x1ac0 +# define EVERGREEN_INTERLEAVE_EN (1 << 0) + +#define MC_SHARED_CHMAP__NOOFCHAN_MASK 0xf000 +#define MC_SHARED_CHMAP__NOOFCHAN__SHIFT 0xc + +#define R600_D1GRPH_ARRAY_MODE_LINEAR_GENERAL (0 << 20) +#define R600_D1GRPH_ARRAY_MODE_LINEAR_ALIGNED (1 << 20) +#define R600_D1GRPH_ARRAY_MODE_1D_TILED_THIN1 (2 << 20) +#define R600_D1GRPH_ARRAY_MODE_2D_TILED_THIN1 (4 << 20) + +#define AMDGPU_TILING_MACRO 0x1 +#define AMDGPU_TILING_MICRO 0x2 + +#define R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1a45 +#define R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1845 + +#define R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1847 +#define R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1a47 + +#define DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT_MASK 0x8 +#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT_MASK 0x8 +#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT_MASK 0x8 +#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT_MASK 0x8 +#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT_MASK 0x8 +#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT_MASK 0x8 + +#define DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT_MASK 0x4 +#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT_MASK 0x4 +#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT_MASK 0x4 +#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT_MASK 0x4 +#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT_MASK 0x4 +#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT_MASK 0x4 + +#define DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT_MASK 0x20000 +#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT_MASK 0x20000 +#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT_MASK 0x20000 +#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT_MASK 0x20000 +#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT_MASK 0x20000 +#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK 0x20000 + +#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK 0x1 +#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK 0x100 + +#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK 0x1 + +#define R600_D1GRPH_SWAP_CONTROL 0x1843 +#define R600_D1GRPH_SWAP_ENDIAN_NONE (0 << 0) +#define R600_D1GRPH_SWAP_ENDIAN_16BIT (1 << 0) +#define R600_D1GRPH_SWAP_ENDIAN_32BIT (2 << 0) +#define R600_D1GRPH_SWAP_ENDIAN_64BIT (3 << 0) + +#define AVIVO_D1VGA_CONTROL 0x00cc +#define AVIVO_D2VGA_CONTROL 0x00ce + +#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK 0x1 + +#define FMT_BIT_DEPTH_CONTROL 0x1bf2 +#define FMT_TRUNCATE_EN (1 << 0) +#define FMT_TRUNCATE_DEPTH (1 << 4) +#define FMT_SPATIAL_DITHER_EN (1 << 8) +#define FMT_SPATIAL_DITHER_MODE(x) ((x) << 9) +#define FMT_SPATIAL_DITHER_DEPTH (1 << 12) +#define FMT_FRAME_RANDOM_ENABLE (1 << 13) +#define FMT_RGB_RANDOM_ENABLE (1 << 14) +#define FMT_HIGHPASS_RANDOM_ENABLE (1 << 15) +#define FMT_TEMPORAL_DITHER_EN (1 << 16) +#define FMT_TEMPORAL_DITHER_DEPTH (1 << 20) +#define FMT_TEMPORAL_DITHER_OFFSET(x) ((x) << 21) +#define FMT_TEMPORAL_LEVEL (1 << 24) +#define FMT_TEMPORAL_DITHER_RESET (1 << 25) +#define FMT_25FRC_SEL(x) ((x) << 26) +#define FMT_50FRC_SEL(x) ((x) << 28) +#define FMT_75FRC_SEL(x) ((x) << 30) + +#define EVERGREEN_DC_LUT_CONTROL 0x1a80 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE 0x1a81 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN 0x1a82 +#define EVERGREEN_DC_LUT_BLACK_OFFSET_RED 0x1a83 +#define EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE 0x1a84 +#define EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN 0x1a85 +#define EVERGREEN_DC_LUT_WHITE_OFFSET_RED 0x1a86 +#define EVERGREEN_DC_LUT_30_COLOR 0x1a7c +#define EVERGREEN_DC_LUT_RW_INDEX 0x1a79 +#define EVERGREEN_DC_LUT_WRITE_EN_MASK 0x1a7e +#define EVERGREEN_DC_LUT_RW_MODE 0x1a78 + +#define EVERGREEN_GRPH_ENABLE 0x1a00 +#define EVERGREEN_GRPH_CONTROL 0x1a01 +#define EVERGREEN_GRPH_DEPTH(x) (((x) & 0x3) << 0) +#define EVERGREEN_GRPH_DEPTH_8BPP 0 +#define EVERGREEN_GRPH_DEPTH_16BPP 1 +#define EVERGREEN_GRPH_DEPTH_32BPP 2 +#define EVERGREEN_GRPH_NUM_BANKS(x) (((x) & 0x3) << 2) +#define EVERGREEN_ADDR_SURF_2_BANK 0 +#define EVERGREEN_ADDR_SURF_4_BANK 1 +#define EVERGREEN_ADDR_SURF_8_BANK 2 +#define EVERGREEN_ADDR_SURF_16_BANK 3 +#define EVERGREEN_GRPH_Z(x) (((x) & 0x3) << 4) +#define EVERGREEN_GRPH_BANK_WIDTH(x) (((x) & 0x3) << 6) +#define EVERGREEN_ADDR_SURF_BANK_WIDTH_1 0 +#define EVERGREEN_ADDR_SURF_BANK_WIDTH_2 1 +#define EVERGREEN_ADDR_SURF_BANK_WIDTH_4 2 +#define EVERGREEN_ADDR_SURF_BANK_WIDTH_8 3 +#define EVERGREEN_GRPH_FORMAT(x) (((x) & 0x7) << 8) + +#define EVERGREEN_GRPH_FORMAT_INDEXED 0 +#define EVERGREEN_GRPH_FORMAT_ARGB1555 0 +#define EVERGREEN_GRPH_FORMAT_ARGB565 1 +#define EVERGREEN_GRPH_FORMAT_ARGB4444 2 +#define EVERGREEN_GRPH_FORMAT_AI88 3 +#define EVERGREEN_GRPH_FORMAT_MONO16 4 +#define EVERGREEN_GRPH_FORMAT_BGRA5551 5 + +/* 32 BPP */ +#define EVERGREEN_GRPH_FORMAT_ARGB8888 0 +#define EVERGREEN_GRPH_FORMAT_ARGB2101010 1 +#define EVERGREEN_GRPH_FORMAT_32BPP_DIG 2 +#define EVERGREEN_GRPH_FORMAT_8B_ARGB2101010 3 +#define EVERGREEN_GRPH_FORMAT_BGRA1010102 4 +#define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102 5 +#define EVERGREEN_GRPH_FORMAT_RGB111110 6 +#define EVERGREEN_GRPH_FORMAT_BGR101111 7 +#define EVERGREEN_GRPH_BANK_HEIGHT(x) (((x) & 0x3) << 11) +#define EVERGREEN_ADDR_SURF_BANK_HEIGHT_1 0 +#define EVERGREEN_ADDR_SURF_BANK_HEIGHT_2 1 +#define EVERGREEN_ADDR_SURF_BANK_HEIGHT_4 2 +#define EVERGREEN_ADDR_SURF_BANK_HEIGHT_8 3 +#define EVERGREEN_GRPH_TILE_SPLIT(x) (((x) & 0x7) << 13) +#define EVERGREEN_ADDR_SURF_TILE_SPLIT_64B 0 +#define EVERGREEN_ADDR_SURF_TILE_SPLIT_128B 1 +#define EVERGREEN_ADDR_SURF_TILE_SPLIT_256B 2 +#define EVERGREEN_ADDR_SURF_TILE_SPLIT_512B 3 +#define EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB 4 +#define EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB 5 +#define EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB 6 +#define EVERGREEN_GRPH_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 18) +#define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1 0 +#define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2 1 +#define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4 2 +#define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8 3 +#define EVERGREEN_GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20) +#define EVERGREEN_GRPH_ARRAY_LINEAR_GENERAL 0 +#define EVERGREEN_GRPH_ARRAY_LINEAR_ALIGNED 1 +#define EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1 2 +#define EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1 4 +#define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1 0 +#define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2 1 +#define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4 2 +#define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8 3 + +#define EVERGREEN_GRPH_SWAP_CONTROL 0x1a03 +#define EVERGREEN_GRPH_ENDIAN_SWAP(x) (((x) & 0x3) << 0) +#define EVERGREEN_GRPH_ENDIAN_NONE 0 + +/* this object requires a surface when mapped - i.e. front buffer */ +#define RADEON_TILING_SURFACE 0x10 +#define RADEON_TILING_MICRO_SQUARE 0x20 +#define RADEON_TILING_EG_BANKW_SHIFT 8 +#define RADEON_TILING_EG_BANKW_MASK 0xf +#define RADEON_TILING_EG_BANKH_SHIFT 12 +#define RADEON_TILING_EG_BANKH_MASK 0xf +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT 16 +#define RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK 0xf +#define RADEON_TILING_EG_TILE_SPLIT_SHIFT 24 +#define RADEON_TILING_EG_TILE_SPLIT_MASK 0xf +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT 28 +#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK 0xf + +#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8 +#define SI_TILE_MODE_COLOR_1D 13 +#define SI_TILE_MODE_COLOR_1D_SCANOUT 9 +#define SI_TILE_MODE_COLOR_2D_8BPP 14 +#define SI_TILE_MODE_COLOR_2D_16BPP 15 +#define SI_TILE_MODE_COLOR_2D_32BPP 16 +#define SI_TILE_MODE_COLOR_2D_64BPP 17 +#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11 +#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12 +#define SI_TILE_MODE_DEPTH_STENCIL_1D 4 +#define SI_TILE_MODE_DEPTH_STENCIL_2D 0 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3 +#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2 + +#define EVERGREEN_D3VGA_CONTROL 0xf8 +#define EVERGREEN_D4VGA_CONTROL 0xf9 +#define EVERGREEN_D5VGA_CONTROL 0xfa +#define EVERGREEN_D6VGA_CONTROL 0xfb + +#define EVERGREEN_GRPH_SURFACE_ADDRESS_MASK 0xffffff00 + +#define EVERGREEN_GRPH_LUT_10BIT_BYPASS_CONTROL 0x1a02 +#define EVERGREEN_LUT_10BIT_BYPASS_EN (1 << 8) + +#define EVERGREEN_GRPH_PITCH 0x1a06 +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1a07 +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1a08 +#define EVERGREEN_GRPH_SURFACE_OFFSET_X 0x1a09 +#define EVERGREEN_GRPH_SURFACE_OFFSET_Y 0x1a0a +#define EVERGREEN_GRPH_X_START 0x1a0b +#define EVERGREEN_GRPH_Y_START 0x1a0c +#define EVERGREEN_GRPH_X_END 0x1a0d +#define EVERGREEN_GRPH_Y_END 0x1a0e +#define EVERGREEN_GRPH_UPDATE 0x1a11 +#define EVERGREEN_GRPH_SURFACE_UPDATE_PENDING (1 << 2) +#define EVERGREEN_GRPH_UPDATE_LOCK (1 << 16) +#define EVERGREEN_GRPH_FLIP_CONTROL 0x1a12 +#define EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN (1 << 0) + +#define EVERGREEN_VIEWPORT_START 0x1b5c +#define EVERGREEN_VIEWPORT_SIZE 0x1b5d +#define EVERGREEN_DESKTOP_HEIGHT 0x1ac1 + +/* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */ +#define EVERGREEN_CUR_CONTROL 0x1a66 +# define EVERGREEN_CURSOR_EN (1 << 0) +# define EVERGREEN_CURSOR_MODE(x) (((x) & 0x3) << 8) +# define EVERGREEN_CURSOR_MONO 0 +# define EVERGREEN_CURSOR_24_1 1 +# define EVERGREEN_CURSOR_24_8_PRE_MULT 2 +# define EVERGREEN_CURSOR_24_8_UNPRE_MULT 3 +# define EVERGREEN_CURSOR_2X_MAGNIFY (1 << 16) +# define EVERGREEN_CURSOR_FORCE_MC_ON (1 << 20) +# define EVERGREEN_CURSOR_URGENT_CONTROL(x) (((x) & 0x7) << 24) +# define EVERGREEN_CURSOR_URGENT_ALWAYS 0 +# define EVERGREEN_CURSOR_URGENT_1_8 1 +# define EVERGREEN_CURSOR_URGENT_1_4 2 +# define EVERGREEN_CURSOR_URGENT_3_8 3 +# define EVERGREEN_CURSOR_URGENT_1_2 4 +#define EVERGREEN_CUR_SURFACE_ADDRESS 0x1a67 +# define EVERGREEN_CUR_SURFACE_ADDRESS_MASK 0xfffff000 +#define EVERGREEN_CUR_SIZE 0x1a68 +#define EVERGREEN_CUR_SURFACE_ADDRESS_HIGH 0x1a69 +#define EVERGREEN_CUR_POSITION 0x1a6a +#define EVERGREEN_CUR_HOT_SPOT 0x1a6b +#define EVERGREEN_CUR_COLOR1 0x1a6c +#define EVERGREEN_CUR_COLOR2 0x1a6d +#define EVERGREEN_CUR_UPDATE 0x1a6e +# define EVERGREEN_CURSOR_UPDATE_PENDING (1 << 0) +# define EVERGREEN_CURSOR_UPDATE_TAKEN (1 << 1) +# define EVERGREEN_CURSOR_UPDATE_LOCK (1 << 16) +# define EVERGREEN_CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24) + + +#define NI_INPUT_CSC_CONTROL 0x1a35 +# define NI_INPUT_CSC_GRPH_MODE(x) (((x) & 0x3) << 0) +# define NI_INPUT_CSC_BYPASS 0 +# define NI_INPUT_CSC_PROG_COEFF 1 +# define NI_INPUT_CSC_PROG_SHARED_MATRIXA 2 +# define NI_INPUT_CSC_OVL_MODE(x) (((x) & 0x3) << 4) + +#define NI_OUTPUT_CSC_CONTROL 0x1a3c +# define NI_OUTPUT_CSC_GRPH_MODE(x) (((x) & 0x7) << 0) +# define NI_OUTPUT_CSC_BYPASS 0 +# define NI_OUTPUT_CSC_TV_RGB 1 +# define NI_OUTPUT_CSC_YCBCR_601 2 +# define NI_OUTPUT_CSC_YCBCR_709 3 +# define NI_OUTPUT_CSC_PROG_COEFF 4 +# define NI_OUTPUT_CSC_PROG_SHARED_MATRIXB 5 +# define NI_OUTPUT_CSC_OVL_MODE(x) (((x) & 0x7) << 4) + +#define NI_DEGAMMA_CONTROL 0x1a58 +# define NI_GRPH_DEGAMMA_MODE(x) (((x) & 0x3) << 0) +# define NI_DEGAMMA_BYPASS 0 +# define NI_DEGAMMA_SRGB_24 1 +# define NI_DEGAMMA_XVYCC_222 2 +# define NI_OVL_DEGAMMA_MODE(x) (((x) & 0x3) << 4) +# define NI_ICON_DEGAMMA_MODE(x) (((x) & 0x3) << 8) +# define NI_CURSOR_DEGAMMA_MODE(x) (((x) & 0x3) << 12) + +#define NI_GAMUT_REMAP_CONTROL 0x1a59 +# define NI_GRPH_GAMUT_REMAP_MODE(x) (((x) & 0x3) << 0) +# define NI_GAMUT_REMAP_BYPASS 0 +# define NI_GAMUT_REMAP_PROG_COEFF 1 +# define NI_GAMUT_REMAP_PROG_SHARED_MATRIXA 2 +# define NI_GAMUT_REMAP_PROG_SHARED_MATRIXB 3 +# define NI_OVL_GAMUT_REMAP_MODE(x) (((x) & 0x3) << 4) + +#define NI_REGAMMA_CONTROL 0x1aa0 +# define NI_GRPH_REGAMMA_MODE(x) (((x) & 0x7) << 0) +# define NI_REGAMMA_BYPASS 0 +# define NI_REGAMMA_SRGB_24 1 +# define NI_REGAMMA_XVYCC_222 2 +# define NI_REGAMMA_PROG_A 3 +# define NI_REGAMMA_PROG_B 4 +# define NI_OVL_REGAMMA_MODE(x) (((x) & 0x7) << 4) + + +#define NI_PRESCALE_GRPH_CONTROL 0x1a2d +# define NI_GRPH_PRESCALE_BYPASS (1 << 4) + +#define NI_PRESCALE_OVL_CONTROL 0x1a31 +# define NI_OVL_PRESCALE_BYPASS (1 << 4) + +#define NI_INPUT_GAMMA_CONTROL 0x1a10 +# define NI_GRPH_INPUT_GAMMA_MODE(x) (((x) & 0x3) << 0) +# define NI_INPUT_GAMMA_USE_LUT 0 +# define NI_INPUT_GAMMA_BYPASS 1 +# define NI_INPUT_GAMMA_SRGB_24 2 +# define NI_INPUT_GAMMA_XVYCC_222 3 +# define NI_OVL_INPUT_GAMMA_MODE(x) (((x) & 0x3) << 4) + +#define IH_RB_WPTR__RB_OVERFLOW_MASK 0x1 +#define IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK 0x80000000 +#define SRBM_STATUS__IH_BUSY_MASK 0x20000 +#define SRBM_SOFT_RESET__SOFT_RESET_IH_MASK 0x400 + +#define BLACKOUT_MODE_MASK 0x00000007 +#define VGA_RENDER_CONTROL 0xC0 +#define R_000300_VGA_RENDER_CONTROL 0xC0 +#define C_000300_VGA_VSTATUS_CNTL 0xFFFCFFFF +#define EVERGREEN_CRTC_STATUS 0x1BA3 +#define EVERGREEN_CRTC_V_BLANK (1 << 0) +#define EVERGREEN_CRTC_STATUS_POSITION 0x1BA4 +/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */ +#define EVERGREEN_CRTC_V_BLANK_START_END 0x1b8d +#define EVERGREEN_CRTC_CONTROL 0x1b9c +# define EVERGREEN_CRTC_MASTER_EN (1 << 0) +# define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) +#define EVERGREEN_CRTC_BLANK_CONTROL 0x1b9d +# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) +# define EVERGREEN_CRTC_V_BLANK (1 << 0) +#define EVERGREEN_CRTC_STATUS_HV_COUNT 0x1ba8 +#define EVERGREEN_CRTC_UPDATE_LOCK 0x1bb5 +#define EVERGREEN_MASTER_UPDATE_LOCK 0x1bbd +#define EVERGREEN_MASTER_UPDATE_MODE 0x1bbe +#define EVERGREEN_GRPH_UPDATE_LOCK (1 << 16) +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1a07 +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1a08 +#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS 0x1a04 +#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS 0x1a05 +#define EVERGREEN_GRPH_UPDATE 0x1a11 +#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0xc4 +#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0xc9 +#define EVERGREEN_GRPH_SURFACE_UPDATE_PENDING (1 << 2) + +#define mmVM_CONTEXT1_CNTL__xxRANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x10 +#define mmVM_CONTEXT1_CNTL__xxRANGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x4 +#define mmVM_CONTEXT1_CNTL__xxDUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x80 +#define mmVM_CONTEXT1_CNTL__xxDUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x7 +#define mmVM_CONTEXT1_CNTL__xxPDE0_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x400 +#define mmVM_CONTEXT1_CNTL__xxPDE0_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0xa +#define mmVM_CONTEXT1_CNTL__xxVALID_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x2000 +#define mmVM_CONTEXT1_CNTL__xxVALID_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0xd +#define mmVM_CONTEXT1_CNTL__xxREAD_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x10000 +#define mmVM_CONTEXT1_CNTL__xxREAD_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x10 +#define mmVM_CONTEXT1_CNTL__xxWRITE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x80000 +#define mmVM_CONTEXT1_CNTL__xxWRITE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x13 + +#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS__xxVMID_MASK 0x1e000000 +#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS__xxVMID__SHIFT 0x19 +#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS__xxPROTECTIONS_MASK 0xff +#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS__xxPROTECTIONS__SHIFT 0x0 +#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS__xxMEMORY_CLIENT_ID_MASK 0xff000 +#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS__xxMEMORY_CLIENT_ID__SHIFT 0xc +#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS__xxMEMORY_CLIENT_RW_MASK 0x1000000 +#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS__xxMEMORY_CLIENT_RW__SHIFT 0x18 + +#define mmMC_SHARED_BLACKOUT_CNTL__xxBLACKOUT_MODE_MASK 0x7 +#define mmMC_SHARED_BLACKOUT_CNTL__xxBLACKOUT_MODE__SHIFT 0x0 + +#define mmBIF_FB_EN__xxFB_READ_EN_MASK 0x1 +#define mmBIF_FB_EN__xxFB_READ_EN__SHIFT 0x0 +#define mmBIF_FB_EN__xxFB_WRITE_EN_MASK 0x2 +#define mmBIF_FB_EN__xxFB_WRITE_EN__SHIFT 0x1 + +#define mmSRBM_SOFT_RESET__xxSOFT_RESET_VMC_MASK 0x20000 +#define mmSRBM_SOFT_RESET__xxSOFT_RESET_VMC__SHIFT 0x11 +#define mmSRBM_SOFT_RESET__xxSOFT_RESET_MC_MASK 0x800 +#define mmSRBM_SOFT_RESET__xxSOFT_RESET_MC__SHIFT 0xb + +#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x8 +#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x3 +#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x40 +#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x6 +#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x200 +#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x9 +#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x1000 +#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0xc +#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x8000 +#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0xf +#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x40000 +#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x12 + +#define MC_SEQ_MISC0__MT__MASK 0xf0000000 +#define MC_SEQ_MISC0__MT__GDDR1 0x10000000 +#define MC_SEQ_MISC0__MT__DDR2 0x20000000 +#define MC_SEQ_MISC0__MT__GDDR3 0x30000000 +#define MC_SEQ_MISC0__MT__GDDR4 0x40000000 +#define MC_SEQ_MISC0__MT__GDDR5 0x50000000 +#define MC_SEQ_MISC0__MT__HBM 0x60000000 +#define MC_SEQ_MISC0__MT__DDR3 0xB0000000 + +#define SRBM_STATUS__MCB_BUSY_MASK 0x200 +#define SRBM_STATUS__MCB_BUSY__SHIFT 0x9 +#define SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK 0x400 +#define SRBM_STATUS__MCB_NON_DISPLAY_BUSY__SHIFT 0xa +#define SRBM_STATUS__MCC_BUSY_MASK 0x800 +#define SRBM_STATUS__MCC_BUSY__SHIFT 0xb +#define SRBM_STATUS__MCD_BUSY_MASK 0x1000 +#define SRBM_STATUS__MCD_BUSY__SHIFT 0xc +#define SRBM_STATUS__VMC_BUSY_MASK 0x100 +#define SRBM_STATUS__VMC_BUSY__SHIFT 0x8 + + +#define GRBM_STATUS__GUI_ACTIVE_MASK 0x80000000 +#define CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK 0x4000000 +#define CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK 0x800000 +#define CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK 0x400000 +#define PACKET3_SEM_WAIT_ON_SIGNAL (0x1 << 12) +#define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) +#define PACKET3_SEM_SEL_WAIT (0x7 << 29) + +#define CONFIG_CNTL 0x1509 +#define CC_DRM_ID_STRAPS 0X1559 +#define AMDGPU_PCIE_INDEX 0xc +#define AMDGPU_PCIE_DATA 0xd + +#define DMA_SEM_INCOMPLETE_TIMER_CNTL 0x3411 +#define DMA_SEM_WAIT_FAIL_TIMER_CNTL 0x3412 +#define DMA_MODE 0x342f +#define DMA_RB_RPTR_ADDR_HI 0x3407 +#define DMA_RB_RPTR_ADDR_LO 0x3408 +#define DMA_BUSY_MASK 0x20 +#define DMA1_BUSY_MASK 0X40 +#define SDMA_MAX_INSTANCE 2 + +#define PCIE_BUS_CLK 10000 +#define TCLK (PCIE_BUS_CLK / 10) +#define CC_DRM_ID_STRAPS__ATI_REV_ID_MASK 0xf0000000 +#define CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT 0x1c +#define PCIE_PORT_INDEX 0xe +#define PCIE_PORT_DATA 0xf +#define EVERGREEN_PIF_PHY0_INDEX 0x8 +#define EVERGREEN_PIF_PHY0_DATA 0xc +#define EVERGREEN_PIF_PHY1_INDEX 0x10 +#define EVERGREEN_PIF_PHY1_DATA 0x14 + +#define MC_VM_FB_OFFSET 0x81a + +#endif -- cgit v1.1 From df70502eef80be23e9eab6c916aeb91b460211e9 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 14:01:19 +0800 Subject: drm/amdgpu: add graphic memory controller implementation for si v7 v4: rebase fixups v5: rebase fixups v5: rebase fixups v6: rebase fixups for gart size changes v7: add gmc v6 firmware versions for sysfs dump Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 1071 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h | 29 + 2 files changed, 1100 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c create mode 100644 drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c new file mode 100644 index 0000000..1d2952b --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -0,0 +1,1071 @@ + +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +#include "drmP.h" +#include "amdgpu.h" +#include "gmc_v6_0.h" +#include "amdgpu_ucode.h" +#include "si/sid.h" + +static void gmc_v6_0_set_gart_funcs(struct amdgpu_device *adev); +static void gmc_v6_0_set_irq_funcs(struct amdgpu_device *adev); +static int gmc_v6_0_wait_for_idle(void *handle); + +MODULE_FIRMWARE("radeon/tahiti_mc.bin"); +MODULE_FIRMWARE("radeon/pitcairn_mc.bin"); +MODULE_FIRMWARE("radeon/verde_mc.bin"); +MODULE_FIRMWARE("radeon/oland_mc.bin"); + +static const u32 crtc_offsets[6] = +{ + SI_CRTC0_REGISTER_OFFSET, + SI_CRTC1_REGISTER_OFFSET, + SI_CRTC2_REGISTER_OFFSET, + SI_CRTC3_REGISTER_OFFSET, + SI_CRTC4_REGISTER_OFFSET, + SI_CRTC5_REGISTER_OFFSET +}; + +static void gmc_v6_0_mc_stop(struct amdgpu_device *adev, + struct amdgpu_mode_mc_save *save) +{ + u32 blackout; + + if (adev->mode_info.num_crtc) + amdgpu_display_stop_mc_access(adev, save); + + gmc_v6_0_wait_for_idle((void *)adev); + + blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); + if (REG_GET_FIELD(blackout, mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE) != 1) { + /* Block CPU access */ + WREG32(BIF_FB_EN, 0); + /* blackout the MC */ + blackout = REG_SET_FIELD(blackout, + mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE, 0); + WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); + } + /* wait for the MC to settle */ + udelay(100); + +} + +static void gmc_v6_0_mc_resume(struct amdgpu_device *adev, + struct amdgpu_mode_mc_save *save) +{ + u32 tmp; + + /* unblackout the MC */ + tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); + tmp = REG_SET_FIELD(tmp, mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE, 0); + WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); + /* allow CPU access */ + tmp = REG_SET_FIELD(0, mmBIF_FB_EN, xxFB_READ_EN, 1); + tmp = REG_SET_FIELD(tmp, mmBIF_FB_EN, xxFB_WRITE_EN, 1); + WREG32(BIF_FB_EN, tmp); + + if (adev->mode_info.num_crtc) + amdgpu_display_resume_mc_access(adev, save); + +} + +static int gmc_v6_0_init_microcode(struct amdgpu_device *adev) +{ + const char *chip_name; + char fw_name[30]; + int err; + + DRM_DEBUG("\n"); + + switch (adev->asic_type) { + case CHIP_TAHITI: + chip_name = "tahiti"; + break; + case CHIP_PITCAIRN: + chip_name = "pitcairn"; + break; + case CHIP_VERDE: + chip_name = "verde"; + break; + case CHIP_OLAND: + chip_name = "oland"; + break; + case CHIP_HAINAN: + chip_name = "hainan"; + break; + default: BUG(); + } + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + err = request_firmware(&adev->mc.fw, fw_name, adev->dev); + if (err) + goto out; + + err = amdgpu_ucode_validate(adev->mc.fw); + +out: + if (err) { + printk(KERN_ERR + "si_mc: Failed to load firmware \"%s\"\n", + fw_name); + release_firmware(adev->mc.fw); + adev->mc.fw = NULL; + } + return err; +} + +static int gmc_v6_0_mc_load_microcode(struct amdgpu_device *adev) +{ + const __le32 *new_fw_data = NULL; + u32 running; + const __le32 *new_io_mc_regs = NULL; + int i, regs_size, ucode_size; + const struct mc_firmware_header_v1_0 *hdr; + + if (!adev->mc.fw) + return -EINVAL; + + hdr = (const struct mc_firmware_header_v1_0 *)adev->mc.fw->data; + + amdgpu_ucode_print_mc_hdr(&hdr->header); + + adev->mc.fw_version = le32_to_cpu(hdr->header.ucode_version); + regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2); + new_io_mc_regs = (const __le32 *) + (adev->mc.fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes)); + ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; + new_fw_data = (const __le32 *) + (adev->mc.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + + running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; + + if (running == 0) { + + /* reset the engine and set to writable */ + WREG32(MC_SEQ_SUP_CNTL, 0x00000008); + WREG32(MC_SEQ_SUP_CNTL, 0x00000010); + + /* load mc io regs */ + for (i = 0; i < regs_size; i++) { + WREG32(MC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++)); + WREG32(MC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++)); + } + /* load the MC ucode */ + for (i = 0; i < ucode_size; i++) { + WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++)); + } + + /* put the engine back into the active state */ + WREG32(MC_SEQ_SUP_CNTL, 0x00000008); + WREG32(MC_SEQ_SUP_CNTL, 0x00000004); + WREG32(MC_SEQ_SUP_CNTL, 0x00000001); + + /* wait for training to complete */ + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D0) + break; + udelay(1); + } + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D1) + break; + udelay(1); + } + + } + + return 0; +} + +static void gmc_v6_0_vram_gtt_location(struct amdgpu_device *adev, + struct amdgpu_mc *mc) +{ + if (mc->mc_vram_size > 0xFFC0000000ULL) { + dev_warn(adev->dev, "limiting VRAM\n"); + mc->real_vram_size = 0xFFC0000000ULL; + mc->mc_vram_size = 0xFFC0000000ULL; + } + amdgpu_vram_location(adev, &adev->mc, 0); + adev->mc.gtt_base_align = 0; + amdgpu_gtt_location(adev, mc); +} + +static void gmc_v6_0_mc_program(struct amdgpu_device *adev) +{ + struct amdgpu_mode_mc_save save; + u32 tmp; + int i, j; + + /* Initialize HDP */ + for (i = 0, j = 0; i < 32; i++, j += 0x6) { + WREG32((0xb05 + j), 0x00000000); + WREG32((0xb06 + j), 0x00000000); + WREG32((0xb07 + j), 0x00000000); + WREG32((0xb08 + j), 0x00000000); + WREG32((0xb09 + j), 0x00000000); + } + WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0); + + gmc_v6_0_mc_stop(adev, &save); + + if (gmc_v6_0_wait_for_idle((void *)adev)) { + dev_warn(adev->dev, "Wait for MC idle timedout !\n"); + } + + WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); + /* Update configuration */ + WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + adev->mc.vram_start >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + adev->mc.vram_end >> 12); + WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, + adev->vram_scratch.gpu_addr >> 12); + tmp = ((adev->mc.vram_end >> 24) & 0xFFFF) << 16; + tmp |= ((adev->mc.vram_start >> 24) & 0xFFFF); + WREG32(MC_VM_FB_LOCATION, tmp); + /* XXX double check these! */ + WREG32(HDP_NONSURFACE_BASE, (adev->mc.vram_start >> 8)); + WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); + WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); + WREG32(MC_VM_AGP_BASE, 0); + WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); + WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); + + if (gmc_v6_0_wait_for_idle((void *)adev)) { + dev_warn(adev->dev, "Wait for MC idle timedout !\n"); + } + gmc_v6_0_mc_resume(adev, &save); + amdgpu_display_set_vga_render_state(adev, false); +} + +static int gmc_v6_0_mc_init(struct amdgpu_device *adev) +{ + + u32 tmp; + int chansize, numchan; + + tmp = RREG32(MC_ARB_RAMCFG); + if (tmp & CHANSIZE_OVERRIDE) { + chansize = 16; + } else if (tmp & CHANSIZE_MASK) { + chansize = 64; + } else { + chansize = 32; + } + tmp = RREG32(MC_SHARED_CHMAP); + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + default: + numchan = 1; + break; + case 1: + numchan = 2; + break; + case 2: + numchan = 4; + break; + case 3: + numchan = 8; + break; + case 4: + numchan = 3; + break; + case 5: + numchan = 6; + break; + case 6: + numchan = 10; + break; + case 7: + numchan = 12; + break; + case 8: + numchan = 16; + break; + } + adev->mc.vram_width = numchan * chansize; + /* Could aper size report 0 ? */ + adev->mc.aper_base = pci_resource_start(adev->pdev, 0); + adev->mc.aper_size = pci_resource_len(adev->pdev, 0); + /* size in MB on si */ + adev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; + adev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; + adev->mc.visible_vram_size = adev->mc.aper_size; + + /* unless the user had overridden it, set the gart + * size equal to the 1024 or vram, whichever is larger. + */ + if (amdgpu_gart_size == -1) + adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev); + else + adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; + + gmc_v6_0_vram_gtt_location(adev, &adev->mc); + + return 0; +} + +static void gmc_v6_0_gart_flush_gpu_tlb(struct amdgpu_device *adev, + uint32_t vmid) +{ + WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0); + + WREG32(VM_INVALIDATE_REQUEST, 1 << vmid); +} + +static int gmc_v6_0_gart_set_pte_pde(struct amdgpu_device *adev, + void *cpu_pt_addr, + uint32_t gpu_page_idx, + uint64_t addr, + uint32_t flags) +{ + void __iomem *ptr = (void *)cpu_pt_addr; + uint64_t value; + + value = addr & 0xFFFFFFFFFFFFF000ULL; + value |= flags; + writeq(value, ptr + (gpu_page_idx * 8)); + + return 0; +} + +static void gmc_v6_0_set_fault_enable_default(struct amdgpu_device *adev, + bool value) +{ + u32 tmp; + + tmp = RREG32(VM_CONTEXT1_CNTL); + tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL, + xxRANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value); + tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL, + xxDUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value); + tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL, + xxPDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value); + tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL, + xxVALID_PROTECTION_FAULT_ENABLE_DEFAULT, value); + tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL, + xxREAD_PROTECTION_FAULT_ENABLE_DEFAULT, value); + tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL, + xxWRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); + WREG32(VM_CONTEXT1_CNTL, tmp); +} + +static int gmc_v6_0_gart_enable(struct amdgpu_device *adev) +{ + int r, i; + + if (adev->gart.robj == NULL) { + dev_err(adev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; + } + r = amdgpu_gart_table_vram_pin(adev); + if (r) + return r; + /* Setup TLB control */ + WREG32(MC_VM_MX_L1_TLB_CNTL, + (0xA << 7) | + ENABLE_L1_TLB | + ENABLE_L1_FRAGMENT_PROCESSING | + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + ENABLE_ADVANCED_DRIVER_MODEL | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | + ENABLE_L2_FRAGMENT_PROCESSING | + ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7) | + CONTEXT1_IDENTITY_ACCESS_MODE(1)); + WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); + WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | + BANK_SELECT(4) | + L2_CACHE_BIGK_FRAGMENT_SIZE(4)); + /* setup context0 */ + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12); + WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(adev->dummy_page.addr >> 12)); + WREG32(VM_CONTEXT0_CNTL2, 0); + WREG32(VM_CONTEXT0_CNTL, (ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT)); + + WREG32(0x575, 0); + WREG32(0x576, 0); + WREG32(0x577, 0); + + /* empty context1-15 */ + /* set vm size, must be a multiple of 4 */ + WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); + WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, adev->vm_manager.max_pfn - 1); + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c + */ + for (i = 1; i < 16; i++) { + if (i < 8) + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i, + adev->gart.table_addr >> 12); + else + WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + i - 8, + adev->gart.table_addr >> 12); + } + + /* enable context1-15 */ + WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(adev->dummy_page.addr >> 12)); + WREG32(VM_CONTEXT1_CNTL2, 4); + WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | + PAGE_TABLE_BLOCK_SIZE(amdgpu_vm_block_size - 9) | + RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | + RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | + DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | + DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | + PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | + PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | + VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | + VALID_PROTECTION_FAULT_ENABLE_DEFAULT | + READ_PROTECTION_FAULT_ENABLE_INTERRUPT | + READ_PROTECTION_FAULT_ENABLE_DEFAULT | + WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | + WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); + + gmc_v6_0_gart_flush_gpu_tlb(adev, 0); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + (unsigned)(adev->mc.gtt_size >> 20), + (unsigned long long)adev->gart.table_addr); + adev->gart.ready = true; + return 0; +} + +static int gmc_v6_0_gart_init(struct amdgpu_device *adev) +{ + int r; + + if (adev->gart.robj) { + WARN(1, "gmc_v6_0 PCIE GART already initialized\n"); + return 0; + } + r = amdgpu_gart_init(adev); + if (r) + return r; + adev->gart.table_size = adev->gart.num_gpu_pages * 8; + return amdgpu_gart_table_vram_alloc(adev); +} + +static void gmc_v6_0_gart_disable(struct amdgpu_device *adev) +{ + /*unsigned i; + + for (i = 1; i < 16; ++i) { + uint32_t reg; + if (i < 8) + reg = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i ; + else + reg = VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + (i - 8); + adev->vm_manager.saved_table_addr[i] = RREG32(reg); + }*/ + + /* Disable all tables */ + WREG32(VM_CONTEXT0_CNTL, 0); + WREG32(VM_CONTEXT1_CNTL, 0); + /* Setup TLB control */ + WREG32(MC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); + /* Setup L2 cache */ + WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | + ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | + EFFECTIVE_L2_QUEUE_SIZE(7) | + CONTEXT1_IDENTITY_ACCESS_MODE(1)); + WREG32(VM_L2_CNTL2, 0); + WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | + L2_CACHE_BIGK_FRAGMENT_SIZE(0)); + amdgpu_gart_table_vram_unpin(adev); +} + +static void gmc_v6_0_gart_fini(struct amdgpu_device *adev) +{ + amdgpu_gart_table_vram_free(adev); + amdgpu_gart_fini(adev); +} + +static int gmc_v6_0_vm_init(struct amdgpu_device *adev) +{ + /* + * number of VMs + * VMID 0 is reserved for System + * amdgpu graphics/compute will use VMIDs 1-7 + * amdkfd will use VMIDs 8-15 + */ + adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS; + amdgpu_vm_manager_init(adev); + + /* base offset of vram pages */ + if (adev->flags & AMD_IS_APU) { + u64 tmp = RREG32(MC_VM_FB_OFFSET); + tmp <<= 22; + adev->vm_manager.vram_base_offset = tmp; + } else + adev->vm_manager.vram_base_offset = 0; + + return 0; +} + +static void gmc_v6_0_vm_fini(struct amdgpu_device *adev) +{ +} + +static void gmc_v6_0_vm_decode_fault(struct amdgpu_device *adev, + u32 status, u32 addr, u32 mc_client) +{ + u32 mc_id; + u32 vmid = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS, xxVMID); + u32 protections = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS, + xxPROTECTIONS); + char block[5] = { mc_client >> 24, (mc_client >> 16) & 0xff, + (mc_client >> 8) & 0xff, mc_client & 0xff, 0 }; + + mc_id = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS, + xxMEMORY_CLIENT_ID); + + printk("VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n", + protections, vmid, addr, + REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS, + xxMEMORY_CLIENT_RW) ? + "write" : "read", block, mc_client, mc_id); +} + +/* +static const u32 mc_cg_registers[] = { + MC_HUB_MISC_HUB_CG, + MC_HUB_MISC_SIP_CG, + MC_HUB_MISC_VM_CG, + MC_XPB_CLK_GAT, + ATC_MISC_CG, + MC_CITF_MISC_WR_CG, + MC_CITF_MISC_RD_CG, + MC_CITF_MISC_VM_CG, + VM_L2_CG, +}; + +static const u32 mc_cg_ls_en[] = { + MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE_MASK, + MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE_MASK, + MC_HUB_MISC_VM_CG__MEM_LS_ENABLE_MASK, + MC_XPB_CLK_GAT__MEM_LS_ENABLE_MASK, + ATC_MISC_CG__MEM_LS_ENABLE_MASK, + MC_CITF_MISC_WR_CG__MEM_LS_ENABLE_MASK, + MC_CITF_MISC_RD_CG__MEM_LS_ENABLE_MASK, + MC_CITF_MISC_VM_CG__MEM_LS_ENABLE_MASK, + VM_L2_CG__MEM_LS_ENABLE_MASK, +}; + +static const u32 mc_cg_en[] = { + MC_HUB_MISC_HUB_CG__ENABLE_MASK, + MC_HUB_MISC_SIP_CG__ENABLE_MASK, + MC_HUB_MISC_VM_CG__ENABLE_MASK, + MC_XPB_CLK_GAT__ENABLE_MASK, + ATC_MISC_CG__ENABLE_MASK, + MC_CITF_MISC_WR_CG__ENABLE_MASK, + MC_CITF_MISC_RD_CG__ENABLE_MASK, + MC_CITF_MISC_VM_CG__ENABLE_MASK, + VM_L2_CG__ENABLE_MASK, +}; + +static void gmc_v6_0_enable_mc_ls(struct amdgpu_device *adev, + bool enable) +{ + int i; + u32 orig, data; + + for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) { + orig = data = RREG32(mc_cg_registers[i]); + if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_MC_LS)) + data |= mc_cg_ls_en[i]; + else + data &= ~mc_cg_ls_en[i]; + if (data != orig) + WREG32(mc_cg_registers[i], data); + } +} + +static void gmc_v6_0_enable_mc_mgcg(struct amdgpu_device *adev, + bool enable) +{ + int i; + u32 orig, data; + + for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) { + orig = data = RREG32(mc_cg_registers[i]); + if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_MC_MGCG)) + data |= mc_cg_en[i]; + else + data &= ~mc_cg_en[i]; + if (data != orig) + WREG32(mc_cg_registers[i], data); + } +} + +static void gmc_v6_0_enable_bif_mgls(struct amdgpu_device *adev, + bool enable) +{ + u32 orig, data; + + orig = data = RREG32_PCIE(ixPCIE_CNTL2); + + if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_BIF_LS)) { + data = REG_SET_FIELD(data, PCIE_CNTL2, SLV_MEM_LS_EN, 1); + data = REG_SET_FIELD(data, PCIE_CNTL2, MST_MEM_LS_EN, 1); + data = REG_SET_FIELD(data, PCIE_CNTL2, REPLAY_MEM_LS_EN, 1); + data = REG_SET_FIELD(data, PCIE_CNTL2, SLV_MEM_AGGRESSIVE_LS_EN, 1); + } else { + data = REG_SET_FIELD(data, PCIE_CNTL2, SLV_MEM_LS_EN, 0); + data = REG_SET_FIELD(data, PCIE_CNTL2, MST_MEM_LS_EN, 0); + data = REG_SET_FIELD(data, PCIE_CNTL2, REPLAY_MEM_LS_EN, 0); + data = REG_SET_FIELD(data, PCIE_CNTL2, SLV_MEM_AGGRESSIVE_LS_EN, 0); + } + + if (orig != data) + WREG32_PCIE(ixPCIE_CNTL2, data); +} + +static void gmc_v6_0_enable_hdp_mgcg(struct amdgpu_device *adev, + bool enable) +{ + u32 orig, data; + + orig = data = RREG32(HDP_HOST_PATH_CNTL); + + if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_HDP_MGCG)) + data = REG_SET_FIELD(data, HDP_HOST_PATH_CNTL, CLOCK_GATING_DIS, 0); + else + data = REG_SET_FIELD(data, HDP_HOST_PATH_CNTL, CLOCK_GATING_DIS, 1); + + if (orig != data) + WREG32(HDP_HOST_PATH_CNTL, data); +} + +static void gmc_v6_0_enable_hdp_ls(struct amdgpu_device *adev, + bool enable) +{ + u32 orig, data; + + orig = data = RREG32(HDP_MEM_POWER_LS); + + if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_HDP_LS)) + data = REG_SET_FIELD(data, HDP_MEM_POWER_LS, LS_ENABLE, 1); + else + data = REG_SET_FIELD(data, HDP_MEM_POWER_LS, LS_ENABLE, 0); + + if (orig != data) + WREG32(HDP_MEM_POWER_LS, data); +} +*/ + +static int gmc_v6_0_convert_vram_type(int mc_seq_vram_type) +{ + switch (mc_seq_vram_type) { + case MC_SEQ_MISC0__MT__GDDR1: + return AMDGPU_VRAM_TYPE_GDDR1; + case MC_SEQ_MISC0__MT__DDR2: + return AMDGPU_VRAM_TYPE_DDR2; + case MC_SEQ_MISC0__MT__GDDR3: + return AMDGPU_VRAM_TYPE_GDDR3; + case MC_SEQ_MISC0__MT__GDDR4: + return AMDGPU_VRAM_TYPE_GDDR4; + case MC_SEQ_MISC0__MT__GDDR5: + return AMDGPU_VRAM_TYPE_GDDR5; + case MC_SEQ_MISC0__MT__DDR3: + return AMDGPU_VRAM_TYPE_DDR3; + default: + return AMDGPU_VRAM_TYPE_UNKNOWN; + } +} + +static int gmc_v6_0_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + gmc_v6_0_set_gart_funcs(adev); + gmc_v6_0_set_irq_funcs(adev); + + if (adev->flags & AMD_IS_APU) { + adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN; + } else { + u32 tmp = RREG32(MC_SEQ_MISC0); + tmp &= MC_SEQ_MISC0__MT__MASK; + adev->mc.vram_type = gmc_v6_0_convert_vram_type(tmp); + } + + return 0; +} + +static int gmc_v6_0_late_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0); +} + +static int gmc_v6_0_sw_init(void *handle) +{ + int r; + int dma_bits; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + r = amdgpu_irq_add_id(adev, 146, &adev->mc.vm_fault); + if (r) + return r; + + r = amdgpu_irq_add_id(adev, 147, &adev->mc.vm_fault); + if (r) + return r; + + adev->vm_manager.max_pfn = amdgpu_vm_size << 18; + + adev->mc.mc_mask = 0xffffffffffULL; + + adev->need_dma32 = false; + dma_bits = adev->need_dma32 ? 32 : 40; + r = pci_set_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits)); + if (r) { + adev->need_dma32 = true; + dma_bits = 32; + printk(KERN_WARNING "amdgpu: No suitable DMA available.\n"); + } + r = pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits)); + if (r) { + pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32)); + printk(KERN_WARNING "amdgpu: No coherent DMA available.\n"); + } + + r = gmc_v6_0_init_microcode(adev); + if (r) { + DRM_ERROR("Failed to load mc firmware!\n"); + return r; + } + + r = amdgpu_ttm_global_init(adev); + if (r) { + return r; + } + + r = gmc_v6_0_mc_init(adev); + if (r) + return r; + + r = amdgpu_bo_init(adev); + if (r) + return r; + + r = gmc_v6_0_gart_init(adev); + if (r) + return r; + + if (!adev->vm_manager.enabled) { + r = gmc_v6_0_vm_init(adev); + if (r) { + dev_err(adev->dev, "vm manager initialization failed (%d).\n", r); + return r; + } + adev->vm_manager.enabled = true; + } + + return r; +} + +static int gmc_v6_0_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->vm_manager.enabled) { + gmc_v6_0_vm_fini(adev); + adev->vm_manager.enabled = false; + } + gmc_v6_0_gart_fini(adev); + amdgpu_gem_force_release(adev); + amdgpu_bo_fini(adev); + + return 0; +} + +static int gmc_v6_0_hw_init(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + gmc_v6_0_mc_program(adev); + + if (!(adev->flags & AMD_IS_APU)) { + r = gmc_v6_0_mc_load_microcode(adev); + if (r) { + DRM_ERROR("Failed to load MC firmware!\n"); + return r; + } + } + + r = gmc_v6_0_gart_enable(adev); + if (r) + return r; + + return r; +} + +static int gmc_v6_0_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_irq_put(adev, &adev->mc.vm_fault, 0); + gmc_v6_0_gart_disable(adev); + + return 0; +} + +static int gmc_v6_0_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->vm_manager.enabled) { + gmc_v6_0_vm_fini(adev); + adev->vm_manager.enabled = false; + } + gmc_v6_0_hw_fini(adev); + + return 0; +} + +static int gmc_v6_0_resume(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + r = gmc_v6_0_hw_init(adev); + if (r) + return r; + + if (!adev->vm_manager.enabled) { + r = gmc_v6_0_vm_init(adev); + if (r) { + dev_err(adev->dev, "vm manager initialization failed (%d).\n", r); + return r; + } + adev->vm_manager.enabled = true; + } + + return r; +} + +static bool gmc_v6_0_is_idle(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + u32 tmp = RREG32(SRBM_STATUS); + + if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK | + SRBM_STATUS__MCC_BUSY_MASK | SRBM_STATUS__MCD_BUSY_MASK | SRBM_STATUS__VMC_BUSY_MASK)) + return false; + + return true; +} + +static int gmc_v6_0_wait_for_idle(void *handle) +{ + unsigned i; + u32 tmp; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(SRBM_STATUS) & (SRBM_STATUS__MCB_BUSY_MASK | + SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK | + SRBM_STATUS__MCC_BUSY_MASK | + SRBM_STATUS__MCD_BUSY_MASK | + SRBM_STATUS__VMC_BUSY_MASK); + if (!tmp) + return 0; + udelay(1); + } + return -ETIMEDOUT; + +} + +static int gmc_v6_0_soft_reset(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_mode_mc_save save; + u32 srbm_soft_reset = 0; + u32 tmp = RREG32(SRBM_STATUS); + + if (tmp & SRBM_STATUS__VMC_BUSY_MASK) + srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, + mmSRBM_SOFT_RESET, xxSOFT_RESET_VMC, 1); + + if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK | + SRBM_STATUS__MCC_BUSY_MASK | SRBM_STATUS__MCD_BUSY_MASK)) { + if (!(adev->flags & AMD_IS_APU)) + srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, + mmSRBM_SOFT_RESET, xxSOFT_RESET_MC, 1); + } + + if (srbm_soft_reset) { + gmc_v6_0_mc_stop(adev, &save); + if (gmc_v6_0_wait_for_idle(adev)) { + dev_warn(adev->dev, "Wait for GMC idle timed out !\n"); + } + + + tmp = RREG32(SRBM_SOFT_RESET); + tmp |= srbm_soft_reset; + dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(SRBM_SOFT_RESET, tmp); + tmp = RREG32(SRBM_SOFT_RESET); + + udelay(50); + + tmp &= ~srbm_soft_reset; + WREG32(SRBM_SOFT_RESET, tmp); + tmp = RREG32(SRBM_SOFT_RESET); + + udelay(50); + + gmc_v6_0_mc_resume(adev, &save); + udelay(50); + } + + return 0; +} + +static int gmc_v6_0_vm_fault_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 tmp; + u32 bits = (VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK); + + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + tmp = RREG32(VM_CONTEXT0_CNTL); + tmp &= ~bits; + WREG32(VM_CONTEXT0_CNTL, tmp); + tmp = RREG32(VM_CONTEXT1_CNTL); + tmp &= ~bits; + WREG32(VM_CONTEXT1_CNTL, tmp); + break; + case AMDGPU_IRQ_STATE_ENABLE: + tmp = RREG32(VM_CONTEXT0_CNTL); + tmp |= bits; + WREG32(VM_CONTEXT0_CNTL, tmp); + tmp = RREG32(VM_CONTEXT1_CNTL); + tmp |= bits; + WREG32(VM_CONTEXT1_CNTL, tmp); + break; + default: + break; + } + + return 0; +} + +static int gmc_v6_0_process_interrupt(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + u32 addr, status; + + addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR); + status = RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS); + WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); + + if (!addr && !status) + return 0; + + if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST) + gmc_v6_0_set_fault_enable_default(adev, false); + + dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n", + entry->src_id, entry->src_data); + dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", + addr); + dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", + status); + gmc_v6_0_vm_decode_fault(adev, status, addr, 0); + + return 0; +} + +static int gmc_v6_0_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int gmc_v6_0_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +const struct amd_ip_funcs gmc_v6_0_ip_funcs = { + .name = "gmc_v6_0", + .early_init = gmc_v6_0_early_init, + .late_init = gmc_v6_0_late_init, + .sw_init = gmc_v6_0_sw_init, + .sw_fini = gmc_v6_0_sw_fini, + .hw_init = gmc_v6_0_hw_init, + .hw_fini = gmc_v6_0_hw_fini, + .suspend = gmc_v6_0_suspend, + .resume = gmc_v6_0_resume, + .is_idle = gmc_v6_0_is_idle, + .wait_for_idle = gmc_v6_0_wait_for_idle, + .soft_reset = gmc_v6_0_soft_reset, + .set_clockgating_state = gmc_v6_0_set_clockgating_state, + .set_powergating_state = gmc_v6_0_set_powergating_state, +}; + +static const struct amdgpu_gart_funcs gmc_v6_0_gart_funcs = { + .flush_gpu_tlb = gmc_v6_0_gart_flush_gpu_tlb, + .set_pte_pde = gmc_v6_0_gart_set_pte_pde, +}; + +static const struct amdgpu_irq_src_funcs gmc_v6_0_irq_funcs = { + .set = gmc_v6_0_vm_fault_interrupt_state, + .process = gmc_v6_0_process_interrupt, +}; + +static void gmc_v6_0_set_gart_funcs(struct amdgpu_device *adev) +{ + if (adev->gart.gart_funcs == NULL) + adev->gart.gart_funcs = &gmc_v6_0_gart_funcs; +} + +static void gmc_v6_0_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->mc.vm_fault.num_types = 1; + adev->mc.vm_fault.funcs = &gmc_v6_0_irq_funcs; +} + diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h new file mode 100644 index 0000000..42c4fc6 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h @@ -0,0 +1,29 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __GMC_V6_0_H__ +#define __GMC_V6_0_H__ + +extern const struct amd_ip_funcs gmc_v6_0_ip_funcs; + +#endif -- cgit v1.1 From 27ae10641e9c99f32db004cc54cb0639cd58d6d1 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 14:02:14 +0800 Subject: drm/amdgpu: add interupt handler implementation for si v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v3: rebase fixups Reviewed-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_ih.c | 313 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/si_ih.h | 29 ++++ 2 files changed, 342 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/si_ih.c create mode 100644 drivers/gpu/drm/amd/amdgpu/si_ih.h diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c new file mode 100644 index 0000000..994ff02 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c @@ -0,0 +1,313 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "drmP.h" +#include "amdgpu.h" +#include "amdgpu_ih.h" +#include "si/sid.h" +#include "si_ih.h" + +static void si_ih_set_interrupt_funcs(struct amdgpu_device *adev); + +static void si_ih_enable_interrupts(struct amdgpu_device *adev) +{ + u32 ih_cntl = RREG32(IH_CNTL); + u32 ih_rb_cntl = RREG32(IH_RB_CNTL); + + ih_cntl |= ENABLE_INTR; + ih_rb_cntl |= IH_RB_ENABLE; + WREG32(IH_CNTL, ih_cntl); + WREG32(IH_RB_CNTL, ih_rb_cntl); + adev->irq.ih.enabled = true; +} + +static void si_ih_disable_interrupts(struct amdgpu_device *adev) +{ + u32 ih_rb_cntl = RREG32(IH_RB_CNTL); + u32 ih_cntl = RREG32(IH_CNTL); + + ih_rb_cntl &= ~IH_RB_ENABLE; + ih_cntl &= ~ENABLE_INTR; + WREG32(IH_RB_CNTL, ih_rb_cntl); + WREG32(IH_CNTL, ih_cntl); + WREG32(IH_RB_RPTR, 0); + WREG32(IH_RB_WPTR, 0); + adev->irq.ih.enabled = false; + adev->irq.ih.rptr = 0; +} + +static int si_ih_irq_init(struct amdgpu_device *adev) +{ + int ret = 0; + int rb_bufsz; + u32 interrupt_cntl, ih_cntl, ih_rb_cntl; + u64 wptr_off; + + si_ih_disable_interrupts(adev); + WREG32(INTERRUPT_CNTL2, adev->irq.ih.gpu_addr >> 8); + interrupt_cntl = RREG32(INTERRUPT_CNTL); + interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; + interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; + WREG32(INTERRUPT_CNTL, interrupt_cntl); + + WREG32(IH_RB_BASE, adev->irq.ih.gpu_addr >> 8); + rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4); + + ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | + IH_WPTR_OVERFLOW_CLEAR | + (rb_bufsz << 1)); + + ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; + + wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); + WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); + WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); + + WREG32(IH_RB_CNTL, ih_rb_cntl); + + WREG32(IH_RB_RPTR, 0); + WREG32(IH_RB_WPTR, 0); + + ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10) | MC_VMID(0); + if (adev->irq.msi_enabled) + ih_cntl |= RPTR_REARM; + WREG32(IH_CNTL, ih_cntl); + + pci_set_master(adev->pdev); + + si_ih_enable_interrupts(adev); + + return ret; +} + +static void si_ih_irq_disable(struct amdgpu_device *adev) +{ + si_ih_disable_interrupts(adev); + mdelay(1); +} + +static u32 si_ih_get_wptr(struct amdgpu_device *adev) +{ + u32 wptr, tmp; + + wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]); + + if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) { + wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK; + dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", + wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask); + adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask; + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; + WREG32(IH_RB_CNTL, tmp); + } + return (wptr & adev->irq.ih.ptr_mask); +} + +static void si_ih_decode_iv(struct amdgpu_device *adev, + struct amdgpu_iv_entry *entry) +{ + u32 ring_index = adev->irq.ih.rptr >> 2; + uint32_t dw[4]; + + dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); + dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]); + dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]); + dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); + + entry->src_id = dw[0] & 0xff; + entry->src_data = dw[1] & 0xfffffff; + entry->ring_id = dw[2] & 0xff; + entry->vm_id = (dw[2] >> 8) & 0xff; + + adev->irq.ih.rptr += 16; +} + +static void si_ih_set_rptr(struct amdgpu_device *adev) +{ + WREG32(IH_RB_RPTR, adev->irq.ih.rptr); +} + +static int si_ih_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + si_ih_set_interrupt_funcs(adev); + + return 0; +} + +static int si_ih_sw_init(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + r = amdgpu_ih_ring_init(adev, 64 * 1024, false); + if (r) + return r; + + r = amdgpu_irq_init(adev); + + return r; +} + +static int si_ih_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_irq_fini(adev); + amdgpu_ih_ring_fini(adev); + + return 0; +} + +static int si_ih_hw_init(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + r = si_ih_irq_init(adev); + if (r) + return r; + + return 0; +} + +static int si_ih_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + si_ih_irq_disable(adev); + + return 0; +} + +static int si_ih_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return si_ih_hw_fini(adev); +} + +static int si_ih_resume(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return si_ih_hw_init(adev); +} + +static bool si_ih_is_idle(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + u32 tmp = RREG32(SRBM_STATUS); + + if (tmp & SRBM_STATUS__IH_BUSY_MASK) + return false; + + return true; +} + +static int si_ih_wait_for_idle(void *handle) +{ + unsigned i; + u32 tmp; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(SRBM_STATUS) & SRBM_STATUS__IH_BUSY_MASK; + if (!tmp) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int si_ih_soft_reset(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + u32 srbm_soft_reset = 0; + u32 tmp = RREG32(SRBM_STATUS); + + if (tmp & SRBM_STATUS__IH_BUSY_MASK) + srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_IH_MASK; + + if (srbm_soft_reset) { + tmp = RREG32(SRBM_SOFT_RESET); + tmp |= srbm_soft_reset; + dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(SRBM_SOFT_RESET, tmp); + tmp = RREG32(SRBM_SOFT_RESET); + + udelay(50); + + tmp &= ~srbm_soft_reset; + WREG32(SRBM_SOFT_RESET, tmp); + tmp = RREG32(SRBM_SOFT_RESET); + + udelay(50); + } + + return 0; +} + +static int si_ih_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int si_ih_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +const struct amd_ip_funcs si_ih_ip_funcs = { + .name = "si_ih", + .early_init = si_ih_early_init, + .late_init = NULL, + .sw_init = si_ih_sw_init, + .sw_fini = si_ih_sw_fini, + .hw_init = si_ih_hw_init, + .hw_fini = si_ih_hw_fini, + .suspend = si_ih_suspend, + .resume = si_ih_resume, + .is_idle = si_ih_is_idle, + .wait_for_idle = si_ih_wait_for_idle, + .soft_reset = si_ih_soft_reset, + .set_clockgating_state = si_ih_set_clockgating_state, + .set_powergating_state = si_ih_set_powergating_state, +}; + +static const struct amdgpu_ih_funcs si_ih_funcs = { + .get_wptr = si_ih_get_wptr, + .decode_iv = si_ih_decode_iv, + .set_rptr = si_ih_set_rptr +}; + +static void si_ih_set_interrupt_funcs(struct amdgpu_device *adev) +{ + if (adev->irq.ih_funcs == NULL) + adev->irq.ih_funcs = &si_ih_funcs; +} + diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.h b/drivers/gpu/drm/amd/amdgpu/si_ih.h new file mode 100644 index 0000000..f3e3a95 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si_ih.h @@ -0,0 +1,29 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __SI_IH_H__ +#define __SI_IH_H__ + +extern const struct amd_ip_funcs si_ih_ip_funcs; + +#endif -- cgit v1.1 From e2cdf640cbb5b7d6643e1c8ad54bf3bfc99d4d48 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 14:03:24 +0800 Subject: drm/amdgpu: add display controller implementation for si v10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v4: rebase fixups v5: more fixes based on dce8 code v6: squash in dmif offset fix v7: rebase fixups v8: rebase fixups, drop some debugging remnants v9: fix BE build v10: include Marek's tiling fixes, add support for page_flip_target, set MASTER_UDPATE_MODE=0, fix cursor Acked-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 3160 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/dce_v6_0.h | 29 + drivers/gpu/drm/amd/include/asic_reg/si/sid.h | 37 +- 3 files changed, 3193 insertions(+), 33 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/dce_v6_0.c create mode 100644 drivers/gpu/drm/amd/amdgpu/dce_v6_0.h diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c new file mode 100644 index 0000000..d3512f3 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -0,0 +1,3160 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "drmP.h" +#include "amdgpu.h" +#include "amdgpu_pm.h" +#include "amdgpu_i2c.h" +#include "atom.h" +#include "amdgpu_atombios.h" +#include "atombios_crtc.h" +#include "atombios_encoders.h" +#include "amdgpu_pll.h" +#include "amdgpu_connectors.h" +#include "si/si_reg.h" +#include "si/sid.h" + +static void dce_v6_0_set_display_funcs(struct amdgpu_device *adev); +static void dce_v6_0_set_irq_funcs(struct amdgpu_device *adev); + +static const u32 crtc_offsets[6] = +{ + SI_CRTC0_REGISTER_OFFSET, + SI_CRTC1_REGISTER_OFFSET, + SI_CRTC2_REGISTER_OFFSET, + SI_CRTC3_REGISTER_OFFSET, + SI_CRTC4_REGISTER_OFFSET, + SI_CRTC5_REGISTER_OFFSET +}; + +static const uint32_t dig_offsets[] = { + SI_CRTC0_REGISTER_OFFSET, + SI_CRTC1_REGISTER_OFFSET, + SI_CRTC2_REGISTER_OFFSET, + SI_CRTC3_REGISTER_OFFSET, + SI_CRTC4_REGISTER_OFFSET, + SI_CRTC5_REGISTER_OFFSET, + (0x13830 - 0x7030) >> 2, +}; + +static const struct { + uint32_t reg; + uint32_t vblank; + uint32_t vline; + uint32_t hpd; + +} interrupt_status_offsets[6] = { { + .reg = DISP_INTERRUPT_STATUS, + .vblank = DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT_MASK, + .vline = DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT_MASK, + .hpd = DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT_MASK +}, { + .reg = DISP_INTERRUPT_STATUS_CONTINUE, + .vblank = DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT_MASK, + .vline = DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT_MASK, + .hpd = DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT_MASK +}, { + .reg = DISP_INTERRUPT_STATUS_CONTINUE2, + .vblank = DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT_MASK, + .vline = DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT_MASK, + .hpd = DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT_MASK +}, { + .reg = DISP_INTERRUPT_STATUS_CONTINUE3, + .vblank = DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT_MASK, + .vline = DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT_MASK, + .hpd = DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT_MASK +}, { + .reg = DISP_INTERRUPT_STATUS_CONTINUE4, + .vblank = DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT_MASK, + .vline = DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT_MASK, + .hpd = DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT_MASK +}, { + .reg = DISP_INTERRUPT_STATUS_CONTINUE5, + .vblank = DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT_MASK, + .vline = DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT_MASK, + .hpd = DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK +} }; + +static const uint32_t hpd_int_control_offsets[6] = { + DC_HPD1_INT_CONTROL, + DC_HPD2_INT_CONTROL, + DC_HPD3_INT_CONTROL, + DC_HPD4_INT_CONTROL, + DC_HPD5_INT_CONTROL, + DC_HPD6_INT_CONTROL, +}; + +static u32 dce_v6_0_audio_endpt_rreg(struct amdgpu_device *adev, + u32 block_offset, u32 reg) +{ + DRM_INFO("xxxx: dce_v6_0_audio_endpt_rreg ----no impl!!!!\n"); + return 0; +} + +static void dce_v6_0_audio_endpt_wreg(struct amdgpu_device *adev, + u32 block_offset, u32 reg, u32 v) +{ + DRM_INFO("xxxx: dce_v6_0_audio_endpt_wreg ----no impl!!!!\n"); +} + +static bool dce_v6_0_is_in_vblank(struct amdgpu_device *adev, int crtc) +{ + if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) + return true; + else + return false; +} + +static bool dce_v6_0_is_counter_moving(struct amdgpu_device *adev, int crtc) +{ + u32 pos1, pos2; + + pos1 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]); + pos2 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]); + + if (pos1 != pos2) + return true; + else + return false; +} + +/** + * dce_v6_0_wait_for_vblank - vblank wait asic callback. + * + * @crtc: crtc to wait for vblank on + * + * Wait for vblank on the requested crtc (evergreen+). + */ +static void dce_v6_0_vblank_wait(struct amdgpu_device *adev, int crtc) +{ + unsigned i = 0; + + if (crtc >= adev->mode_info.num_crtc) + return; + + if (!(RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN)) + return; + + /* depending on when we hit vblank, we may be close to active; if so, + * wait for another frame. + */ + while (dce_v6_0_is_in_vblank(adev, crtc)) { + if (i++ % 100 == 0) { + if (!dce_v6_0_is_counter_moving(adev, crtc)) + break; + } + } + + while (!dce_v6_0_is_in_vblank(adev, crtc)) { + if (i++ % 100 == 0) { + if (!dce_v6_0_is_counter_moving(adev, crtc)) + break; + } + } +} + +static u32 dce_v6_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) +{ + if (crtc >= adev->mode_info.num_crtc) + return 0; + else + return RREG32(CRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); +} + +static void dce_v6_0_pageflip_interrupt_init(struct amdgpu_device *adev) +{ + unsigned i; + + /* Enable pflip interrupts */ + for (i = 0; i <= adev->mode_info.num_crtc; i++) + amdgpu_irq_get(adev, &adev->pageflip_irq, i); +} + +static void dce_v6_0_pageflip_interrupt_fini(struct amdgpu_device *adev) +{ + unsigned i; + + /* Disable pflip interrupts */ + for (i = 0; i <= adev->mode_info.num_crtc; i++) + amdgpu_irq_put(adev, &adev->pageflip_irq, i); +} + +/** + * dce_v6_0_page_flip - pageflip callback. + * + * @adev: amdgpu_device pointer + * @crtc_id: crtc to cleanup pageflip on + * @crtc_base: new address of the crtc (GPU MC address) + * + * Does the actual pageflip (evergreen+). + * During vblank we take the crtc lock and wait for the update_pending + * bit to go high, when it does, we release the lock, and allow the + * double buffered update to take place. + * Returns the current update pending status. + */ +static void dce_v6_0_page_flip(struct amdgpu_device *adev, + int crtc_id, u64 crtc_base, bool async) +{ + struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; + + /* flip at hsync for async, default is vsync */ + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, async ? + EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0); + /* update the scanout addresses */ + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, + upper_32_bits(crtc_base)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset, + (u32)crtc_base); + + /* post the write */ + RREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset); +} + +static int dce_v6_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, + u32 *vbl, u32 *position) +{ + if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc)) + return -EINVAL; + *vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + crtc_offsets[crtc]); + *position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]); + + return 0; + +} + +/** + * dce_v6_0_hpd_sense - hpd sense callback. + * + * @adev: amdgpu_device pointer + * @hpd: hpd (hotplug detect) pin + * + * Checks if a digital monitor is connected (evergreen+). + * Returns true if connected, false if not connected. + */ +static bool dce_v6_0_hpd_sense(struct amdgpu_device *adev, + enum amdgpu_hpd_id hpd) +{ + bool connected = false; + + switch (hpd) { + case AMDGPU_HPD_1: + if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case AMDGPU_HPD_2: + if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case AMDGPU_HPD_3: + if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case AMDGPU_HPD_4: + if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case AMDGPU_HPD_5: + if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + case AMDGPU_HPD_6: + if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) + connected = true; + break; + default: + break; + } + + return connected; +} + +/** + * dce_v6_0_hpd_set_polarity - hpd set polarity callback. + * + * @adev: amdgpu_device pointer + * @hpd: hpd (hotplug detect) pin + * + * Set the polarity of the hpd pin (evergreen+). + */ +static void dce_v6_0_hpd_set_polarity(struct amdgpu_device *adev, + enum amdgpu_hpd_id hpd) +{ + u32 tmp; + bool connected = dce_v6_0_hpd_sense(adev, hpd); + + switch (hpd) { + case AMDGPU_HPD_1: + tmp = RREG32(DC_HPD1_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD1_INT_CONTROL, tmp); + break; + case AMDGPU_HPD_2: + tmp = RREG32(DC_HPD2_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD2_INT_CONTROL, tmp); + break; + case AMDGPU_HPD_3: + tmp = RREG32(DC_HPD3_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD3_INT_CONTROL, tmp); + break; + case AMDGPU_HPD_4: + tmp = RREG32(DC_HPD4_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD4_INT_CONTROL, tmp); + break; + case AMDGPU_HPD_5: + tmp = RREG32(DC_HPD5_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD5_INT_CONTROL, tmp); + break; + case AMDGPU_HPD_6: + tmp = RREG32(DC_HPD6_INT_CONTROL); + if (connected) + tmp &= ~DC_HPDx_INT_POLARITY; + else + tmp |= DC_HPDx_INT_POLARITY; + WREG32(DC_HPD6_INT_CONTROL, tmp); + break; + default: + break; + } +} + +/** + * dce_v6_0_hpd_init - hpd setup callback. + * + * @adev: amdgpu_device pointer + * + * Setup the hpd pins used by the card (evergreen+). + * Enable the pin, set the polarity, and enable the hpd interrupts. + */ +static void dce_v6_0_hpd_init(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_connector *connector; + u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | + DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || + connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { + /* don't try to enable hpd on eDP or LVDS avoid breaking the + * aux dp channel on imac and help (but not completely fix) + * https://bugzilla.redhat.com/show_bug.cgi?id=726143 + * also avoid interrupt storms during dpms. + */ + continue; + } + switch (amdgpu_connector->hpd.hpd) { + case AMDGPU_HPD_1: + WREG32(DC_HPD1_CONTROL, tmp); + break; + case AMDGPU_HPD_2: + WREG32(DC_HPD2_CONTROL, tmp); + break; + case AMDGPU_HPD_3: + WREG32(DC_HPD3_CONTROL, tmp); + break; + case AMDGPU_HPD_4: + WREG32(DC_HPD4_CONTROL, tmp); + break; + case AMDGPU_HPD_5: + WREG32(DC_HPD5_CONTROL, tmp); + break; + case AMDGPU_HPD_6: + WREG32(DC_HPD6_CONTROL, tmp); + break; + default: + break; + } + dce_v6_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd); + amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); + } + +} + +/** + * dce_v6_0_hpd_fini - hpd tear down callback. + * + * @adev: amdgpu_device pointer + * + * Tear down the hpd pins used by the card (evergreen+). + * Disable the hpd interrupts. + */ +static void dce_v6_0_hpd_fini(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + + switch (amdgpu_connector->hpd.hpd) { + case AMDGPU_HPD_1: + WREG32(DC_HPD1_CONTROL, 0); + break; + case AMDGPU_HPD_2: + WREG32(DC_HPD2_CONTROL, 0); + break; + case AMDGPU_HPD_3: + WREG32(DC_HPD3_CONTROL, 0); + break; + case AMDGPU_HPD_4: + WREG32(DC_HPD4_CONTROL, 0); + break; + case AMDGPU_HPD_5: + WREG32(DC_HPD5_CONTROL, 0); + break; + case AMDGPU_HPD_6: + WREG32(DC_HPD6_CONTROL, 0); + break; + default: + break; + } + amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd); + } +} + +static u32 dce_v6_0_hpd_get_gpio_reg(struct amdgpu_device *adev) +{ + return SI_DC_GPIO_HPD_A; +} + +static bool dce_v6_0_is_display_hung(struct amdgpu_device *adev) +{ + DRM_INFO("xxxx: dce_v6_0_is_display_hung ----no imp!!!!!\n"); + + return true; +} + +static u32 evergreen_get_vblank_counter(struct amdgpu_device* adev, int crtc) +{ + if (crtc >= adev->mode_info.num_crtc) + return 0; + else + return RREG32(CRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); +} + +static void dce_v6_0_stop_mc_access(struct amdgpu_device *adev, + struct amdgpu_mode_mc_save *save) +{ + u32 crtc_enabled, tmp, frame_count; + int i, j; + + save->vga_render_control = RREG32(VGA_RENDER_CONTROL); + save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); + + /* disable VGA render */ + WREG32(VGA_RENDER_CONTROL, 0); + + /* blank the display controllers */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; + if (crtc_enabled) { + save->crtc_enabled[i] = true; + tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); + + if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { + dce_v6_0_vblank_wait(adev, i); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + /* wait for the next frame */ + frame_count = evergreen_get_vblank_counter(adev, i); + for (j = 0; j < adev->usec_timeout; j++) { + if (evergreen_get_vblank_counter(adev, i) != frame_count) + break; + udelay(1); + } + + /* XXX this is a hack to avoid strange behavior with EFI on certain systems */ + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + tmp &= ~EVERGREEN_CRTC_MASTER_EN; + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + save->crtc_enabled[i] = false; + /* ***** */ + } else { + save->crtc_enabled[i] = false; + } + } +} + +static void dce_v6_0_resume_mc_access(struct amdgpu_device *adev, + struct amdgpu_mode_mc_save *save) +{ + u32 tmp; + int i, j; + + /* update crtc base addresses */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], + upper_32_bits(adev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], + upper_32_bits(adev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)adev->mc.vram_start); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], + (u32)adev->mc.vram_start); + } + + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start)); + WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)adev->mc.vram_start); + + /* unlock regs and wait for update */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (save->crtc_enabled[i]) { + tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]); + if ((tmp & 0x7) != 3) { + tmp &= ~0x7; + tmp |= 0x3; + WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp); + } + tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); + if (tmp & EVERGREEN_GRPH_UPDATE_LOCK) { + tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; + WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp); + } + tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]); + if (tmp & 1) { + tmp &= ~1; + WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp); + } + for (j = 0; j < adev->usec_timeout; j++) { + tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); + if ((tmp & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) == 0) + break; + udelay(1); + } + } + } + + /* Unlock vga access */ + WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); + mdelay(1); + WREG32(VGA_RENDER_CONTROL, save->vga_render_control); + +} + +static void dce_v6_0_set_vga_render_state(struct amdgpu_device *adev, + bool render) +{ + if (!render) + WREG32(R_000300_VGA_RENDER_CONTROL, + RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL); + +} + +static void dce_v6_0_program_fmt(struct drm_encoder *encoder) +{ + + struct drm_device *dev = encoder->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); + int bpc = 0; + u32 tmp = 0; + enum amdgpu_connector_dither dither = AMDGPU_FMT_DITHER_DISABLE; + + if (connector) { + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + bpc = amdgpu_connector_get_monitor_bpc(connector); + dither = amdgpu_connector->dither; + } + + /* LVDS FMT is set up by atom */ + if (amdgpu_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) + return; + + if (bpc == 0) + return; + + + switch (bpc) { + case 6: + if (dither == AMDGPU_FMT_DITHER_ENABLE) + /* XXX sort out optimal dither settings */ + tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | + FMT_SPATIAL_DITHER_EN); + else + tmp |= FMT_TRUNCATE_EN; + break; + case 8: + if (dither == AMDGPU_FMT_DITHER_ENABLE) + /* XXX sort out optimal dither settings */ + tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | + FMT_RGB_RANDOM_ENABLE | + FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH); + else + tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH); + break; + case 10: + default: + /* not needed */ + break; + } + + WREG32(FMT_BIT_DEPTH_CONTROL + amdgpu_crtc->crtc_offset, tmp); +} + +/** + * cik_get_number_of_dram_channels - get the number of dram channels + * + * @adev: amdgpu_device pointer + * + * Look up the number of video ram channels (CIK). + * Used for display watermark bandwidth calculations + * Returns the number of dram channels + */ +static u32 si_get_number_of_dram_channels(struct amdgpu_device *adev) +{ + u32 tmp = RREG32(MC_SHARED_CHMAP); + + switch ((tmp & MC_SHARED_CHMAP__NOOFCHAN_MASK) >> MC_SHARED_CHMAP__NOOFCHAN__SHIFT) { + case 0: + default: + return 1; + case 1: + return 2; + case 2: + return 4; + case 3: + return 8; + case 4: + return 3; + case 5: + return 6; + case 6: + return 10; + case 7: + return 12; + case 8: + return 16; + } +} + +struct dce6_wm_params { + u32 dram_channels; /* number of dram channels */ + u32 yclk; /* bandwidth per dram data pin in kHz */ + u32 sclk; /* engine clock in kHz */ + u32 disp_clk; /* display clock in kHz */ + u32 src_width; /* viewport width */ + u32 active_time; /* active display time in ns */ + u32 blank_time; /* blank time in ns */ + bool interlaced; /* mode is interlaced */ + fixed20_12 vsc; /* vertical scale ratio */ + u32 num_heads; /* number of active crtcs */ + u32 bytes_per_pixel; /* bytes per pixel display + overlay */ + u32 lb_size; /* line buffer allocated to pipe */ + u32 vtaps; /* vertical scaler taps */ +}; + +/** + * dce_v6_0_dram_bandwidth - get the dram bandwidth + * + * @wm: watermark calculation data + * + * Calculate the raw dram bandwidth (CIK). + * Used for display watermark bandwidth calculations + * Returns the dram bandwidth in MBytes/s + */ +static u32 dce_v6_0_dram_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate raw DRAM Bandwidth */ + fixed20_12 dram_efficiency; /* 0.7 */ + fixed20_12 yclk, dram_channels, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + yclk.full = dfixed_const(wm->yclk); + yclk.full = dfixed_div(yclk, a); + dram_channels.full = dfixed_const(wm->dram_channels * 4); + a.full = dfixed_const(10); + dram_efficiency.full = dfixed_const(7); + dram_efficiency.full = dfixed_div(dram_efficiency, a); + bandwidth.full = dfixed_mul(dram_channels, yclk); + bandwidth.full = dfixed_mul(bandwidth, dram_efficiency); + + return dfixed_trunc(bandwidth); +} + +/** + * dce_v6_0_dram_bandwidth_for_display - get the dram bandwidth for display + * + * @wm: watermark calculation data + * + * Calculate the dram bandwidth used for display (CIK). + * Used for display watermark bandwidth calculations + * Returns the dram bandwidth for display in MBytes/s + */ +static u32 dce_v6_0_dram_bandwidth_for_display(struct dce6_wm_params *wm) +{ + /* Calculate DRAM Bandwidth and the part allocated to display. */ + fixed20_12 disp_dram_allocation; /* 0.3 to 0.7 */ + fixed20_12 yclk, dram_channels, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + yclk.full = dfixed_const(wm->yclk); + yclk.full = dfixed_div(yclk, a); + dram_channels.full = dfixed_const(wm->dram_channels * 4); + a.full = dfixed_const(10); + disp_dram_allocation.full = dfixed_const(3); /* XXX worse case value 0.3 */ + disp_dram_allocation.full = dfixed_div(disp_dram_allocation, a); + bandwidth.full = dfixed_mul(dram_channels, yclk); + bandwidth.full = dfixed_mul(bandwidth, disp_dram_allocation); + + return dfixed_trunc(bandwidth); +} + +/** + * dce_v6_0_data_return_bandwidth - get the data return bandwidth + * + * @wm: watermark calculation data + * + * Calculate the data return bandwidth used for display (CIK). + * Used for display watermark bandwidth calculations + * Returns the data return bandwidth in MBytes/s + */ +static u32 dce_v6_0_data_return_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate the display Data return Bandwidth */ + fixed20_12 return_efficiency; /* 0.8 */ + fixed20_12 sclk, bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + sclk.full = dfixed_const(wm->sclk); + sclk.full = dfixed_div(sclk, a); + a.full = dfixed_const(10); + return_efficiency.full = dfixed_const(8); + return_efficiency.full = dfixed_div(return_efficiency, a); + a.full = dfixed_const(32); + bandwidth.full = dfixed_mul(a, sclk); + bandwidth.full = dfixed_mul(bandwidth, return_efficiency); + + return dfixed_trunc(bandwidth); +} + +/** + * dce_v6_0_dmif_request_bandwidth - get the dmif bandwidth + * + * @wm: watermark calculation data + * + * Calculate the dmif bandwidth used for display (CIK). + * Used for display watermark bandwidth calculations + * Returns the dmif bandwidth in MBytes/s + */ +static u32 dce_v6_0_dmif_request_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate the DMIF Request Bandwidth */ + fixed20_12 disp_clk_request_efficiency; /* 0.8 */ + fixed20_12 disp_clk, bandwidth; + fixed20_12 a, b; + + a.full = dfixed_const(1000); + disp_clk.full = dfixed_const(wm->disp_clk); + disp_clk.full = dfixed_div(disp_clk, a); + a.full = dfixed_const(32); + b.full = dfixed_mul(a, disp_clk); + + a.full = dfixed_const(10); + disp_clk_request_efficiency.full = dfixed_const(8); + disp_clk_request_efficiency.full = dfixed_div(disp_clk_request_efficiency, a); + + bandwidth.full = dfixed_mul(b, disp_clk_request_efficiency); + + return dfixed_trunc(bandwidth); +} + +/** + * dce_v6_0_available_bandwidth - get the min available bandwidth + * + * @wm: watermark calculation data + * + * Calculate the min available bandwidth used for display (CIK). + * Used for display watermark bandwidth calculations + * Returns the min available bandwidth in MBytes/s + */ +static u32 dce_v6_0_available_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate the Available bandwidth. Display can use this temporarily but not in average. */ + u32 dram_bandwidth = dce_v6_0_dram_bandwidth(wm); + u32 data_return_bandwidth = dce_v6_0_data_return_bandwidth(wm); + u32 dmif_req_bandwidth = dce_v6_0_dmif_request_bandwidth(wm); + + return min(dram_bandwidth, min(data_return_bandwidth, dmif_req_bandwidth)); +} + +/** + * dce_v6_0_average_bandwidth - get the average available bandwidth + * + * @wm: watermark calculation data + * + * Calculate the average available bandwidth used for display (CIK). + * Used for display watermark bandwidth calculations + * Returns the average available bandwidth in MBytes/s + */ +static u32 dce_v6_0_average_bandwidth(struct dce6_wm_params *wm) +{ + /* Calculate the display mode Average Bandwidth + * DisplayMode should contain the source and destination dimensions, + * timing, etc. + */ + fixed20_12 bpp; + fixed20_12 line_time; + fixed20_12 src_width; + fixed20_12 bandwidth; + fixed20_12 a; + + a.full = dfixed_const(1000); + line_time.full = dfixed_const(wm->active_time + wm->blank_time); + line_time.full = dfixed_div(line_time, a); + bpp.full = dfixed_const(wm->bytes_per_pixel); + src_width.full = dfixed_const(wm->src_width); + bandwidth.full = dfixed_mul(src_width, bpp); + bandwidth.full = dfixed_mul(bandwidth, wm->vsc); + bandwidth.full = dfixed_div(bandwidth, line_time); + + return dfixed_trunc(bandwidth); +} + +/** + * dce_v6_0_latency_watermark - get the latency watermark + * + * @wm: watermark calculation data + * + * Calculate the latency watermark (CIK). + * Used for display watermark bandwidth calculations + * Returns the latency watermark in ns + */ +static u32 dce_v6_0_latency_watermark(struct dce6_wm_params *wm) +{ + /* First calculate the latency in ns */ + u32 mc_latency = 2000; /* 2000 ns. */ + u32 available_bandwidth = dce_v6_0_available_bandwidth(wm); + u32 worst_chunk_return_time = (512 * 8 * 1000) / available_bandwidth; + u32 cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth; + u32 dc_latency = 40000000 / wm->disp_clk; /* dc pipe latency */ + u32 other_heads_data_return_time = ((wm->num_heads + 1) * worst_chunk_return_time) + + (wm->num_heads * cursor_line_pair_return_time); + u32 latency = mc_latency + other_heads_data_return_time + dc_latency; + u32 max_src_lines_per_dst_line, lb_fill_bw, line_fill_time; + u32 tmp, dmif_size = 12288; + fixed20_12 a, b, c; + + if (wm->num_heads == 0) + return 0; + + a.full = dfixed_const(2); + b.full = dfixed_const(1); + if ((wm->vsc.full > a.full) || + ((wm->vsc.full > b.full) && (wm->vtaps >= 3)) || + (wm->vtaps >= 5) || + ((wm->vsc.full >= a.full) && wm->interlaced)) + max_src_lines_per_dst_line = 4; + else + max_src_lines_per_dst_line = 2; + + a.full = dfixed_const(available_bandwidth); + b.full = dfixed_const(wm->num_heads); + a.full = dfixed_div(a, b); + + b.full = dfixed_const(mc_latency + 512); + c.full = dfixed_const(wm->disp_clk); + b.full = dfixed_div(b, c); + + c.full = dfixed_const(dmif_size); + b.full = dfixed_div(c, b); + + tmp = min(dfixed_trunc(a), dfixed_trunc(b)); + + b.full = dfixed_const(1000); + c.full = dfixed_const(wm->disp_clk); + b.full = dfixed_div(c, b); + c.full = dfixed_const(wm->bytes_per_pixel); + b.full = dfixed_mul(b, c); + + lb_fill_bw = min(tmp, dfixed_trunc(b)); + + a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); + b.full = dfixed_const(1000); + c.full = dfixed_const(lb_fill_bw); + b.full = dfixed_div(c, b); + a.full = dfixed_div(a, b); + line_fill_time = dfixed_trunc(a); + + if (line_fill_time < wm->active_time) + return latency; + else + return latency + (line_fill_time - wm->active_time); + +} + +/** + * dce_v6_0_average_bandwidth_vs_dram_bandwidth_for_display - check + * average and available dram bandwidth + * + * @wm: watermark calculation data + * + * Check if the display average bandwidth fits in the display + * dram bandwidth (CIK). + * Used for display watermark bandwidth calculations + * Returns true if the display fits, false if not. + */ +static bool dce_v6_0_average_bandwidth_vs_dram_bandwidth_for_display(struct dce6_wm_params *wm) +{ + if (dce_v6_0_average_bandwidth(wm) <= + (dce_v6_0_dram_bandwidth_for_display(wm) / wm->num_heads)) + return true; + else + return false; +} + +/** + * dce_v6_0_average_bandwidth_vs_available_bandwidth - check + * average and available bandwidth + * + * @wm: watermark calculation data + * + * Check if the display average bandwidth fits in the display + * available bandwidth (CIK). + * Used for display watermark bandwidth calculations + * Returns true if the display fits, false if not. + */ +static bool dce_v6_0_average_bandwidth_vs_available_bandwidth(struct dce6_wm_params *wm) +{ + if (dce_v6_0_average_bandwidth(wm) <= + (dce_v6_0_available_bandwidth(wm) / wm->num_heads)) + return true; + else + return false; +} + +/** + * dce_v6_0_check_latency_hiding - check latency hiding + * + * @wm: watermark calculation data + * + * Check latency hiding (CIK). + * Used for display watermark bandwidth calculations + * Returns true if the display fits, false if not. + */ +static bool dce_v6_0_check_latency_hiding(struct dce6_wm_params *wm) +{ + u32 lb_partitions = wm->lb_size / wm->src_width; + u32 line_time = wm->active_time + wm->blank_time; + u32 latency_tolerant_lines; + u32 latency_hiding; + fixed20_12 a; + + a.full = dfixed_const(1); + if (wm->vsc.full > a.full) + latency_tolerant_lines = 1; + else { + if (lb_partitions <= (wm->vtaps + 1)) + latency_tolerant_lines = 1; + else + latency_tolerant_lines = 2; + } + + latency_hiding = (latency_tolerant_lines * line_time + wm->blank_time); + + if (dce_v6_0_latency_watermark(wm) <= latency_hiding) + return true; + else + return false; +} + +/** + * dce_v6_0_program_watermarks - program display watermarks + * + * @adev: amdgpu_device pointer + * @amdgpu_crtc: the selected display controller + * @lb_size: line buffer size + * @num_heads: number of display controllers in use + * + * Calculate and program the display watermarks for the + * selected display controller (CIK). + */ +static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, + struct amdgpu_crtc *amdgpu_crtc, + u32 lb_size, u32 num_heads) +{ + struct drm_display_mode *mode = &amdgpu_crtc->base.mode; + struct dce6_wm_params wm_low, wm_high; + u32 dram_channels; + u32 pixel_period; + u32 line_time = 0; + u32 latency_watermark_a = 0, latency_watermark_b = 0; + u32 priority_a_mark = 0, priority_b_mark = 0; + u32 priority_a_cnt = PRIORITY_OFF; + u32 priority_b_cnt = PRIORITY_OFF; + u32 tmp, arb_control3; + fixed20_12 a, b, c; + + if (amdgpu_crtc->base.enabled && num_heads && mode) { + pixel_period = 1000000 / (u32)mode->clock; + line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + priority_a_cnt = 0; + priority_b_cnt = 0; + + dram_channels = si_get_number_of_dram_channels(adev); + + /* watermark for high clocks */ + if (adev->pm.dpm_enabled) { + wm_high.yclk = + amdgpu_dpm_get_mclk(adev, false) * 10; + wm_high.sclk = + amdgpu_dpm_get_sclk(adev, false) * 10; + } else { + wm_high.yclk = adev->pm.current_mclk * 10; + wm_high.sclk = adev->pm.current_sclk * 10; + } + + wm_high.disp_clk = mode->clock; + wm_high.src_width = mode->crtc_hdisplay; + wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.blank_time = line_time - wm_high.active_time; + wm_high.interlaced = false; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + wm_high.interlaced = true; + wm_high.vsc = amdgpu_crtc->vsc; + wm_high.vtaps = 1; + if (amdgpu_crtc->rmx_type != RMX_OFF) + wm_high.vtaps = 2; + wm_high.bytes_per_pixel = 4; /* XXX: get this from fb config */ + wm_high.lb_size = lb_size; + wm_high.dram_channels = dram_channels; + wm_high.num_heads = num_heads; + + if (adev->pm.dpm_enabled) { + /* watermark for low clocks */ + wm_low.yclk = + amdgpu_dpm_get_mclk(adev, true) * 10; + wm_low.sclk = + amdgpu_dpm_get_sclk(adev, true) * 10; + } else { + wm_low.yclk = adev->pm.current_mclk * 10; + wm_low.sclk = adev->pm.current_sclk * 10; + } + + wm_low.disp_clk = mode->clock; + wm_low.src_width = mode->crtc_hdisplay; + wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.blank_time = line_time - wm_low.active_time; + wm_low.interlaced = false; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + wm_low.interlaced = true; + wm_low.vsc = amdgpu_crtc->vsc; + wm_low.vtaps = 1; + if (amdgpu_crtc->rmx_type != RMX_OFF) + wm_low.vtaps = 2; + wm_low.bytes_per_pixel = 4; /* XXX: get this from fb config */ + wm_low.lb_size = lb_size; + wm_low.dram_channels = dram_channels; + wm_low.num_heads = num_heads; + + /* set for high clocks */ + latency_watermark_a = min(dce_v6_0_latency_watermark(&wm_high), (u32)65535); + /* set for low clocks */ + latency_watermark_b = min(dce_v6_0_latency_watermark(&wm_low), (u32)65535); + + /* possibly force display priority to high */ + /* should really do this at mode validation time... */ + if (!dce_v6_0_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) || + !dce_v6_0_average_bandwidth_vs_available_bandwidth(&wm_high) || + !dce_v6_0_check_latency_hiding(&wm_high) || + (adev->mode_info.disp_priority == 2)) { + DRM_DEBUG_KMS("force priority to high\n"); + priority_a_cnt |= PRIORITY_ALWAYS_ON; + priority_b_cnt |= PRIORITY_ALWAYS_ON; + } + if (!dce_v6_0_average_bandwidth_vs_dram_bandwidth_for_display(&wm_low) || + !dce_v6_0_average_bandwidth_vs_available_bandwidth(&wm_low) || + !dce_v6_0_check_latency_hiding(&wm_low) || + (adev->mode_info.disp_priority == 2)) { + DRM_DEBUG_KMS("force priority to high\n"); + priority_a_cnt |= PRIORITY_ALWAYS_ON; + priority_b_cnt |= PRIORITY_ALWAYS_ON; + } + + a.full = dfixed_const(1000); + b.full = dfixed_const(mode->clock); + b.full = dfixed_div(b, a); + c.full = dfixed_const(latency_watermark_a); + c.full = dfixed_mul(c, b); + c.full = dfixed_mul(c, amdgpu_crtc->hsc); + c.full = dfixed_div(c, a); + a.full = dfixed_const(16); + c.full = dfixed_div(c, a); + priority_a_mark = dfixed_trunc(c); + priority_a_cnt |= priority_a_mark & PRIORITY_MARK_MASK; + + a.full = dfixed_const(1000); + b.full = dfixed_const(mode->clock); + b.full = dfixed_div(b, a); + c.full = dfixed_const(latency_watermark_b); + c.full = dfixed_mul(c, b); + c.full = dfixed_mul(c, amdgpu_crtc->hsc); + c.full = dfixed_div(c, a); + a.full = dfixed_const(16); + c.full = dfixed_div(c, a); + priority_b_mark = dfixed_trunc(c); + priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; + } + + /* select wm A */ + arb_control3 = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset); + tmp = arb_control3; + tmp &= ~LATENCY_WATERMARK_MASK(3); + tmp |= LATENCY_WATERMARK_MASK(1); + WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp); + WREG32(DPG_PIPE_LATENCY_CONTROL + amdgpu_crtc->crtc_offset, + (LATENCY_LOW_WATERMARK(latency_watermark_a) | + LATENCY_HIGH_WATERMARK(line_time))); + /* select wm B */ + tmp = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset); + tmp &= ~LATENCY_WATERMARK_MASK(3); + tmp |= LATENCY_WATERMARK_MASK(2); + WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp); + WREG32(DPG_PIPE_LATENCY_CONTROL + amdgpu_crtc->crtc_offset, + (LATENCY_LOW_WATERMARK(latency_watermark_b) | + LATENCY_HIGH_WATERMARK(line_time))); + /* restore original selection */ + WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, arb_control3); + + /* write the priority marks */ + WREG32(PRIORITY_A_CNT + amdgpu_crtc->crtc_offset, priority_a_cnt); + WREG32(PRIORITY_B_CNT + amdgpu_crtc->crtc_offset, priority_b_cnt); + + /* save values for DPM */ + amdgpu_crtc->line_time = line_time; + amdgpu_crtc->wm_high = latency_watermark_a; +} + +/* watermark setup */ +static u32 dce_v6_0_line_buffer_adjust(struct amdgpu_device *adev, + struct amdgpu_crtc *amdgpu_crtc, + struct drm_display_mode *mode, + struct drm_display_mode *other_mode) +{ + u32 tmp, buffer_alloc, i; + u32 pipe_offset = amdgpu_crtc->crtc_id * 0x8; + /* + * Line Buffer Setup + * There are 3 line buffers, each one shared by 2 display controllers. + * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between + * the display controllers. The paritioning is done via one of four + * preset allocations specified in bits 21:20: + * 0 - half lb + * 2 - whole lb, other crtc must be disabled + */ + /* this can get tricky if we have two large displays on a paired group + * of crtcs. Ideally for multiple large displays we'd assign them to + * non-linked crtcs for maximum line buffer allocation. + */ + if (amdgpu_crtc->base.enabled && mode) { + if (other_mode) { + tmp = 0; /* 1/2 */ + buffer_alloc = 1; + } else { + tmp = 2; /* whole */ + buffer_alloc = 2; + } + } else { + tmp = 0; + buffer_alloc = 0; + } + + WREG32(DC_LB_MEMORY_SPLIT + amdgpu_crtc->crtc_offset, + DC_LB_MEMORY_CONFIG(tmp)); + + WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + + if (amdgpu_crtc->base.enabled && mode) { + switch (tmp) { + case 0: + default: + return 4096 * 2; + case 2: + return 8192 * 2; + } + } + + /* controller not enabled, so no lb used */ + return 0; +} + + +/** + * + * dce_v6_0_bandwidth_update - program display watermarks + * + * @adev: amdgpu_device pointer + * + * Calculate and program the display watermarks and line + * buffer allocation (CIK). + */ +static void dce_v6_0_bandwidth_update(struct amdgpu_device *adev) +{ + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + u32 num_heads = 0, lb_size; + int i; + + if (!adev->mode_info.mode_config_initialized) + return; + + amdgpu_update_display_priority(adev); + + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (adev->mode_info.crtcs[i]->base.enabled) + num_heads++; + } + for (i = 0; i < adev->mode_info.num_crtc; i += 2) { + mode0 = &adev->mode_info.crtcs[i]->base.mode; + mode1 = &adev->mode_info.crtcs[i+1]->base.mode; + lb_size = dce_v6_0_line_buffer_adjust(adev, adev->mode_info.crtcs[i], mode0, mode1); + dce_v6_0_program_watermarks(adev, adev->mode_info.crtcs[i], lb_size, num_heads); + lb_size = dce_v6_0_line_buffer_adjust(adev, adev->mode_info.crtcs[i+1], mode1, mode0); + dce_v6_0_program_watermarks(adev, adev->mode_info.crtcs[i+1], lb_size, num_heads); + } +} +/* +static void dce_v6_0_audio_get_connected_pins(struct amdgpu_device *adev) +{ + int i; + u32 offset, tmp; + + for (i = 0; i < adev->mode_info.audio.num_pins; i++) { + offset = adev->mode_info.audio.pin[i].offset; + tmp = RREG32_AUDIO_ENDPT(offset, + AZ_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT); + if (((tmp & PORT_CONNECTIVITY_MASK) >> PORT_CONNECTIVITY_SHIFT) == 1) + adev->mode_info.audio.pin[i].connected = false; + else + adev->mode_info.audio.pin[i].connected = true; + } + +} + +static struct amdgpu_audio_pin *dce_v6_0_audio_get_pin(struct amdgpu_device *adev) +{ + int i; + + dce_v6_0_audio_get_connected_pins(adev); + + for (i = 0; i < adev->mode_info.audio.num_pins; i++) { + if (adev->mode_info.audio.pin[i].connected) + return &adev->mode_info.audio.pin[i]; + } + DRM_ERROR("No connected audio pins found!\n"); + return NULL; +} + +static void dce_v6_0_afmt_audio_select_pin(struct drm_encoder *encoder) +{ + struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; + u32 offset; + + if (!dig || !dig->afmt || !dig->afmt->pin) + return; + + offset = dig->afmt->offset; + + WREG32(AFMT_AUDIO_SRC_CONTROL + offset, + AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id)); + +} + +static void dce_v6_0_audio_write_latency_fields(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + DRM_INFO("xxxx: dce_v6_0_audio_write_latency_fields---no imp!!!!!\n"); +} + +static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder) +{ + DRM_INFO("xxxx: dce_v6_0_audio_write_speaker_allocation---no imp!!!!!\n"); +} + +static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder) +{ + DRM_INFO("xxxx: dce_v6_0_audio_write_sad_regs---no imp!!!!!\n"); + +} +*/ +static void dce_v6_0_audio_enable(struct amdgpu_device *adev, + struct amdgpu_audio_pin *pin, + bool enable) +{ + DRM_INFO("xxxx: dce_v6_0_audio_enable---no imp!!!!!\n"); +} + +static const u32 pin_offsets[7] = +{ + (0x1780 - 0x1780), + (0x1786 - 0x1780), + (0x178c - 0x1780), + (0x1792 - 0x1780), + (0x1798 - 0x1780), + (0x179d - 0x1780), + (0x17a4 - 0x1780), +}; + +static int dce_v6_0_audio_init(struct amdgpu_device *adev) +{ + return 0; +} + +static void dce_v6_0_audio_fini(struct amdgpu_device *adev) +{ + +} + +/* +static void dce_v6_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock) +{ + DRM_INFO("xxxx: dce_v6_0_afmt_update_ACR---no imp!!!!!\n"); +} +*/ +/* + * build a HDMI Video Info Frame + */ +/* +static void dce_v6_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, + void *buffer, size_t size) +{ + DRM_INFO("xxxx: dce_v6_0_afmt_update_avi_infoframe---no imp!!!!!\n"); +} + +static void dce_v6_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) +{ + DRM_INFO("xxxx: dce_v6_0_audio_set_dto---no imp!!!!!\n"); +} +*/ +/* + * update the info frames with the data from the current display mode + */ +static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + DRM_INFO("xxxx: dce_v6_0_afmt_setmode ----no impl !!!!!!!!\n"); +} + +static void dce_v6_0_afmt_enable(struct drm_encoder *encoder, bool enable) +{ + struct drm_device *dev = encoder->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; + + if (!dig || !dig->afmt) + return; + + /* Silent, r600_hdmi_enable will raise WARN for us */ + if (enable && dig->afmt->enabled) + return; + if (!enable && !dig->afmt->enabled) + return; + + if (!enable && dig->afmt->pin) { + dce_v6_0_audio_enable(adev, dig->afmt->pin, false); + dig->afmt->pin = NULL; + } + + dig->afmt->enabled = enable; + + DRM_DEBUG("%sabling AFMT interface @ 0x%04X for encoder 0x%x\n", + enable ? "En" : "Dis", dig->afmt->offset, amdgpu_encoder->encoder_id); +} + +static void dce_v6_0_afmt_init(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < adev->mode_info.num_dig; i++) + adev->mode_info.afmt[i] = NULL; + + /* DCE8 has audio blocks tied to DIG encoders */ + for (i = 0; i < adev->mode_info.num_dig; i++) { + adev->mode_info.afmt[i] = kzalloc(sizeof(struct amdgpu_afmt), GFP_KERNEL); + if (adev->mode_info.afmt[i]) { + adev->mode_info.afmt[i]->offset = dig_offsets[i]; + adev->mode_info.afmt[i]->id = i; + } + } +} + +static void dce_v6_0_afmt_fini(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < adev->mode_info.num_dig; i++) { + kfree(adev->mode_info.afmt[i]); + adev->mode_info.afmt[i] = NULL; + } +} + +static const u32 vga_control_regs[6] = +{ + AVIVO_D1VGA_CONTROL, + AVIVO_D2VGA_CONTROL, + EVERGREEN_D3VGA_CONTROL, + EVERGREEN_D4VGA_CONTROL, + EVERGREEN_D5VGA_CONTROL, + EVERGREEN_D6VGA_CONTROL, +}; + +static void dce_v6_0_vga_enable(struct drm_crtc *crtc, bool enable) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + u32 vga_control; + + vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; + if (enable) + WREG32(vga_control_regs[amdgpu_crtc->crtc_id], vga_control | 1); + else + WREG32(vga_control_regs[amdgpu_crtc->crtc_id], vga_control); +} + +static void dce_v6_0_grph_enable(struct drm_crtc *crtc, bool enable) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + + if (enable) + WREG32(EVERGREEN_GRPH_ENABLE + amdgpu_crtc->crtc_offset, 1); + else + WREG32(EVERGREEN_GRPH_ENABLE + amdgpu_crtc->crtc_offset, 0); +} + +static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, int atomic) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_framebuffer *amdgpu_fb; + struct drm_framebuffer *target_fb; + struct drm_gem_object *obj; + struct amdgpu_bo *rbo; + uint64_t fb_location, tiling_flags; + uint32_t fb_format, fb_pitch_pixels, pipe_config; + u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); + u32 viewport_w, viewport_h; + int r; + bool bypass_lut = false; + + /* no fb bound */ + if (!atomic && !crtc->primary->fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + if (atomic) { + amdgpu_fb = to_amdgpu_framebuffer(fb); + target_fb = fb; + } + else { + amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb); + target_fb = crtc->primary->fb; + } + + /* If atomic, assume fb object is pinned & idle & fenced and + * just update base pointers + */ + obj = amdgpu_fb->obj; + rbo = gem_to_amdgpu_bo(obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + if (atomic) + fb_location = amdgpu_bo_gpu_offset(rbo); + else { + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &fb_location); + if (unlikely(r != 0)) { + amdgpu_bo_unreserve(rbo); + return -EINVAL; + } + } + + amdgpu_bo_get_tiling_flags(rbo, &tiling_flags); + amdgpu_bo_unreserve(rbo); + + switch (target_fb->pixel_format) { + case DRM_FORMAT_C8: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED)); + break; + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_ARGB4444: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB4444)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); +#endif + break; + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_ARGB1555: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); +#endif + break; + case DRM_FORMAT_BGRX5551: + case DRM_FORMAT_BGRA5551: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA5551)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); +#endif + break; + case DRM_FORMAT_RGB565: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); +#endif + break; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32); +#endif + break; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB2101010)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32); +#endif + /* Greater 8 bpc fb needs to bypass hw-lut to retain precision */ + bypass_lut = true; + break; + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_BGRA1010102: + fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | + EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA1010102)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32); +#endif + /* Greater 8 bpc fb needs to bypass hw-lut to retain precision */ + bypass_lut = true; + break; + default: + DRM_ERROR("Unsupported screen format %s\n", + drm_get_format_name(target_fb->pixel_format)); + return -EINVAL; + } + + if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == ARRAY_2D_TILED_THIN1) { + unsigned bankw, bankh, mtaspect, tile_split, num_banks; + + bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); + bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); + mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); + tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); + num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); + + fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks); + fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1); + fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split); + fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw); + fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh); + fb_format |= EVERGREEN_GRPH_MACRO_TILE_ASPECT(mtaspect); + } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == ARRAY_1D_TILED_THIN1) + fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1); + + pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); + fb_format |= SI_GRPH_PIPE_CONFIG(pipe_config); + + dce_v6_0_vga_enable(crtc, false); + + /* Make sure surface address is updated at vertical blank rather than + * horizontal blank + */ + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, 0); + + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, + upper_32_bits(fb_location)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, + upper_32_bits(fb_location)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset, + (u32)fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset, + (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); + WREG32(EVERGREEN_GRPH_CONTROL + amdgpu_crtc->crtc_offset, fb_format); + WREG32(EVERGREEN_GRPH_SWAP_CONTROL + amdgpu_crtc->crtc_offset, fb_swap); + + /* + * The LUT only has 256 slots for indexing by a 8 bpc fb. Bypass the LUT + * for > 8 bpc scanout to avoid truncation of fb indices to 8 msb's, to + * retain the full precision throughout the pipeline. + */ + WREG32_P(EVERGREEN_GRPH_LUT_10BIT_BYPASS_CONTROL + amdgpu_crtc->crtc_offset, + (bypass_lut ? EVERGREEN_LUT_10BIT_BYPASS_EN : 0), + ~EVERGREEN_LUT_10BIT_BYPASS_EN); + + if (bypass_lut) + DRM_DEBUG_KMS("Bypassing hardware LUT due to 10 bit fb scanout.\n"); + + WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + amdgpu_crtc->crtc_offset, 0); + WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + amdgpu_crtc->crtc_offset, 0); + WREG32(EVERGREEN_GRPH_X_START + amdgpu_crtc->crtc_offset, 0); + WREG32(EVERGREEN_GRPH_Y_START + amdgpu_crtc->crtc_offset, 0); + WREG32(EVERGREEN_GRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width); + WREG32(EVERGREEN_GRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height); + + fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + WREG32(EVERGREEN_GRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels); + + dce_v6_0_grph_enable(crtc, true); + + WREG32(EVERGREEN_DESKTOP_HEIGHT + amdgpu_crtc->crtc_offset, + target_fb->height); + x &= ~3; + y &= ~1; + WREG32(EVERGREEN_VIEWPORT_START + amdgpu_crtc->crtc_offset, + (x << 16) | y); + viewport_w = crtc->mode.hdisplay; + viewport_h = (crtc->mode.vdisplay + 1) & ~1; + + WREG32(EVERGREEN_VIEWPORT_SIZE + amdgpu_crtc->crtc_offset, + (viewport_w << 16) | viewport_h); + + /* set pageflip to happen anywhere in vblank interval */ + WREG32(EVERGREEN_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0); + + if (!atomic && fb && fb != crtc->primary->fb) { + amdgpu_fb = to_amdgpu_framebuffer(fb); + rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + amdgpu_bo_unpin(rbo); + amdgpu_bo_unreserve(rbo); + } + + /* Bytes per pixel may have changed */ + dce_v6_0_bandwidth_update(adev); + + return 0; + +} + +static void dce_v6_0_set_interleave(struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + WREG32(EVERGREEN_DATA_FORMAT + amdgpu_crtc->crtc_offset, + EVERGREEN_INTERLEAVE_EN); + else + WREG32(EVERGREEN_DATA_FORMAT + amdgpu_crtc->crtc_offset, 0); +} + +static void dce_v6_0_crtc_load_lut(struct drm_crtc *crtc) +{ + + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + int i; + + DRM_DEBUG_KMS("%d\n", amdgpu_crtc->crtc_id); + + WREG32(NI_INPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset, + (NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) | + NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS))); + WREG32(NI_PRESCALE_GRPH_CONTROL + amdgpu_crtc->crtc_offset, + NI_GRPH_PRESCALE_BYPASS); + WREG32(NI_PRESCALE_OVL_CONTROL + amdgpu_crtc->crtc_offset, + NI_OVL_PRESCALE_BYPASS); + WREG32(NI_INPUT_GAMMA_CONTROL + amdgpu_crtc->crtc_offset, + (NI_GRPH_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT) | + NI_OVL_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT))); + + + + WREG32(EVERGREEN_DC_LUT_CONTROL + amdgpu_crtc->crtc_offset, 0); + + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + amdgpu_crtc->crtc_offset, 0); + + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0xffff); + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0xffff); + WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + amdgpu_crtc->crtc_offset, 0xffff); + + WREG32(EVERGREEN_DC_LUT_RW_MODE + amdgpu_crtc->crtc_offset, 0); + WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + amdgpu_crtc->crtc_offset, 0x00000007); + + WREG32(EVERGREEN_DC_LUT_RW_INDEX + amdgpu_crtc->crtc_offset, 0); + for (i = 0; i < 256; i++) { + WREG32(EVERGREEN_DC_LUT_30_COLOR + amdgpu_crtc->crtc_offset, + (amdgpu_crtc->lut_r[i] << 20) | + (amdgpu_crtc->lut_g[i] << 10) | + (amdgpu_crtc->lut_b[i] << 0)); + } + + WREG32(NI_DEGAMMA_CONTROL + amdgpu_crtc->crtc_offset, + (NI_GRPH_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) | + NI_OVL_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) | + NI_ICON_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) | + NI_CURSOR_DEGAMMA_MODE(NI_DEGAMMA_BYPASS))); + WREG32(NI_GAMUT_REMAP_CONTROL + amdgpu_crtc->crtc_offset, + (NI_GRPH_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS) | + NI_OVL_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS))); + WREG32(NI_REGAMMA_CONTROL + amdgpu_crtc->crtc_offset, + (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) | + NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS))); + WREG32(NI_OUTPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset, + (NI_OUTPUT_CSC_GRPH_MODE(0) | + NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS))); + /* XXX match this to the depth of the crtc fmt block, move to modeset? */ + WREG32(0x1a50 + amdgpu_crtc->crtc_offset, 0); + + +} + +static int dce_v6_0_pick_dig_encoder(struct drm_encoder *encoder) +{ + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; + + switch (amdgpu_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + if (dig->linkb) + return 1; + else + return 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + if (dig->linkb) + return 3; + else + return 2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->linkb) + return 5; + else + return 4; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + return 6; + break; + default: + DRM_ERROR("invalid encoder_id: 0x%x\n", amdgpu_encoder->encoder_id); + return 0; + } +} + +/** + * dce_v6_0_pick_pll - Allocate a PPLL for use by the crtc. + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) to be used by the crtc. For DP monitors + * a single PPLL can be used for all DP crtcs/encoders. For non-DP + * monitors a dedicated PPLL must be used. If a particular board has + * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming + * as there is no need to program the PLL itself. If we are not able to + * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to + * avoid messing up an existing monitor. + * + * + */ +static u32 dce_v6_0_pick_pll(struct drm_crtc *crtc) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + u32 pll_in_use; + int pll; + + if (ENCODER_MODE_IS_DP(amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder))) { + if (adev->clock.dp_extclk) + /* skip PPLL programming if using ext clock */ + return ATOM_PPLL_INVALID; + else + return ATOM_PPLL0; + } else { + /* use the same PPLL for all monitors with the same clock */ + pll = amdgpu_pll_get_shared_nondp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + + /* PPLL1, and PPLL2 */ + pll_in_use = amdgpu_pll_get_use_mask(crtc); + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; +} + +static void dce_v6_0_lock_cursor(struct drm_crtc *crtc, bool lock) +{ + struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + uint32_t cur_lock; + + cur_lock = RREG32(EVERGREEN_CUR_UPDATE + amdgpu_crtc->crtc_offset); + if (lock) + cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK; + else + cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK; + WREG32(EVERGREEN_CUR_UPDATE + amdgpu_crtc->crtc_offset, cur_lock); +} + +static void dce_v6_0_hide_cursor(struct drm_crtc *crtc) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct amdgpu_device *adev = crtc->dev->dev_private; + + WREG32_IDX(EVERGREEN_CUR_CONTROL + amdgpu_crtc->crtc_offset, + EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | + EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); + + +} + +static void dce_v6_0_show_cursor(struct drm_crtc *crtc) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct amdgpu_device *adev = crtc->dev->dev_private; + + WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, + upper_32_bits(amdgpu_crtc->cursor_addr)); + WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset, + lower_32_bits(amdgpu_crtc->cursor_addr)); + + WREG32_IDX(EVERGREEN_CUR_CONTROL + amdgpu_crtc->crtc_offset, + EVERGREEN_CURSOR_EN | + EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | + EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); + +} + +static int dce_v6_0_cursor_move_locked(struct drm_crtc *crtc, + int x, int y) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct amdgpu_device *adev = crtc->dev->dev_private; + int xorigin = 0, yorigin = 0; + + int w = amdgpu_crtc->cursor_width; + + /* avivo cursor are offset into the total surface */ + x += crtc->x; + y += crtc->y; + DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + WREG32(EVERGREEN_CUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y); + WREG32(EVERGREEN_CUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin); + WREG32(EVERGREEN_CUR_SIZE + amdgpu_crtc->crtc_offset, + ((w - 1) << 16) | (amdgpu_crtc->cursor_height - 1)); + + amdgpu_crtc->cursor_x = x; + amdgpu_crtc->cursor_y = y; + return 0; +} + +static int dce_v6_0_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + int ret; + + dce_v6_0_lock_cursor(crtc, true); + ret = dce_v6_0_cursor_move_locked(crtc, x, y); + dce_v6_0_lock_cursor(crtc, false); + + return ret; +} + +static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height, + int32_t hot_x, + int32_t hot_y) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_gem_object *obj; + struct amdgpu_bo *aobj; + int ret; + + if (!handle) { + /* turn off cursor */ + dce_v6_0_hide_cursor(crtc); + obj = NULL; + goto unpin; + } + + if ((width > amdgpu_crtc->max_cursor_width) || + (height > amdgpu_crtc->max_cursor_height)) { + DRM_ERROR("bad cursor width or height %d x %d\n", width, height); + return -EINVAL; + } + + obj = drm_gem_object_lookup(file_priv, handle); + if (!obj) { + DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, amdgpu_crtc->crtc_id); + return -ENOENT; + } + + aobj = gem_to_amdgpu_bo(obj); + ret = amdgpu_bo_reserve(aobj, false); + if (ret != 0) { + drm_gem_object_unreference_unlocked(obj); + return ret; + } + + ret = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM, &amdgpu_crtc->cursor_addr); + amdgpu_bo_unreserve(aobj); + if (ret) { + DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret); + drm_gem_object_unreference_unlocked(obj); + return ret; + } + + amdgpu_crtc->cursor_width = width; + amdgpu_crtc->cursor_height = height; + + dce_v6_0_lock_cursor(crtc, true); + + if (hot_x != amdgpu_crtc->cursor_hot_x || + hot_y != amdgpu_crtc->cursor_hot_y) { + int x, y; + + x = amdgpu_crtc->cursor_x + amdgpu_crtc->cursor_hot_x - hot_x; + y = amdgpu_crtc->cursor_y + amdgpu_crtc->cursor_hot_y - hot_y; + + dce_v6_0_cursor_move_locked(crtc, x, y); + + amdgpu_crtc->cursor_hot_x = hot_x; + amdgpu_crtc->cursor_hot_y = hot_y; + } + + dce_v6_0_show_cursor(crtc); + dce_v6_0_lock_cursor(crtc, false); + +unpin: + if (amdgpu_crtc->cursor_bo) { + struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); + ret = amdgpu_bo_reserve(aobj, false); + if (likely(ret == 0)) { + amdgpu_bo_unpin(aobj); + amdgpu_bo_unreserve(aobj); + } + drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo); + } + + amdgpu_crtc->cursor_bo = obj; + return 0; +} + +static void dce_v6_0_cursor_reset(struct drm_crtc *crtc) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + if (amdgpu_crtc->cursor_bo) { + dce_v6_0_lock_cursor(crtc, true); + + dce_v6_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x, + amdgpu_crtc->cursor_y); + + dce_v6_0_show_cursor(crtc); + + dce_v6_0_lock_cursor(crtc, false); + } +} + +static int dce_v6_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, uint32_t size) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + int i; + + /* userspace palettes are always correct as is */ + for (i = 0; i < size; i++) { + amdgpu_crtc->lut_r[i] = red[i] >> 6; + amdgpu_crtc->lut_g[i] = green[i] >> 6; + amdgpu_crtc->lut_b[i] = blue[i] >> 6; + } + dce_v6_0_crtc_load_lut(crtc); + + return 0; +} + +static void dce_v6_0_crtc_destroy(struct drm_crtc *crtc) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + drm_crtc_cleanup(crtc); + kfree(amdgpu_crtc); +} + +static const struct drm_crtc_funcs dce_v6_0_crtc_funcs = { + .cursor_set2 = dce_v6_0_crtc_cursor_set2, + .cursor_move = dce_v6_0_crtc_cursor_move, + .gamma_set = dce_v6_0_crtc_gamma_set, + .set_config = amdgpu_crtc_set_config, + .destroy = dce_v6_0_crtc_destroy, + .page_flip_target = amdgpu_crtc_page_flip_target, +}; + +static void dce_v6_0_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + unsigned type; + + switch (mode) { + case DRM_MODE_DPMS_ON: + amdgpu_crtc->enabled = true; + amdgpu_atombios_crtc_enable(crtc, ATOM_ENABLE); + amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); + /* Make sure VBLANK and PFLIP interrupts are still enabled */ + type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); + amdgpu_irq_update(adev, &adev->crtc_irq, type); + amdgpu_irq_update(adev, &adev->pageflip_irq, type); + drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); + dce_v6_0_crtc_load_lut(crtc); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + drm_vblank_pre_modeset(dev, amdgpu_crtc->crtc_id); + if (amdgpu_crtc->enabled) + amdgpu_atombios_crtc_blank(crtc, ATOM_ENABLE); + amdgpu_atombios_crtc_enable(crtc, ATOM_DISABLE); + amdgpu_crtc->enabled = false; + break; + } + /* adjust pm to dpms */ + amdgpu_pm_compute_clocks(adev); +} + +static void dce_v6_0_crtc_prepare(struct drm_crtc *crtc) +{ + /* disable crtc pair power gating before programming */ + amdgpu_atombios_crtc_powergate(crtc, ATOM_DISABLE); + amdgpu_atombios_crtc_lock(crtc, ATOM_ENABLE); + dce_v6_0_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); +} + +static void dce_v6_0_crtc_commit(struct drm_crtc *crtc) +{ + dce_v6_0_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + amdgpu_atombios_crtc_lock(crtc, ATOM_DISABLE); +} + +static void dce_v6_0_crtc_disable(struct drm_crtc *crtc) +{ + + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_atom_ss ss; + int i; + + dce_v6_0_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + if (crtc->primary->fb) { + int r; + struct amdgpu_framebuffer *amdgpu_fb; + struct amdgpu_bo *rbo; + + amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb); + rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) + DRM_ERROR("failed to reserve rbo before unpin\n"); + else { + amdgpu_bo_unpin(rbo); + amdgpu_bo_unreserve(rbo); + } + } + /* disable the GRPH */ + dce_v6_0_grph_enable(crtc, false); + + amdgpu_atombios_crtc_powergate(crtc, ATOM_ENABLE); + + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (adev->mode_info.crtcs[i] && + adev->mode_info.crtcs[i]->enabled && + i != amdgpu_crtc->crtc_id && + amdgpu_crtc->pll_id == adev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off the pll + */ + goto done; + } + } + + switch (amdgpu_crtc->pll_id) { + case ATOM_PPLL1: + case ATOM_PPLL2: + /* disable the ppll */ + amdgpu_atombios_crtc_program_pll(crtc, amdgpu_crtc->crtc_id, amdgpu_crtc->pll_id, + 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); + break; + default: + break; + } +done: + amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; + amdgpu_crtc->adjusted_clock = 0; + amdgpu_crtc->encoder = NULL; + amdgpu_crtc->connector = NULL; +} + +static int dce_v6_0_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, struct drm_framebuffer *old_fb) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + if (!amdgpu_crtc->adjusted_clock) + return -EINVAL; + + amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode); + amdgpu_atombios_crtc_set_dtd_timing(crtc, adjusted_mode); + dce_v6_0_crtc_do_set_base(crtc, old_fb, x, y, 0); + amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode); + amdgpu_atombios_crtc_scaler_setup(crtc); + dce_v6_0_cursor_reset(crtc); + /* update the hw version fpr dpm */ + amdgpu_crtc->hw_mode = *adjusted_mode; + + return 0; +} + +static bool dce_v6_0_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct drm_encoder *encoder; + + /* assign the encoder to the amdgpu crtc to avoid repeated lookups later */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->crtc == crtc) { + amdgpu_crtc->encoder = encoder; + amdgpu_crtc->connector = amdgpu_get_connector_for_encoder(encoder); + break; + } + } + if ((amdgpu_crtc->encoder == NULL) || (amdgpu_crtc->connector == NULL)) { + amdgpu_crtc->encoder = NULL; + amdgpu_crtc->connector = NULL; + return false; + } + if (!amdgpu_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) + return false; + if (amdgpu_atombios_crtc_prepare_pll(crtc, adjusted_mode)) + return false; + /* pick pll */ + amdgpu_crtc->pll_id = dce_v6_0_pick_pll(crtc); + /* if we can't get a PPLL for a non-DP encoder, fail */ + if ((amdgpu_crtc->pll_id == ATOM_PPLL_INVALID) && + !ENCODER_MODE_IS_DP(amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder))) + return false; + + return true; +} + +static int dce_v6_0_crtc_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + return dce_v6_0_crtc_do_set_base(crtc, old_fb, x, y, 0); +} + +static int dce_v6_0_crtc_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, enum mode_set_atomic state) +{ + return dce_v6_0_crtc_do_set_base(crtc, fb, x, y, 1); +} + +static const struct drm_crtc_helper_funcs dce_v6_0_crtc_helper_funcs = { + .dpms = dce_v6_0_crtc_dpms, + .mode_fixup = dce_v6_0_crtc_mode_fixup, + .mode_set = dce_v6_0_crtc_mode_set, + .mode_set_base = dce_v6_0_crtc_set_base, + .mode_set_base_atomic = dce_v6_0_crtc_set_base_atomic, + .prepare = dce_v6_0_crtc_prepare, + .commit = dce_v6_0_crtc_commit, + .load_lut = dce_v6_0_crtc_load_lut, + .disable = dce_v6_0_crtc_disable, +}; + +static int dce_v6_0_crtc_init(struct amdgpu_device *adev, int index) +{ + struct amdgpu_crtc *amdgpu_crtc; + int i; + + amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) + + (AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); + if (amdgpu_crtc == NULL) + return -ENOMEM; + + drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v6_0_crtc_funcs); + + drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); + amdgpu_crtc->crtc_id = index; + adev->mode_info.crtcs[index] = amdgpu_crtc; + + amdgpu_crtc->max_cursor_width = CURSOR_WIDTH; + amdgpu_crtc->max_cursor_height = CURSOR_HEIGHT; + adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + + for (i = 0; i < 256; i++) { + amdgpu_crtc->lut_r[i] = i << 2; + amdgpu_crtc->lut_g[i] = i << 2; + amdgpu_crtc->lut_b[i] = i << 2; + } + + amdgpu_crtc->crtc_offset = crtc_offsets[amdgpu_crtc->crtc_id]; + + amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; + amdgpu_crtc->adjusted_clock = 0; + amdgpu_crtc->encoder = NULL; + amdgpu_crtc->connector = NULL; + drm_crtc_helper_add(&amdgpu_crtc->base, &dce_v6_0_crtc_helper_funcs); + + return 0; +} + +static int dce_v6_0_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + adev->audio_endpt_rreg = &dce_v6_0_audio_endpt_rreg; + adev->audio_endpt_wreg = &dce_v6_0_audio_endpt_wreg; + + dce_v6_0_set_display_funcs(adev); + dce_v6_0_set_irq_funcs(adev); + + switch (adev->asic_type) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; + break; + case CHIP_OLAND: + adev->mode_info.num_crtc = 2; + adev->mode_info.num_hpd = 2; + adev->mode_info.num_dig = 2; + break; + default: + /* FIXME: not supported yet */ + return -EINVAL; + } + + return 0; +} + +static int dce_v6_0_sw_init(void *handle) +{ + int r, i; + bool ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + for (i = 0; i < adev->mode_info.num_crtc; i++) { + r = amdgpu_irq_add_id(adev, i + 1, &adev->crtc_irq); + if (r) + return r; + } + + for (i = 8; i < 20; i += 2) { + r = amdgpu_irq_add_id(adev, i, &adev->pageflip_irq); + if (r) + return r; + } + + /* HPD hotplug */ + r = amdgpu_irq_add_id(adev, 42, &adev->hpd_irq); + if (r) + return r; + + adev->mode_info.mode_config_initialized = true; + + adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + + adev->ddev->mode_config.async_page_flip = true; + + adev->ddev->mode_config.max_width = 16384; + adev->ddev->mode_config.max_height = 16384; + + adev->ddev->mode_config.preferred_depth = 24; + adev->ddev->mode_config.prefer_shadow = 1; + + adev->ddev->mode_config.fb_base = adev->mc.aper_base; + + r = amdgpu_modeset_create_props(adev); + if (r) + return r; + + adev->ddev->mode_config.max_width = 16384; + adev->ddev->mode_config.max_height = 16384; + + /* allocate crtcs */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + r = dce_v6_0_crtc_init(adev, i); + if (r) + return r; + } + + ret = amdgpu_atombios_get_connector_info_from_object_table(adev); + if (ret) + amdgpu_print_display_setup(adev->ddev); + else + return -EINVAL; + + /* setup afmt */ + dce_v6_0_afmt_init(adev); + + r = dce_v6_0_audio_init(adev); + if (r) + return r; + + drm_kms_helper_poll_init(adev->ddev); + + return r; +} + +static int dce_v6_0_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + kfree(adev->mode_info.bios_hardcoded_edid); + + drm_kms_helper_poll_fini(adev->ddev); + + dce_v6_0_audio_fini(adev); + + dce_v6_0_afmt_fini(adev); + + drm_mode_config_cleanup(adev->ddev); + adev->mode_info.mode_config_initialized = false; + + return 0; +} + +static int dce_v6_0_hw_init(void *handle) +{ + int i; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + /* init dig PHYs, disp eng pll */ + amdgpu_atombios_encoder_init_dig(adev); + amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk); + + /* initialize hpd */ + dce_v6_0_hpd_init(adev); + + for (i = 0; i < adev->mode_info.audio.num_pins; i++) { + dce_v6_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); + } + + dce_v6_0_pageflip_interrupt_init(adev); + + return 0; +} + +static int dce_v6_0_hw_fini(void *handle) +{ + int i; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + dce_v6_0_hpd_fini(adev); + + for (i = 0; i < adev->mode_info.audio.num_pins; i++) { + dce_v6_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); + } + + dce_v6_0_pageflip_interrupt_fini(adev); + + return 0; +} + +static int dce_v6_0_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_atombios_scratch_regs_save(adev); + + return dce_v6_0_hw_fini(handle); +} + +static int dce_v6_0_resume(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int ret; + + ret = dce_v6_0_hw_init(handle); + + amdgpu_atombios_scratch_regs_restore(adev); + + /* turn on the BL */ + if (adev->mode_info.bl_encoder) { + u8 bl_level = amdgpu_display_backlight_get_level(adev, + adev->mode_info.bl_encoder); + amdgpu_display_backlight_set_level(adev, adev->mode_info.bl_encoder, + bl_level); + } + + return ret; +} + +static bool dce_v6_0_is_idle(void *handle) +{ + return true; +} + +static int dce_v6_0_wait_for_idle(void *handle) +{ + return 0; +} + +static int dce_v6_0_soft_reset(void *handle) +{ + DRM_INFO("xxxx: dce_v6_0_soft_reset --- no impl!!\n"); + return 0; +} + +static void dce_v6_0_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev, + int crtc, + enum amdgpu_interrupt_state state) +{ + u32 reg_block, interrupt_mask; + + if (crtc >= adev->mode_info.num_crtc) { + DRM_DEBUG("invalid crtc %d\n", crtc); + return; + } + + switch (crtc) { + case 0: + reg_block = SI_CRTC0_REGISTER_OFFSET; + break; + case 1: + reg_block = SI_CRTC1_REGISTER_OFFSET; + break; + case 2: + reg_block = SI_CRTC2_REGISTER_OFFSET; + break; + case 3: + reg_block = SI_CRTC3_REGISTER_OFFSET; + break; + case 4: + reg_block = SI_CRTC4_REGISTER_OFFSET; + break; + case 5: + reg_block = SI_CRTC5_REGISTER_OFFSET; + break; + default: + DRM_DEBUG("invalid crtc %d\n", crtc); + return; + } + + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + interrupt_mask = RREG32(INT_MASK + reg_block); + interrupt_mask &= ~VBLANK_INT_MASK; + WREG32(INT_MASK + reg_block, interrupt_mask); + break; + case AMDGPU_IRQ_STATE_ENABLE: + interrupt_mask = RREG32(INT_MASK + reg_block); + interrupt_mask |= VBLANK_INT_MASK; + WREG32(INT_MASK + reg_block, interrupt_mask); + break; + default: + break; + } +} + +static void dce_v6_0_set_crtc_vline_interrupt_state(struct amdgpu_device *adev, + int crtc, + enum amdgpu_interrupt_state state) +{ + +} + +static int dce_v6_0_set_hpd_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl; + + switch (type) { + case AMDGPU_HPD_1: + dc_hpd_int_cntl_reg = DC_HPD1_INT_CONTROL; + break; + case AMDGPU_HPD_2: + dc_hpd_int_cntl_reg = DC_HPD2_INT_CONTROL; + break; + case AMDGPU_HPD_3: + dc_hpd_int_cntl_reg = DC_HPD3_INT_CONTROL; + break; + case AMDGPU_HPD_4: + dc_hpd_int_cntl_reg = DC_HPD4_INT_CONTROL; + break; + case AMDGPU_HPD_5: + dc_hpd_int_cntl_reg = DC_HPD5_INT_CONTROL; + break; + case AMDGPU_HPD_6: + dc_hpd_int_cntl_reg = DC_HPD6_INT_CONTROL; + break; + default: + DRM_DEBUG("invalid hdp %d\n", type); + return 0; + } + + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg); + dc_hpd_int_cntl &= ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN); + WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl); + break; + case AMDGPU_IRQ_STATE_ENABLE: + dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg); + dc_hpd_int_cntl |= (DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN); + WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl); + break; + default: + break; + } + + return 0; +} + +static int dce_v6_0_set_crtc_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + switch (type) { + case AMDGPU_CRTC_IRQ_VBLANK1: + dce_v6_0_set_crtc_vblank_interrupt_state(adev, 0, state); + break; + case AMDGPU_CRTC_IRQ_VBLANK2: + dce_v6_0_set_crtc_vblank_interrupt_state(adev, 1, state); + break; + case AMDGPU_CRTC_IRQ_VBLANK3: + dce_v6_0_set_crtc_vblank_interrupt_state(adev, 2, state); + break; + case AMDGPU_CRTC_IRQ_VBLANK4: + dce_v6_0_set_crtc_vblank_interrupt_state(adev, 3, state); + break; + case AMDGPU_CRTC_IRQ_VBLANK5: + dce_v6_0_set_crtc_vblank_interrupt_state(adev, 4, state); + break; + case AMDGPU_CRTC_IRQ_VBLANK6: + dce_v6_0_set_crtc_vblank_interrupt_state(adev, 5, state); + break; + case AMDGPU_CRTC_IRQ_VLINE1: + dce_v6_0_set_crtc_vline_interrupt_state(adev, 0, state); + break; + case AMDGPU_CRTC_IRQ_VLINE2: + dce_v6_0_set_crtc_vline_interrupt_state(adev, 1, state); + break; + case AMDGPU_CRTC_IRQ_VLINE3: + dce_v6_0_set_crtc_vline_interrupt_state(adev, 2, state); + break; + case AMDGPU_CRTC_IRQ_VLINE4: + dce_v6_0_set_crtc_vline_interrupt_state(adev, 3, state); + break; + case AMDGPU_CRTC_IRQ_VLINE5: + dce_v6_0_set_crtc_vline_interrupt_state(adev, 4, state); + break; + case AMDGPU_CRTC_IRQ_VLINE6: + dce_v6_0_set_crtc_vline_interrupt_state(adev, 5, state); + break; + default: + break; + } + return 0; +} + +static int dce_v6_0_crtc_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + unsigned crtc = entry->src_id - 1; + uint32_t disp_int = RREG32(interrupt_status_offsets[crtc].reg); + unsigned irq_type = amdgpu_crtc_idx_to_irq_type(adev, crtc); + + switch (entry->src_data) { + case 0: /* vblank */ + if (disp_int & interrupt_status_offsets[crtc].vblank) + WREG32(VBLANK_STATUS + crtc_offsets[crtc], VBLANK_ACK); + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (amdgpu_irq_enabled(adev, source, irq_type)) { + drm_handle_vblank(adev->ddev, crtc); + } + DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + break; + case 1: /* vline */ + if (disp_int & interrupt_status_offsets[crtc].vline) + WREG32(VLINE_STATUS + crtc_offsets[crtc], VLINE_ACK); + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + DRM_DEBUG("IH: D%d vline\n", crtc + 1); + break; + default: + DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); + break; + } + + return 0; +} + +static int dce_v6_0_set_pageflip_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 reg; + + if (type >= adev->mode_info.num_crtc) { + DRM_ERROR("invalid pageflip crtc %d\n", type); + return -EINVAL; + } + + reg = RREG32(GRPH_INT_CONTROL + crtc_offsets[type]); + if (state == AMDGPU_IRQ_STATE_DISABLE) + WREG32(GRPH_INT_CONTROL + crtc_offsets[type], + reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK); + else + WREG32(GRPH_INT_CONTROL + crtc_offsets[type], + reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK); + + return 0; +} + +static int dce_v6_0_pageflip_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + unsigned long flags; + unsigned crtc_id; + struct amdgpu_crtc *amdgpu_crtc; + struct amdgpu_flip_work *works; + + crtc_id = (entry->src_id - 8) >> 1; + amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; + + if (crtc_id >= adev->mode_info.num_crtc) { + DRM_ERROR("invalid pageflip crtc %d\n", crtc_id); + return -EINVAL; + } + + if (RREG32(GRPH_INT_STATUS + crtc_offsets[crtc_id]) & + GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK) + WREG32(GRPH_INT_STATUS + crtc_offsets[crtc_id], + GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK); + + /* IRQ could occur when in initial stage */ + if (amdgpu_crtc == NULL) + return 0; + + spin_lock_irqsave(&adev->ddev->event_lock, flags); + works = amdgpu_crtc->pflip_works; + if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ + DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " + "AMDGPU_FLIP_SUBMITTED(%d)\n", + amdgpu_crtc->pflip_status, + AMDGPU_FLIP_SUBMITTED); + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + return 0; + } + + /* page flip completed. clean up */ + amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; + amdgpu_crtc->pflip_works = NULL; + + /* wakeup usersapce */ + if (works->event) + drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); + + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + + drm_crtc_vblank_put(&amdgpu_crtc->base); + schedule_work(&works->unpin_work); + + return 0; +} + +static int dce_v6_0_hpd_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + uint32_t disp_int, mask, int_control, tmp; + unsigned hpd; + + if (entry->src_data > 6) { + DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); + return 0; + } + + hpd = entry->src_data; + disp_int = RREG32(interrupt_status_offsets[hpd].reg); + mask = interrupt_status_offsets[hpd].hpd; + int_control = hpd_int_control_offsets[hpd]; + + if (disp_int & mask) { + tmp = RREG32(int_control); + tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK; + WREG32(int_control, tmp); + schedule_work(&adev->hotplug_work); + DRM_INFO("IH: HPD%d\n", hpd + 1); + } + + return 0; + +} + +static int dce_v6_0_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int dce_v6_0_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +const struct amd_ip_funcs dce_v6_0_ip_funcs = { + .name = "dce_v6_0", + .early_init = dce_v6_0_early_init, + .late_init = NULL, + .sw_init = dce_v6_0_sw_init, + .sw_fini = dce_v6_0_sw_fini, + .hw_init = dce_v6_0_hw_init, + .hw_fini = dce_v6_0_hw_fini, + .suspend = dce_v6_0_suspend, + .resume = dce_v6_0_resume, + .is_idle = dce_v6_0_is_idle, + .wait_for_idle = dce_v6_0_wait_for_idle, + .soft_reset = dce_v6_0_soft_reset, + .set_clockgating_state = dce_v6_0_set_clockgating_state, + .set_powergating_state = dce_v6_0_set_powergating_state, +}; + +static void +dce_v6_0_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + + amdgpu_encoder->pixel_clock = adjusted_mode->clock; + + /* need to call this here rather than in prepare() since we need some crtc info */ + amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + + /* set scaler clears this on some chips */ + dce_v6_0_set_interleave(encoder->crtc, mode); + + if (amdgpu_atombios_encoder_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { + dce_v6_0_afmt_enable(encoder, true); + dce_v6_0_afmt_setmode(encoder, adjusted_mode); + } +} + +static void dce_v6_0_encoder_prepare(struct drm_encoder *encoder) +{ + + struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); + + if ((amdgpu_encoder->active_device & + (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || + (amdgpu_encoder_get_dp_bridge_encoder_id(encoder) != + ENCODER_OBJECT_ID_NONE)) { + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; + if (dig) { + dig->dig_encoder = dce_v6_0_pick_dig_encoder(encoder); + if (amdgpu_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) + dig->afmt = adev->mode_info.afmt[dig->dig_encoder]; + } + } + + amdgpu_atombios_scratch_regs_lock(adev, true); + + if (connector) { + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + + /* select the clock/data port if it uses a router */ + if (amdgpu_connector->router.cd_valid) + amdgpu_i2c_router_select_cd_port(amdgpu_connector); + + /* turn eDP panel on for mode set */ + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) + amdgpu_atombios_encoder_set_edp_panel_power(connector, + ATOM_TRANSMITTER_ACTION_POWER_ON); + } + + /* this is needed for the pll/ss setup to work correctly in some cases */ + amdgpu_atombios_encoder_set_crtc_source(encoder); + /* set up the FMT blocks */ + dce_v6_0_program_fmt(encoder); +} + +static void dce_v6_0_encoder_commit(struct drm_encoder *encoder) +{ + + struct drm_device *dev = encoder->dev; + struct amdgpu_device *adev = dev->dev_private; + + /* need to call this here as we need the crtc set up */ + amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); + amdgpu_atombios_scratch_regs_lock(adev, false); +} + +static void dce_v6_0_encoder_disable(struct drm_encoder *encoder) +{ + + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct amdgpu_encoder_atom_dig *dig; + + amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + + if (amdgpu_atombios_encoder_is_digital(encoder)) { + if (amdgpu_atombios_encoder_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) + dce_v6_0_afmt_enable(encoder, false); + dig = amdgpu_encoder->enc_priv; + dig->dig_encoder = -1; + } + amdgpu_encoder->active_device = 0; +} + +/* these are handled by the primary encoders */ +static void dce_v6_0_ext_prepare(struct drm_encoder *encoder) +{ + +} + +static void dce_v6_0_ext_commit(struct drm_encoder *encoder) +{ + +} + +static void +dce_v6_0_ext_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + +} + +static void dce_v6_0_ext_disable(struct drm_encoder *encoder) +{ + +} + +static void +dce_v6_0_ext_dpms(struct drm_encoder *encoder, int mode) +{ + +} + +static bool dce_v6_0_ext_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static const struct drm_encoder_helper_funcs dce_v6_0_ext_helper_funcs = { + .dpms = dce_v6_0_ext_dpms, + .mode_fixup = dce_v6_0_ext_mode_fixup, + .prepare = dce_v6_0_ext_prepare, + .mode_set = dce_v6_0_ext_mode_set, + .commit = dce_v6_0_ext_commit, + .disable = dce_v6_0_ext_disable, + /* no detect for TMDS/LVDS yet */ +}; + +static const struct drm_encoder_helper_funcs dce_v6_0_dig_helper_funcs = { + .dpms = amdgpu_atombios_encoder_dpms, + .mode_fixup = amdgpu_atombios_encoder_mode_fixup, + .prepare = dce_v6_0_encoder_prepare, + .mode_set = dce_v6_0_encoder_mode_set, + .commit = dce_v6_0_encoder_commit, + .disable = dce_v6_0_encoder_disable, + .detect = amdgpu_atombios_encoder_dig_detect, +}; + +static const struct drm_encoder_helper_funcs dce_v6_0_dac_helper_funcs = { + .dpms = amdgpu_atombios_encoder_dpms, + .mode_fixup = amdgpu_atombios_encoder_mode_fixup, + .prepare = dce_v6_0_encoder_prepare, + .mode_set = dce_v6_0_encoder_mode_set, + .commit = dce_v6_0_encoder_commit, + .detect = amdgpu_atombios_encoder_dac_detect, +}; + +static void dce_v6_0_encoder_destroy(struct drm_encoder *encoder) +{ + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + amdgpu_atombios_encoder_fini_backlight(amdgpu_encoder); + kfree(amdgpu_encoder->enc_priv); + drm_encoder_cleanup(encoder); + kfree(amdgpu_encoder); +} + +static const struct drm_encoder_funcs dce_v6_0_encoder_funcs = { + .destroy = dce_v6_0_encoder_destroy, +}; + +static void dce_v6_0_encoder_add(struct amdgpu_device *adev, + uint32_t encoder_enum, + uint32_t supported_device, + u16 caps) +{ + struct drm_device *dev = adev->ddev; + struct drm_encoder *encoder; + struct amdgpu_encoder *amdgpu_encoder; + + /* see if we already added it */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + amdgpu_encoder = to_amdgpu_encoder(encoder); + if (amdgpu_encoder->encoder_enum == encoder_enum) { + amdgpu_encoder->devices |= supported_device; + return; + } + + } + + /* add a new one */ + amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL); + if (!amdgpu_encoder) + return; + + encoder = &amdgpu_encoder->base; + switch (adev->mode_info.num_crtc) { + case 1: + encoder->possible_crtcs = 0x1; + break; + case 2: + default: + encoder->possible_crtcs = 0x3; + break; + case 4: + encoder->possible_crtcs = 0xf; + break; + case 6: + encoder->possible_crtcs = 0x3f; + break; + } + + amdgpu_encoder->enc_priv = NULL; + + amdgpu_encoder->encoder_enum = encoder_enum; + amdgpu_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + amdgpu_encoder->devices = supported_device; + amdgpu_encoder->rmx_type = RMX_OFF; + amdgpu_encoder->underscan_type = UNDERSCAN_OFF; + amdgpu_encoder->is_ext_encoder = false; + amdgpu_encoder->caps = caps; + + switch (amdgpu_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + drm_encoder_init(dev, encoder, &dce_v6_0_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + drm_encoder_helper_add(encoder, &dce_v6_0_dac_helper_funcs); + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { + amdgpu_encoder->rmx_type = RMX_FULL; + drm_encoder_init(dev, encoder, &dce_v6_0_encoder_funcs, + DRM_MODE_ENCODER_LVDS, NULL); + amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_lcd_info(amdgpu_encoder); + } else if (amdgpu_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) { + drm_encoder_init(dev, encoder, &dce_v6_0_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_dig_info(amdgpu_encoder); + } else { + drm_encoder_init(dev, encoder, &dce_v6_0_encoder_funcs, + DRM_MODE_ENCODER_TMDS, NULL); + amdgpu_encoder->enc_priv = amdgpu_atombios_encoder_get_dig_info(amdgpu_encoder); + } + drm_encoder_helper_add(encoder, &dce_v6_0_dig_helper_funcs); + break; + case ENCODER_OBJECT_ID_SI170B: + case ENCODER_OBJECT_ID_CH7303: + case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: + case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: + case ENCODER_OBJECT_ID_TITFP513: + case ENCODER_OBJECT_ID_VT1623: + case ENCODER_OBJECT_ID_HDMI_SI1930: + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: + /* these are handled by the primary encoders */ + amdgpu_encoder->is_ext_encoder = true; + if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) + drm_encoder_init(dev, encoder, &dce_v6_0_encoder_funcs, + DRM_MODE_ENCODER_LVDS, NULL); + else if (amdgpu_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) + drm_encoder_init(dev, encoder, &dce_v6_0_encoder_funcs, + DRM_MODE_ENCODER_DAC, NULL); + else + drm_encoder_init(dev, encoder, &dce_v6_0_encoder_funcs, + DRM_MODE_ENCODER_TMDS, NULL); + drm_encoder_helper_add(encoder, &dce_v6_0_ext_helper_funcs); + break; + } +} + +static const struct amdgpu_display_funcs dce_v6_0_display_funcs = { + .set_vga_render_state = &dce_v6_0_set_vga_render_state, + .bandwidth_update = &dce_v6_0_bandwidth_update, + .vblank_get_counter = &dce_v6_0_vblank_get_counter, + .vblank_wait = &dce_v6_0_vblank_wait, + .is_display_hung = &dce_v6_0_is_display_hung, + .backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level, + .backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level, + .hpd_sense = &dce_v6_0_hpd_sense, + .hpd_set_polarity = &dce_v6_0_hpd_set_polarity, + .hpd_get_gpio_reg = &dce_v6_0_hpd_get_gpio_reg, + .page_flip = &dce_v6_0_page_flip, + .page_flip_get_scanoutpos = &dce_v6_0_crtc_get_scanoutpos, + .add_encoder = &dce_v6_0_encoder_add, + .add_connector = &amdgpu_connector_add, + .stop_mc_access = &dce_v6_0_stop_mc_access, + .resume_mc_access = &dce_v6_0_resume_mc_access, +}; + +static void dce_v6_0_set_display_funcs(struct amdgpu_device *adev) +{ + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dce_v6_0_display_funcs; +} + +static const struct amdgpu_irq_src_funcs dce_v6_0_crtc_irq_funcs = { + .set = dce_v6_0_set_crtc_interrupt_state, + .process = dce_v6_0_crtc_irq, +}; + +static const struct amdgpu_irq_src_funcs dce_v6_0_pageflip_irq_funcs = { + .set = dce_v6_0_set_pageflip_interrupt_state, + .process = dce_v6_0_pageflip_irq, +}; + +static const struct amdgpu_irq_src_funcs dce_v6_0_hpd_irq_funcs = { + .set = dce_v6_0_set_hpd_interrupt_state, + .process = dce_v6_0_hpd_irq, +}; + +static void dce_v6_0_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST; + adev->crtc_irq.funcs = &dce_v6_0_crtc_irq_funcs; + + adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST; + adev->pageflip_irq.funcs = &dce_v6_0_pageflip_irq_funcs; + + adev->hpd_irq.num_types = AMDGPU_HPD_LAST; + adev->hpd_irq.funcs = &dce_v6_0_hpd_irq_funcs; +} diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h new file mode 100644 index 0000000..6a55281 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h @@ -0,0 +1,29 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __DCE_V6_0_H__ +#define __DCE_V6_0_H__ + +extern const struct amd_ip_funcs dce_v6_0_ip_funcs; + +#endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/si/sid.h b/drivers/gpu/drm/amd/include/asic_reg/si/sid.h index 15358cd..a96d930 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/si/sid.h +++ b/drivers/gpu/drm/amd/include/asic_reg/si/sid.h @@ -1976,9 +1976,6 @@ #define R600_D1GRPH_ARRAY_MODE_1D_TILED_THIN1 (2 << 20) #define R600_D1GRPH_ARRAY_MODE_2D_TILED_THIN1 (4 << 20) -#define AMDGPU_TILING_MACRO 0x1 -#define AMDGPU_TILING_MICRO 0x2 - #define R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1a45 #define R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1845 @@ -2118,36 +2115,10 @@ #define EVERGREEN_GRPH_SWAP_CONTROL 0x1a03 #define EVERGREEN_GRPH_ENDIAN_SWAP(x) (((x) & 0x3) << 0) -#define EVERGREEN_GRPH_ENDIAN_NONE 0 - -/* this object requires a surface when mapped - i.e. front buffer */ -#define RADEON_TILING_SURFACE 0x10 -#define RADEON_TILING_MICRO_SQUARE 0x20 -#define RADEON_TILING_EG_BANKW_SHIFT 8 -#define RADEON_TILING_EG_BANKW_MASK 0xf -#define RADEON_TILING_EG_BANKH_SHIFT 12 -#define RADEON_TILING_EG_BANKH_MASK 0xf -#define RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT 16 -#define RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK 0xf -#define RADEON_TILING_EG_TILE_SPLIT_SHIFT 24 -#define RADEON_TILING_EG_TILE_SPLIT_MASK 0xf -#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT 28 -#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK 0xf - -#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8 -#define SI_TILE_MODE_COLOR_1D 13 -#define SI_TILE_MODE_COLOR_1D_SCANOUT 9 -#define SI_TILE_MODE_COLOR_2D_8BPP 14 -#define SI_TILE_MODE_COLOR_2D_16BPP 15 -#define SI_TILE_MODE_COLOR_2D_32BPP 16 -#define SI_TILE_MODE_COLOR_2D_64BPP 17 -#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11 -#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12 -#define SI_TILE_MODE_DEPTH_STENCIL_1D 4 -#define SI_TILE_MODE_DEPTH_STENCIL_2D 0 -#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3 -#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3 -#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2 +# define EVERGREEN_GRPH_ENDIAN_NONE 0 +# define EVERGREEN_GRPH_ENDIAN_8IN16 1 +# define EVERGREEN_GRPH_ENDIAN_8IN32 2 +# define EVERGREEN_GRPH_ENDIAN_8IN64 3 #define EVERGREEN_D3VGA_CONTROL 0xf8 #define EVERGREEN_D4VGA_CONTROL 0xf9 -- cgit v1.1 From 098e4b6a908bd773bf30286c80b562e0150f8feb Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 15:07:29 +0800 Subject: drm/amdgpu: atombios change for dce6 to work v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v3: white space fixes Reviewed-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/atombios_crtc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c index 49a39b1..f7d236f 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c @@ -497,7 +497,13 @@ void amdgpu_atombios_crtc_set_disp_eng_pll(struct amdgpu_device *adev, * SetPixelClock provides the dividers */ args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk); - args.v6.ucPpll = ATOM_EXT_PLL1; + if (adev->asic_type == CHIP_TAHITI || + adev->asic_type == CHIP_PITCAIRN || + adev->asic_type == CHIP_VERDE || + adev->asic_type == CHIP_OLAND) + args.v6.ucPpll = ATOM_PPLL0; + else + args.v6.ucPpll = ATOM_EXT_PLL1; break; default: DRM_ERROR("Unknown table version %d %d\n", frev, crev); -- cgit v1.1 From 2cd46ad22383ab8372b86cdb5257589496099412 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 14:04:28 +0800 Subject: drm/amdgpu: add graphic pipeline implementation for si v8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v5: rebase fixes v6: rebase fixes v7: rebase fixes fix tile reg offset as noticed by Jonathan Drop some debugging remnants v8: add gfx v6 firmware versions for sysfs dump Acked-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 3288 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h | 29 + 2 files changed, 3317 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c create mode 100644 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c new file mode 100644 index 0000000..17a560c --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -0,0 +1,3288 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +#include "amdgpu.h" +#include "amdgpu_ih.h" +#include "amdgpu_gfx.h" +#include "amdgpu_ucode.h" +#include "si/clearstate_si.h" +#include "si/sid.h" + +#define GFX6_NUM_GFX_RINGS 1 +#define GFX6_NUM_COMPUTE_RINGS 2 +#define STATIC_PER_CU_PG_ENABLE (1 << 3) +#define DYN_PER_CU_PG_ENABLE (1 << 2) +#define RLC_SAVE_AND_RESTORE_STARTING_OFFSET 0x90 +#define RLC_CLEAR_STATE_DESCRIPTOR_OFFSET 0x3D + + +static void gfx_v6_0_set_ring_funcs(struct amdgpu_device *adev); +static void gfx_v6_0_set_irq_funcs(struct amdgpu_device *adev); +static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev); + +MODULE_FIRMWARE("radeon/tahiti_pfp.bin"); +MODULE_FIRMWARE("radeon/tahiti_me.bin"); +MODULE_FIRMWARE("radeon/tahiti_ce.bin"); +MODULE_FIRMWARE("radeon/tahiti_rlc.bin"); + +MODULE_FIRMWARE("radeon/pitcairn_pfp.bin"); +MODULE_FIRMWARE("radeon/pitcairn_me.bin"); +MODULE_FIRMWARE("radeon/pitcairn_ce.bin"); +MODULE_FIRMWARE("radeon/pitcairn_rlc.bin"); + +MODULE_FIRMWARE("radeon/verde_pfp.bin"); +MODULE_FIRMWARE("radeon/verde_me.bin"); +MODULE_FIRMWARE("radeon/verde_ce.bin"); +MODULE_FIRMWARE("radeon/verde_rlc.bin"); + +MODULE_FIRMWARE("radeon/oland_pfp.bin"); +MODULE_FIRMWARE("radeon/oland_me.bin"); +MODULE_FIRMWARE("radeon/oland_ce.bin"); +MODULE_FIRMWARE("radeon/oland_rlc.bin"); + +MODULE_FIRMWARE("radeon/hainan_pfp.bin"); +MODULE_FIRMWARE("radeon/hainan_me.bin"); +MODULE_FIRMWARE("radeon/hainan_ce.bin"); +MODULE_FIRMWARE("radeon/hainan_rlc.bin"); + +static u32 gfx_v6_0_get_csb_size(struct amdgpu_device *adev); +static void gfx_v6_0_get_csb_buffer(struct amdgpu_device *adev, volatile u32 *buffer); +//static void gfx_v6_0_init_cp_pg_table(struct amdgpu_device *adev); +static void gfx_v6_0_init_pg(struct amdgpu_device *adev); + + +static const u32 verde_rlc_save_restore_register_list[] = +{ + (0x8000 << 16) | (0x98f4 >> 2), + 0x00000000, + (0x8040 << 16) | (0x98f4 >> 2), + 0x00000000, + (0x8000 << 16) | (0xe80 >> 2), + 0x00000000, + (0x8040 << 16) | (0xe80 >> 2), + 0x00000000, + (0x8000 << 16) | (0x89bc >> 2), + 0x00000000, + (0x8040 << 16) | (0x89bc >> 2), + 0x00000000, + (0x8000 << 16) | (0x8c1c >> 2), + 0x00000000, + (0x8040 << 16) | (0x8c1c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x98f0 >> 2), + 0x00000000, + (0x9c00 << 16) | (0xe7c >> 2), + 0x00000000, + (0x8000 << 16) | (0x9148 >> 2), + 0x00000000, + (0x8040 << 16) | (0x9148 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9150 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x897c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8d8c >> 2), + 0x00000000, + (0x9c00 << 16) | (0xac54 >> 2), + 0X00000000, + 0x3, + (0x9c00 << 16) | (0x98f8 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9910 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9914 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9918 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x991c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9920 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9924 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9928 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x992c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9930 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9934 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9938 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x993c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9940 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9944 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9948 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x994c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9950 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9954 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9958 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x995c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9960 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9964 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9968 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x996c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9970 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9974 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9978 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x997c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9980 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9984 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9988 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x998c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8c00 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8c14 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8c04 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8c08 >> 2), + 0x00000000, + (0x8000 << 16) | (0x9b7c >> 2), + 0x00000000, + (0x8040 << 16) | (0x9b7c >> 2), + 0x00000000, + (0x8000 << 16) | (0xe84 >> 2), + 0x00000000, + (0x8040 << 16) | (0xe84 >> 2), + 0x00000000, + (0x8000 << 16) | (0x89c0 >> 2), + 0x00000000, + (0x8040 << 16) | (0x89c0 >> 2), + 0x00000000, + (0x8000 << 16) | (0x914c >> 2), + 0x00000000, + (0x8040 << 16) | (0x914c >> 2), + 0x00000000, + (0x8000 << 16) | (0x8c20 >> 2), + 0x00000000, + (0x8040 << 16) | (0x8c20 >> 2), + 0x00000000, + (0x8000 << 16) | (0x9354 >> 2), + 0x00000000, + (0x8040 << 16) | (0x9354 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9060 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9364 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9100 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x913c >> 2), + 0x00000000, + (0x8000 << 16) | (0x90e0 >> 2), + 0x00000000, + (0x8000 << 16) | (0x90e4 >> 2), + 0x00000000, + (0x8000 << 16) | (0x90e8 >> 2), + 0x00000000, + (0x8040 << 16) | (0x90e0 >> 2), + 0x00000000, + (0x8040 << 16) | (0x90e4 >> 2), + 0x00000000, + (0x8040 << 16) | (0x90e8 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8bcc >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8b24 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x88c4 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8e50 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8c0c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8e58 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8e5c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9508 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x950c >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9494 >> 2), + 0x00000000, + (0x9c00 << 16) | (0xac0c >> 2), + 0x00000000, + (0x9c00 << 16) | (0xac10 >> 2), + 0x00000000, + (0x9c00 << 16) | (0xac14 >> 2), + 0x00000000, + (0x9c00 << 16) | (0xae00 >> 2), + 0x00000000, + (0x9c00 << 16) | (0xac08 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x88d4 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x88c8 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x88cc >> 2), + 0x00000000, + (0x9c00 << 16) | (0x89b0 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8b10 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x8a14 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9830 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9834 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9838 >> 2), + 0x00000000, + (0x9c00 << 16) | (0x9a10 >> 2), + 0x00000000, + (0x8000 << 16) | (0x9870 >> 2), + 0x00000000, + (0x8000 << 16) | (0x9874 >> 2), + 0x00000000, + (0x8001 << 16) | (0x9870 >> 2), + 0x00000000, + (0x8001 << 16) | (0x9874 >> 2), + 0x00000000, + (0x8040 << 16) | (0x9870 >> 2), + 0x00000000, + (0x8040 << 16) | (0x9874 >> 2), + 0x00000000, + (0x8041 << 16) | (0x9870 >> 2), + 0x00000000, + (0x8041 << 16) | (0x9874 >> 2), + 0x00000000, + 0x00000000 +}; + +static int gfx_v6_0_init_microcode(struct amdgpu_device *adev) +{ + const char *chip_name; + char fw_name[30]; + int err; + const struct gfx_firmware_header_v1_0 *cp_hdr; + const struct rlc_firmware_header_v1_0 *rlc_hdr; + + DRM_DEBUG("\n"); + + switch (adev->asic_type) { + case CHIP_TAHITI: + chip_name = "tahiti"; + break; + case CHIP_PITCAIRN: + chip_name = "pitcairn"; + break; + case CHIP_VERDE: + chip_name = "verde"; + break; + case CHIP_OLAND: + chip_name = "oland"; + break; + case CHIP_HAINAN: + chip_name = "hainan"; + break; + default: BUG(); + } + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); + err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev); + if (err) + goto out; + err = amdgpu_ucode_validate(adev->gfx.pfp_fw); + if (err) + goto out; + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data; + adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); + err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev); + if (err) + goto out; + err = amdgpu_ucode_validate(adev->gfx.me_fw); + if (err) + goto out; + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data; + adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name); + err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev); + if (err) + goto out; + err = amdgpu_ucode_validate(adev->gfx.ce_fw); + if (err) + goto out; + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data; + adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name); + err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev); + if (err) + goto out; + err = amdgpu_ucode_validate(adev->gfx.rlc_fw); + rlc_hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data; + adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version); + adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version); + +out: + if (err) { + printk(KERN_ERR + "gfx6: Failed to load firmware \"%s\"\n", + fw_name); + release_firmware(adev->gfx.pfp_fw); + adev->gfx.pfp_fw = NULL; + release_firmware(adev->gfx.me_fw); + adev->gfx.me_fw = NULL; + release_firmware(adev->gfx.ce_fw); + adev->gfx.ce_fw = NULL; + release_firmware(adev->gfx.rlc_fw); + adev->gfx.rlc_fw = NULL; + } + return err; +} + +static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev) +{ + const u32 num_tile_mode_states = 32; + u32 reg_offset, gb_tile_moden, split_equal_to_row_size; + + switch (adev->gfx.config.mem_row_size_in_kb) { + case 1: + split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_1KB; + break; + case 2: + default: + split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_2KB; + break; + case 4: + split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_4KB; + break; + } + + if (adev->asic_type == CHIP_VERDE || + adev->asic_type == CHIP_OLAND || + adev->asic_type == CHIP_HAINAN) { + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { + switch (reg_offset) { + case 0: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 1: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 2: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 3: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 4: + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 5: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 6: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 7: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 8: + gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 9: + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 10: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 11: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 12: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 13: + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 14: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 15: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 16: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 17: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P4_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 21: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 22: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 23: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 24: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 25: + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) | + NUM_BANKS(ADDR_SURF_8_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + default: + gb_tile_moden = 0; + break; + } + adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden; + WREG32(GB_TILE_MODE0 + reg_offset, gb_tile_moden); + } + } else if ((adev->asic_type == CHIP_TAHITI) || (adev->asic_type == CHIP_PITCAIRN)) { + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { + switch (reg_offset) { + case 0: /* non-AA compressed depth or any compressed stencil */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 1: /* 2xAA/4xAA compressed depth only */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 2: /* 8xAA compressed depth only */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 3: /* 2xAA/4xAA compressed depth with stencil (for depth buffer) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 4: /* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 5: /* Uncompressed 16bpp depth - and stencil buffer allocated with it */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 6: /* Uncompressed 32bpp depth - and stencil buffer allocated with it */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 7: /* Uncompressed 8bpp stencil without depth (drivers typically do not use) */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 8: /* 1D and 1D Array Surfaces */ + gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 9: /* Displayable maps. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 10: /* Display 8bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 11: /* Display 16bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 12: /* Display 32bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 13: /* Thin. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 14: /* Thin 8 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 15: /* Thin 16 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 16: /* Thin 32 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 17: /* Thin 64 bpp. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(split_equal_to_row_size) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + case 21: /* 8 bpp PRT. */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 22: /* 16 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4)); + break; + case 23: /* 32 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 24: /* 64 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + NUM_BANKS(ADDR_SURF_16_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2)); + break; + case 25: /* 128 bpp PRT */ + gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) | + NUM_BANKS(ADDR_SURF_8_BANK) | + BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1)); + break; + default: + gb_tile_moden = 0; + break; + } + adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden; + WREG32(GB_TILE_MODE0 + reg_offset, gb_tile_moden); + } + } else{ + + DRM_ERROR("unknown asic: 0x%x\n", adev->asic_type); + } + +} + +static void gfx_v6_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, + u32 sh_num, u32 instance) +{ + u32 data; + + if (instance == 0xffffffff) + data = INSTANCE_BROADCAST_WRITES; + else + data = INSTANCE_INDEX(instance); + + if ((se_num == 0xffffffff) && (sh_num == 0xffffffff)) + data |= SH_BROADCAST_WRITES | SE_BROADCAST_WRITES; + else if (se_num == 0xffffffff) + data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num); + else if (sh_num == 0xffffffff) + data |= SH_BROADCAST_WRITES | SE_INDEX(se_num); + else + data |= SH_INDEX(sh_num) | SE_INDEX(se_num); + WREG32(GRBM_GFX_INDEX, data); +} + +static u32 gfx_v6_0_create_bitmask(u32 bit_width) +{ + u32 i, mask = 0; + + for (i = 0; i < bit_width; i++) { + mask <<= 1; + mask |= 1; + } + return mask; +} + +static u32 gfx_v6_0_get_rb_disabled(struct amdgpu_device *adev, + u32 max_rb_num_per_se, + u32 sh_per_se) +{ + u32 data, mask; + + data = RREG32(CC_RB_BACKEND_DISABLE); + data &= BACKEND_DISABLE_MASK; + data |= RREG32(GC_USER_RB_BACKEND_DISABLE); + + data >>= BACKEND_DISABLE_SHIFT; + + mask = gfx_v6_0_create_bitmask(max_rb_num_per_se / sh_per_se); + + return data & mask; +} + +static void gfx_v6_0_setup_rb(struct amdgpu_device *adev, + u32 se_num, u32 sh_per_se, + u32 max_rb_num_per_se) +{ + int i, j; + u32 data, mask; + u32 disabled_rbs = 0; + u32 enabled_rbs = 0; + + for (i = 0; i < se_num; i++) { + for (j = 0; j < sh_per_se; j++) { + gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff); + data = gfx_v6_0_get_rb_disabled(adev, max_rb_num_per_se, sh_per_se); + disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH); + } + } + gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + + mask = 1; + for (i = 0; i < max_rb_num_per_se * se_num; i++) { + if (!(disabled_rbs & mask)) + enabled_rbs |= mask; + mask <<= 1; + } + + adev->gfx.config.backend_enable_mask = enabled_rbs; + adev->gfx.config.num_rbs = hweight32(enabled_rbs); + + for (i = 0; i < se_num; i++) { + gfx_v6_0_select_se_sh(adev, i, 0xffffffff, 0xffffffff); + data = 0; + for (j = 0; j < sh_per_se; j++) { + switch (enabled_rbs & 3) { + case 1: + data |= (RASTER_CONFIG_RB_MAP_0 << (i * sh_per_se + j) * 2); + break; + case 2: + data |= (RASTER_CONFIG_RB_MAP_3 << (i * sh_per_se + j) * 2); + break; + case 3: + default: + data |= (RASTER_CONFIG_RB_MAP_2 << (i * sh_per_se + j) * 2); + break; + } + enabled_rbs >>= 2; + } + WREG32(PA_SC_RASTER_CONFIG, data); + } + gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); +} +/* +static void gmc_v6_0_init_compute_vmid(struct amdgpu_device *adev) +{ +} +*/ + +static u32 gfx_v6_0_get_cu_enabled(struct amdgpu_device *adev, u32 cu_per_sh) +{ + u32 data, mask; + + data = RREG32(CC_GC_SHADER_ARRAY_CONFIG); + data &= INACTIVE_CUS_MASK; + data |= RREG32(GC_USER_SHADER_ARRAY_CONFIG); + + data >>= INACTIVE_CUS_SHIFT; + + mask = gfx_v6_0_create_bitmask(cu_per_sh); + + return ~data & mask; +} + + +static void gfx_v6_0_setup_spi(struct amdgpu_device *adev, + u32 se_num, u32 sh_per_se, + u32 cu_per_sh) +{ + int i, j, k; + u32 data, mask; + u32 active_cu = 0; + + for (i = 0; i < se_num; i++) { + for (j = 0; j < sh_per_se; j++) { + gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff); + data = RREG32(SPI_STATIC_THREAD_MGMT_3); + active_cu = gfx_v6_0_get_cu_enabled(adev, cu_per_sh); + + mask = 1; + for (k = 0; k < 16; k++) { + mask <<= k; + if (active_cu & mask) { + data &= ~mask; + WREG32(SPI_STATIC_THREAD_MGMT_3, data); + break; + } + } + } + } + gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); +} + +static void gfx_v6_0_gpu_init(struct amdgpu_device *adev) +{ + u32 gb_addr_config = 0; + u32 mc_shared_chmap, mc_arb_ramcfg; + u32 sx_debug_1; + u32 hdp_host_path_cntl; + u32 tmp; + + switch (adev->asic_type) { + case CHIP_TAHITI: + adev->gfx.config.max_shader_engines = 2; + adev->gfx.config.max_tile_pipes = 12; + adev->gfx.config.max_cu_per_sh = 8; + adev->gfx.config.max_sh_per_se = 2; + adev->gfx.config.max_backends_per_se = 4; + adev->gfx.config.max_texture_channel_caches = 12; + adev->gfx.config.max_gprs = 256; + adev->gfx.config.max_gs_threads = 32; + adev->gfx.config.max_hw_contexts = 8; + + adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; + adev->gfx.config.sc_prim_fifo_size_backend = 0x100; + adev->gfx.config.sc_hiz_tile_fifo_size = 0x30; + adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_PITCAIRN: + adev->gfx.config.max_shader_engines = 2; + adev->gfx.config.max_tile_pipes = 8; + adev->gfx.config.max_cu_per_sh = 5; + adev->gfx.config.max_sh_per_se = 2; + adev->gfx.config.max_backends_per_se = 4; + adev->gfx.config.max_texture_channel_caches = 8; + adev->gfx.config.max_gprs = 256; + adev->gfx.config.max_gs_threads = 32; + adev->gfx.config.max_hw_contexts = 8; + + adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; + adev->gfx.config.sc_prim_fifo_size_backend = 0x100; + adev->gfx.config.sc_hiz_tile_fifo_size = 0x30; + adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN; + break; + + case CHIP_VERDE: + adev->gfx.config.max_shader_engines = 1; + adev->gfx.config.max_tile_pipes = 4; + adev->gfx.config.max_cu_per_sh = 5; + adev->gfx.config.max_sh_per_se = 2; + adev->gfx.config.max_backends_per_se = 4; + adev->gfx.config.max_texture_channel_caches = 4; + adev->gfx.config.max_gprs = 256; + adev->gfx.config.max_gs_threads = 32; + adev->gfx.config.max_hw_contexts = 8; + + adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; + adev->gfx.config.sc_prim_fifo_size_backend = 0x40; + adev->gfx.config.sc_hiz_tile_fifo_size = 0x30; + adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = VERDE_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_OLAND: + adev->gfx.config.max_shader_engines = 1; + adev->gfx.config.max_tile_pipes = 4; + adev->gfx.config.max_cu_per_sh = 6; + adev->gfx.config.max_sh_per_se = 1; + adev->gfx.config.max_backends_per_se = 2; + adev->gfx.config.max_texture_channel_caches = 4; + adev->gfx.config.max_gprs = 256; + adev->gfx.config.max_gs_threads = 16; + adev->gfx.config.max_hw_contexts = 8; + + adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; + adev->gfx.config.sc_prim_fifo_size_backend = 0x40; + adev->gfx.config.sc_hiz_tile_fifo_size = 0x30; + adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = VERDE_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_HAINAN: + adev->gfx.config.max_shader_engines = 1; + adev->gfx.config.max_tile_pipes = 4; + adev->gfx.config.max_cu_per_sh = 5; + adev->gfx.config.max_sh_per_se = 1; + adev->gfx.config.max_backends_per_se = 1; + adev->gfx.config.max_texture_channel_caches = 2; + adev->gfx.config.max_gprs = 256; + adev->gfx.config.max_gs_threads = 16; + adev->gfx.config.max_hw_contexts = 8; + + adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; + adev->gfx.config.sc_prim_fifo_size_backend = 0x40; + adev->gfx.config.sc_hiz_tile_fifo_size = 0x30; + adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130; + gb_addr_config = HAINAN_GB_ADDR_CONFIG_GOLDEN; + break; + default: + BUG(); + break; + } + + WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); + WREG32(SRBM_INT_CNTL, 1); + WREG32(SRBM_INT_ACK, 1); + + WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); + + mc_shared_chmap = RREG32(MC_SHARED_CHMAP); + mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + + adev->gfx.config.num_tile_pipes = adev->gfx.config.max_tile_pipes; + adev->gfx.config.mem_max_burst_length_bytes = 256; + tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; + adev->gfx.config.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; + if (adev->gfx.config.mem_row_size_in_kb > 4) + adev->gfx.config.mem_row_size_in_kb = 4; + adev->gfx.config.shader_engine_tile_size = 32; + adev->gfx.config.num_gpus = 1; + adev->gfx.config.multi_gpu_tile_size = 64; + + gb_addr_config &= ~ROW_SIZE_MASK; + switch (adev->gfx.config.mem_row_size_in_kb) { + case 1: + default: + gb_addr_config |= ROW_SIZE(0); + break; + case 2: + gb_addr_config |= ROW_SIZE(1); + break; + case 4: + gb_addr_config |= ROW_SIZE(2); + break; + } + adev->gfx.config.gb_addr_config = gb_addr_config; + + WREG32(GB_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CALC, gb_addr_config); + WREG32(HDP_ADDR_CONFIG, gb_addr_config); + WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config); + WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config); +#if 0 + if (adev->has_uvd) { + WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config); + WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config); + WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config); + } +#endif + gfx_v6_0_tiling_mode_table_init(adev); + + gfx_v6_0_setup_rb(adev, adev->gfx.config.max_shader_engines, + adev->gfx.config.max_sh_per_se, + adev->gfx.config.max_backends_per_se); + + gfx_v6_0_setup_spi(adev, adev->gfx.config.max_shader_engines, + adev->gfx.config.max_sh_per_se, + adev->gfx.config.max_cu_per_sh); + + gfx_v6_0_get_cu_info(adev); + + WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | + ROQ_IB2_START(0x2b))); + WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); + + sx_debug_1 = RREG32(SX_DEBUG_1); + WREG32(SX_DEBUG_1, sx_debug_1); + + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4)); + + WREG32(PA_SC_FIFO_SIZE, (SC_FRONTEND_PRIM_FIFO_SIZE(adev->gfx.config.sc_prim_fifo_size_frontend) | + SC_BACKEND_PRIM_FIFO_SIZE(adev->gfx.config.sc_prim_fifo_size_backend) | + SC_HIZ_TILE_FIFO_SIZE(adev->gfx.config.sc_hiz_tile_fifo_size) | + SC_EARLYZ_TILE_FIFO_SIZE(adev->gfx.config.sc_earlyz_tile_fifo_size))); + + WREG32(VGT_NUM_INSTANCES, 1); + + WREG32(CP_PERFMON_CNTL, 0); + + WREG32(SQ_CONFIG, 0); + + WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | + FORCE_EOV_MAX_REZ_CNT(255))); + + WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) | + AUTO_INVLD_EN(ES_AND_GS_AUTO)); + + WREG32(VGT_GS_VERTEX_REUSE, 16); + WREG32(PA_SC_LINE_STIPPLE_STATE, 0); + + WREG32(CB_PERFCOUNTER0_SELECT0, 0); + WREG32(CB_PERFCOUNTER0_SELECT1, 0); + WREG32(CB_PERFCOUNTER1_SELECT0, 0); + WREG32(CB_PERFCOUNTER1_SELECT1, 0); + WREG32(CB_PERFCOUNTER2_SELECT0, 0); + WREG32(CB_PERFCOUNTER2_SELECT1, 0); + WREG32(CB_PERFCOUNTER3_SELECT0, 0); + WREG32(CB_PERFCOUNTER3_SELECT1, 0); + + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + + WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); + + udelay(50); + +} + + +static void gfx_v6_0_scratch_init(struct amdgpu_device *adev) +{ + int i; + + adev->gfx.scratch.num_reg = 7; + adev->gfx.scratch.reg_base = SCRATCH_REG0; + for (i = 0; i < adev->gfx.scratch.num_reg; i++) { + adev->gfx.scratch.free[i] = true; + adev->gfx.scratch.reg[i] = adev->gfx.scratch.reg_base + i; + } +} + +static int gfx_v6_0_ring_test_ring(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + uint32_t scratch; + uint32_t tmp = 0; + unsigned i; + int r; + + r = amdgpu_gfx_scratch_get(adev, &scratch); + if (r) { + DRM_ERROR("amdgpu: cp failed to get scratch reg (%d).\n", r); + return r; + } + WREG32(scratch, 0xCAFEDEAD); + + r = amdgpu_ring_alloc(ring, 3); + if (r) { + DRM_ERROR("amdgpu: cp failed to lock ring %d (%d).\n", ring->idx, r); + amdgpu_gfx_scratch_free(adev, scratch); + return r; + } + amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + amdgpu_ring_write(ring, (scratch - PACKET3_SET_CONFIG_REG_START)); + amdgpu_ring_write(ring, 0xDEADBEEF); + amdgpu_ring_commit(ring); + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) + break; + DRM_UDELAY(1); + } + if (i < adev->usec_timeout) { + DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); + } else { + DRM_ERROR("amdgpu: ring %d test failed (scratch(0x%04X)=0x%08X)\n", + ring->idx, scratch, tmp); + r = -EINVAL; + } + amdgpu_gfx_scratch_free(adev, scratch); + return r; +} + +static void gfx_v6_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) +{ + /* flush hdp cache */ + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) | + WRITE_DATA_DST_SEL(0))); + amdgpu_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, 0x1); +} + +/** + * gfx_v6_0_ring_emit_hdp_invalidate - emit an hdp invalidate on the cp + * + * @adev: amdgpu_device pointer + * @ridx: amdgpu ring index + * + * Emits an hdp invalidate on the cp. + */ +static void gfx_v6_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring) +{ + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) | + WRITE_DATA_DST_SEL(0))); + amdgpu_ring_write(ring, HDP_DEBUG0); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, 0x1); +} + +static void gfx_v6_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, + u64 seq, unsigned flags) +{ + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; + bool int_sel = flags & AMDGPU_FENCE_FLAG_INT; + /* flush read cache over gart */ + amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + amdgpu_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START)); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + amdgpu_ring_write(ring, PACKET3_TCL1_ACTION_ENA | + PACKET3_TC_ACTION_ENA | + PACKET3_SH_KCACHE_ACTION_ENA | + PACKET3_SH_ICACHE_ACTION_ENA); + amdgpu_ring_write(ring, 0xFFFFFFFF); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, 10); /* poll interval */ + /* EVENT_WRITE_EOP - flush caches, send int */ + amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); + amdgpu_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5)); + amdgpu_ring_write(ring, addr & 0xfffffffc); + amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) | + DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0)); + amdgpu_ring_write(ring, lower_32_bits(seq)); + amdgpu_ring_write(ring, upper_32_bits(seq)); +} + +static void gfx_v6_0_ring_emit_fence_compute(struct amdgpu_ring *ring, + u64 addr, u64 seq, + unsigned flags) +{ + gfx_v6_0_ring_emit_fence_gfx(ring, addr, seq, flags); +} + + +static void gfx_v6_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, + struct amdgpu_ib *ib, + unsigned vm_id, bool ctx_switch) +{ + u32 header, control = 0; + + /* insert SWITCH_BUFFER packet before first IB in the ring frame */ + if (ctx_switch) { + amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); + amdgpu_ring_write(ring, 0); + } + + if (ib->flags & AMDGPU_IB_FLAG_CE) + header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); + else + header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); + + control |= ib->length_dw | (vm_id << 24); + + amdgpu_ring_write(ring, header); + amdgpu_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 0) | +#endif + (ib->gpu_addr & 0xFFFFFFFC)); + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); + amdgpu_ring_write(ring, control); +} + +static void gfx_v6_0_ring_emit_ib_compute(struct amdgpu_ring *ring, + struct amdgpu_ib *ib, + unsigned vm_id, bool ctx_switch) +{ + gfx_v6_0_ring_emit_ib_gfx(ring, ib, vm_id, ctx_switch); +} + +/** + * gfx_v6_0_ring_test_ib - basic ring IB test + * + * @ring: amdgpu_ring structure holding ring information + * + * Allocate an IB and execute it on the gfx ring (SI). + * Provides a basic gfx ring test to verify that IBs are working. + * Returns 0 on success, error on failure. + */ +static int gfx_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) +{ + struct amdgpu_device *adev = ring->adev; + struct amdgpu_ib ib; + struct fence *f = NULL; + uint32_t scratch; + uint32_t tmp = 0; + long r; + + r = amdgpu_gfx_scratch_get(adev, &scratch); + if (r) { + DRM_ERROR("amdgpu: failed to get scratch reg (%ld).\n", r); + return r; + } + WREG32(scratch, 0xCAFEDEAD); + memset(&ib, 0, sizeof(ib)); + r = amdgpu_ib_get(adev, NULL, 256, &ib); + if (r) { + DRM_ERROR("amdgpu: failed to get ib (%ld).\n", r); + goto err1; + } + ib.ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1); + ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_START)); + ib.ptr[2] = 0xDEADBEEF; + ib.length_dw = 3; + + r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f); + if (r) + goto err2; + + r = fence_wait_timeout(f, false, timeout); + if (r == 0) { + DRM_ERROR("amdgpu: IB test timed out\n"); + r = -ETIMEDOUT; + goto err2; + } else if (r < 0) { + DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); + goto err2; + } + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) { + DRM_INFO("ib test on ring %d succeeded\n", ring->idx); + r = 0; + } else { + DRM_ERROR("amdgpu: ib test failed (scratch(0x%04X)=0x%08X)\n", + scratch, tmp); + r = -EINVAL; + } + +err2: + amdgpu_ib_free(adev, &ib, NULL); + fence_put(f); +err1: + amdgpu_gfx_scratch_free(adev, scratch); + return r; +} + +static void gfx_v6_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable) +{ + int i; + if (enable) + WREG32(CP_ME_CNTL, 0); + else { + WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); + WREG32(SCRATCH_UMSK, 0); + for (i = 0; i < adev->gfx.num_gfx_rings; i++) + adev->gfx.gfx_ring[i].ready = false; + for (i = 0; i < adev->gfx.num_compute_rings; i++) + adev->gfx.compute_ring[i].ready = false; + } + udelay(50); +} + +static int gfx_v6_0_cp_gfx_load_microcode(struct amdgpu_device *adev) +{ + unsigned i; + const struct gfx_firmware_header_v1_0 *pfp_hdr; + const struct gfx_firmware_header_v1_0 *ce_hdr; + const struct gfx_firmware_header_v1_0 *me_hdr; + const __le32 *fw_data; + u32 fw_size; + + if (!adev->gfx.me_fw || !adev->gfx.pfp_fw || !adev->gfx.ce_fw) + return -EINVAL; + + gfx_v6_0_cp_gfx_enable(adev, false); + pfp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data; + ce_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data; + me_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data; + + amdgpu_ucode_print_gfx_hdr(&pfp_hdr->header); + amdgpu_ucode_print_gfx_hdr(&ce_hdr->header); + amdgpu_ucode_print_gfx_hdr(&me_hdr->header); + + /* PFP */ + fw_data = (const __le32 *) + (adev->gfx.pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes)); + fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4; + WREG32(CP_PFP_UCODE_ADDR, 0); + for (i = 0; i < fw_size; i++) + WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++)); + WREG32(CP_PFP_UCODE_ADDR, 0); + + /* CE */ + fw_data = (const __le32 *) + (adev->gfx.ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes)); + fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4; + WREG32(CP_CE_UCODE_ADDR, 0); + for (i = 0; i < fw_size; i++) + WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++)); + WREG32(CP_CE_UCODE_ADDR, 0); + + /* ME */ + fw_data = (const __be32 *) + (adev->gfx.me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes)); + fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4; + WREG32(CP_ME_RAM_WADDR, 0); + for (i = 0; i < fw_size; i++) + WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++)); + WREG32(CP_ME_RAM_WADDR, 0); + + + WREG32(CP_PFP_UCODE_ADDR, 0); + WREG32(CP_CE_UCODE_ADDR, 0); + WREG32(CP_ME_RAM_WADDR, 0); + WREG32(CP_ME_RAM_RADDR, 0); + return 0; +} + +static int gfx_v6_0_cp_gfx_start(struct amdgpu_device *adev) +{ + const struct cs_section_def *sect = NULL; + const struct cs_extent_def *ext = NULL; + struct amdgpu_ring *ring = &adev->gfx.gfx_ring[0]; + int r, i; + + r = amdgpu_ring_alloc(ring, 7 + 4); + if (r) { + DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r); + return r; + } + amdgpu_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); + amdgpu_ring_write(ring, 0x1); + amdgpu_ring_write(ring, 0x0); + amdgpu_ring_write(ring, adev->gfx.config.max_hw_contexts - 1); + amdgpu_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, 0); + + amdgpu_ring_write(ring, PACKET3(PACKET3_SET_BASE, 2)); + amdgpu_ring_write(ring, PACKET3_BASE_INDEX(CE_PARTITION_BASE)); + amdgpu_ring_write(ring, 0xc000); + amdgpu_ring_write(ring, 0xe000); + amdgpu_ring_commit(ring); + + gfx_v6_0_cp_gfx_enable(adev, true); + + r = amdgpu_ring_alloc(ring, gfx_v6_0_get_csb_size(adev) + 10); + if (r) { + DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r); + return r; + } + + amdgpu_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + amdgpu_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); + + for (sect = adev->gfx.rlc.cs_data; sect->section != NULL; ++sect) { + for (ext = sect->section; ext->extent != NULL; ++ext) { + if (sect->id == SECT_CONTEXT) { + amdgpu_ring_write(ring, + PACKET3(PACKET3_SET_CONTEXT_REG, ext->reg_count)); + amdgpu_ring_write(ring, ext->reg_index - PACKET3_SET_CONTEXT_REG_START); + for (i = 0; i < ext->reg_count; i++) + amdgpu_ring_write(ring, ext->extent[i]); + } + } + } + + amdgpu_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + amdgpu_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); + + amdgpu_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); + amdgpu_ring_write(ring, 0); + + amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + amdgpu_ring_write(ring, 0x00000316); + amdgpu_ring_write(ring, 0x0000000e); + amdgpu_ring_write(ring, 0x00000010); + + amdgpu_ring_commit(ring); + + return 0; +} + +static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev) +{ + struct amdgpu_ring *ring; + u32 tmp; + u32 rb_bufsz; + int r; + u64 rptr_addr; + + WREG32(CP_SEM_WAIT_TIMER, 0x0); + WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); + + /* Set the write pointer delay */ + WREG32(CP_RB_WPTR_DELAY, 0); + + WREG32(CP_DEBUG, 0); + WREG32(SCRATCH_ADDR, 0); + + /* ring 0 - compute and gfx */ + /* Set ring buffer size */ + ring = &adev->gfx.gfx_ring[0]; + rb_bufsz = order_base_2(ring->ring_size / 8); + tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; + +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB0_CNTL, tmp); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB0_WPTR, ring->wptr); + + /* set the wb address whether it's enabled or not */ + rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); + WREG32(CP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr)); + WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF); + + WREG32(SCRATCH_UMSK, 0); + + mdelay(1); + WREG32(CP_RB0_CNTL, tmp); + + WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); + + /* start the rings */ + gfx_v6_0_cp_gfx_start(adev); + ring->ready = true; + r = amdgpu_ring_test_ring(ring); + if (r) { + ring->ready = false; + return r; + } + + return 0; +} + +static u32 gfx_v6_0_ring_get_rptr_gfx(struct amdgpu_ring *ring) +{ + u32 rptr; + + rptr = ring->adev->wb.wb[ring->rptr_offs]; + + return rptr; +} + +static u32 gfx_v6_0_ring_get_wptr_gfx(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + u32 wptr; + + wptr = RREG32(CP_RB0_WPTR); + + return wptr; +} + +static void gfx_v6_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + + WREG32(CP_RB0_WPTR, ring->wptr); + (void)RREG32(CP_RB0_WPTR); +} + +static u32 gfx_v6_0_ring_get_rptr_compute(struct amdgpu_ring *ring) +{ + u32 rptr = ring->adev->wb.wb[ring->rptr_offs]; + + return rptr; +} + +static u32 gfx_v6_0_ring_get_wptr_compute(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + u32 wptr; + + if (ring == &adev->gfx.compute_ring[0]) { + wptr = RREG32(CP_RB1_WPTR); + } else if (ring == &adev->gfx.compute_ring[1]) { + wptr = RREG32(CP_RB2_WPTR); + } else { + BUG(); + } + + return wptr; +} + +static void gfx_v6_0_ring_set_wptr_compute(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + + if (ring == &adev->gfx.compute_ring[0]) { + WREG32(CP_RB1_WPTR, ring->wptr); + (void)RREG32(CP_RB1_WPTR); + } else if (ring == &adev->gfx.compute_ring[1]) { + WREG32(CP_RB2_WPTR, ring->wptr); + (void)RREG32(CP_RB2_WPTR); + } else { + BUG(); + } + +} + + +static void gfx_v6_0_cp_compute_fini(struct amdgpu_device *adev) +{ + int i, r; + + for (i = 0; i < adev->gfx.num_compute_rings; i++) { + struct amdgpu_ring *ring = &adev->gfx.compute_ring[i]; + + if (ring->mqd_obj) { + r = amdgpu_bo_reserve(ring->mqd_obj, false); + if (unlikely(r != 0)) + dev_warn(adev->dev, "(%d) reserve MQD bo failed\n", r); + + amdgpu_bo_unpin(ring->mqd_obj); + amdgpu_bo_unreserve(ring->mqd_obj); + + amdgpu_bo_unref(&ring->mqd_obj); + ring->mqd_obj = NULL; + } + } +} + +static int gfx_v6_0_cp_compute_resume(struct amdgpu_device *adev) +{ + struct amdgpu_ring *ring; + u32 tmp; + u32 rb_bufsz; + int r; + u64 rptr_addr; + + /* ring1 - compute only */ + /* Set ring buffer size */ + + ring = &adev->gfx.compute_ring[0]; + rb_bufsz = order_base_2(ring->ring_size / 8); + tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB1_CNTL, tmp); + + WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB1_WPTR, ring->wptr); + + + rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); + WREG32(CP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr)); + WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF); + + mdelay(1); + WREG32(CP_RB1_CNTL, tmp); + + WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); + + ring = &adev->gfx.compute_ring[1]; + rb_bufsz = order_base_2(ring->ring_size / 8); + tmp = (order_base_2(AMDGPU_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB2_CNTL, tmp); + + WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB2_WPTR, ring->wptr); + rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); + WREG32(CP_RB2_RPTR_ADDR, lower_32_bits(rptr_addr)); + WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF); + + mdelay(1); + WREG32(CP_RB2_CNTL, tmp); + + WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); + + adev->gfx.compute_ring[0].ready = true; + adev->gfx.compute_ring[1].ready = true; + + r = amdgpu_ring_test_ring(&adev->gfx.compute_ring[0]); + if (r) { + adev->gfx.compute_ring[0].ready = false; + return r; + } + + r = amdgpu_ring_test_ring(&adev->gfx.compute_ring[1]); + if (r) { + adev->gfx.compute_ring[1].ready = false; + return r; + } + + return 0; +} + +static void gfx_v6_0_cp_enable(struct amdgpu_device *adev, bool enable) +{ + gfx_v6_0_cp_gfx_enable(adev, enable); +} + +static int gfx_v6_0_cp_load_microcode(struct amdgpu_device *adev) +{ + int r; + + r = gfx_v6_0_cp_gfx_load_microcode(adev); + + return r; + +} + +static void gfx_v6_0_enable_gui_idle_interrupt(struct amdgpu_device *adev, + bool enable) +{ + u32 tmp = RREG32(CP_INT_CNTL_RING0); + u32 mask; + int i; + + if (enable) + tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + else + tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(CP_INT_CNTL_RING0, tmp); + + if (!enable) { + /* read a gfx register */ + tmp = RREG32(DB_DEPTH_INFO); + + mask = RLC_BUSY_STATUS | GFX_POWER_STATUS | GFX_CLOCK_STATUS | GFX_LS_STATUS; + for (i = 0; i < adev->usec_timeout; i++) { + if ((RREG32(RLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS)) + break; + udelay(1); + } + } +} + +static int gfx_v6_0_cp_resume(struct amdgpu_device *adev) +{ + int r; + + gfx_v6_0_enable_gui_idle_interrupt(adev, false); + + r = gfx_v6_0_cp_load_microcode(adev); + if (r) + return r; + + r = gfx_v6_0_cp_gfx_resume(adev); + if (r) + return r; + r = gfx_v6_0_cp_compute_resume(adev); + if (r) + return r; + + gfx_v6_0_enable_gui_idle_interrupt(adev, true); + + return 0; +} + +static void gfx_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) +{ + int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + uint32_t seq = ring->fence_drv.sync_seq; + uint64_t addr = ring->fence_drv.gpu_addr; + + amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); + amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */ + WAIT_REG_MEM_FUNCTION(3) | /* equal */ + WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */ + amdgpu_ring_write(ring, addr & 0xfffffffc); + amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff); + amdgpu_ring_write(ring, seq); + amdgpu_ring_write(ring, 0xffffffff); + amdgpu_ring_write(ring, 4); /* poll interval */ + + if (usepfp) { + /* synce CE with ME to prevent CE fetch CEIB before context switch done */ + amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); + amdgpu_ring_write(ring, 0); + } +} + +static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring, + unsigned vm_id, uint64_t pd_addr) +{ + int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + + /* write new base address */ + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) | + WRITE_DATA_DST_SEL(0))); + if (vm_id < 8) { + amdgpu_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + vm_id )); + } else { + amdgpu_ring_write(ring, (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + (vm_id - 8))); + } + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, pd_addr >> 12); + + /* bits 0-15 are the VM contexts0-15 */ + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) | + WRITE_DATA_DST_SEL(0))); + amdgpu_ring_write(ring, VM_INVALIDATE_REQUEST); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, 1 << vm_id); + + /* wait for the invalidate to complete */ + amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); + amdgpu_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) | /* always */ + WAIT_REG_MEM_ENGINE(0))); /* me */ + amdgpu_ring_write(ring, VM_INVALIDATE_REQUEST); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, 0); /* ref */ + amdgpu_ring_write(ring, 0); /* mask */ + amdgpu_ring_write(ring, 0x20); /* poll interval */ + + if (usepfp) { + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + amdgpu_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + amdgpu_ring_write(ring, 0x0); + + /* synce CE with ME to prevent CE fetch CEIB before context switch done */ + amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); + amdgpu_ring_write(ring, 0); + } +} + + +static void gfx_v6_0_rlc_fini(struct amdgpu_device *adev) +{ + int r; + + if (adev->gfx.rlc.save_restore_obj) { + r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, false); + if (unlikely(r != 0)) + dev_warn(adev->dev, "(%d) reserve RLC sr bo failed\n", r); + amdgpu_bo_unpin(adev->gfx.rlc.save_restore_obj); + amdgpu_bo_unreserve(adev->gfx.rlc.save_restore_obj); + + amdgpu_bo_unref(&adev->gfx.rlc.save_restore_obj); + adev->gfx.rlc.save_restore_obj = NULL; + } + + if (adev->gfx.rlc.clear_state_obj) { + r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false); + if (unlikely(r != 0)) + dev_warn(adev->dev, "(%d) reserve RLC c bo failed\n", r); + amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj); + amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj); + + amdgpu_bo_unref(&adev->gfx.rlc.clear_state_obj); + adev->gfx.rlc.clear_state_obj = NULL; + } + + if (adev->gfx.rlc.cp_table_obj) { + r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, false); + if (unlikely(r != 0)) + dev_warn(adev->dev, "(%d) reserve RLC cp table bo failed\n", r); + amdgpu_bo_unpin(adev->gfx.rlc.cp_table_obj); + amdgpu_bo_unreserve(adev->gfx.rlc.cp_table_obj); + + amdgpu_bo_unref(&adev->gfx.rlc.cp_table_obj); + adev->gfx.rlc.cp_table_obj = NULL; + } +} + +static int gfx_v6_0_rlc_init(struct amdgpu_device *adev) +{ + const u32 *src_ptr; + volatile u32 *dst_ptr; + u32 dws, i; + u64 reg_list_mc_addr; + const struct cs_section_def *cs_data; + int r; + + adev->gfx.rlc.reg_list = verde_rlc_save_restore_register_list; + adev->gfx.rlc.reg_list_size = + (u32)ARRAY_SIZE(verde_rlc_save_restore_register_list); + + adev->gfx.rlc.cs_data = si_cs_data; + src_ptr = adev->gfx.rlc.reg_list; + dws = adev->gfx.rlc.reg_list_size; + cs_data = adev->gfx.rlc.cs_data; + + if (src_ptr) { + /* save restore block */ + if (adev->gfx.rlc.save_restore_obj == NULL) { + + r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true, + AMDGPU_GEM_DOMAIN_VRAM, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + NULL, NULL, + &adev->gfx.rlc.save_restore_obj); + + if (r) { + dev_warn(adev->dev, "(%d) create RLC sr bo failed\n", r); + return r; + } + } + + r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, false); + if (unlikely(r != 0)) { + gfx_v6_0_rlc_fini(adev); + return r; + } + r = amdgpu_bo_pin(adev->gfx.rlc.save_restore_obj, AMDGPU_GEM_DOMAIN_VRAM, + &adev->gfx.rlc.save_restore_gpu_addr); + if (r) { + amdgpu_bo_unreserve(adev->gfx.rlc.save_restore_obj); + dev_warn(adev->dev, "(%d) pin RLC sr bo failed\n", r); + gfx_v6_0_rlc_fini(adev); + return r; + } + + r = amdgpu_bo_kmap(adev->gfx.rlc.save_restore_obj, (void **)&adev->gfx.rlc.sr_ptr); + if (r) { + dev_warn(adev->dev, "(%d) map RLC sr bo failed\n", r); + gfx_v6_0_rlc_fini(adev); + return r; + } + /* write the sr buffer */ + dst_ptr = adev->gfx.rlc.sr_ptr; + for (i = 0; i < adev->gfx.rlc.reg_list_size; i++) + dst_ptr[i] = cpu_to_le32(src_ptr[i]); + amdgpu_bo_kunmap(adev->gfx.rlc.save_restore_obj); + amdgpu_bo_unreserve(adev->gfx.rlc.save_restore_obj); + } + + if (cs_data) { + /* clear state block */ + adev->gfx.rlc.clear_state_size = gfx_v6_0_get_csb_size(adev); + dws = adev->gfx.rlc.clear_state_size + (256 / 4); + + if (adev->gfx.rlc.clear_state_obj == NULL) { + r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true, + AMDGPU_GEM_DOMAIN_VRAM, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + NULL, NULL, + &adev->gfx.rlc.clear_state_obj); + + if (r) { + dev_warn(adev->dev, "(%d) create RLC c bo failed\n", r); + gfx_v6_0_rlc_fini(adev); + return r; + } + } + r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false); + if (unlikely(r != 0)) { + gfx_v6_0_rlc_fini(adev); + return r; + } + r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj, AMDGPU_GEM_DOMAIN_VRAM, + &adev->gfx.rlc.clear_state_gpu_addr); + if (r) { + amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj); + dev_warn(adev->dev, "(%d) pin RLC c bo failed\n", r); + gfx_v6_0_rlc_fini(adev); + return r; + } + + r = amdgpu_bo_kmap(adev->gfx.rlc.clear_state_obj, (void **)&adev->gfx.rlc.cs_ptr); + if (r) { + dev_warn(adev->dev, "(%d) map RLC c bo failed\n", r); + gfx_v6_0_rlc_fini(adev); + return r; + } + /* set up the cs buffer */ + dst_ptr = adev->gfx.rlc.cs_ptr; + reg_list_mc_addr = adev->gfx.rlc.clear_state_gpu_addr + 256; + dst_ptr[0] = cpu_to_le32(upper_32_bits(reg_list_mc_addr)); + dst_ptr[1] = cpu_to_le32(lower_32_bits(reg_list_mc_addr)); + dst_ptr[2] = cpu_to_le32(adev->gfx.rlc.clear_state_size); + gfx_v6_0_get_csb_buffer(adev, &dst_ptr[(256/4)]); + amdgpu_bo_kunmap(adev->gfx.rlc.clear_state_obj); + amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj); + } + + return 0; +} + +static void gfx_v6_0_enable_lbpw(struct amdgpu_device *adev, bool enable) +{ + u32 tmp; + + tmp = RREG32(RLC_LB_CNTL); + if (enable) + tmp |= LOAD_BALANCE_ENABLE; + else + tmp &= ~LOAD_BALANCE_ENABLE; + WREG32(RLC_LB_CNTL, tmp); + + if (!enable) { + gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + WREG32(SPI_LB_CU_MASK, 0x00ff); + } + +} + +static void gfx_v6_0_wait_for_rlc_serdes(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(RLC_SERDES_MASTER_BUSY_0) == 0) + break; + udelay(1); + } + + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(RLC_SERDES_MASTER_BUSY_1) == 0) + break; + udelay(1); + } +} + +static void gfx_v6_0_update_rlc(struct amdgpu_device *adev, u32 rlc) +{ + u32 tmp; + + tmp = RREG32(RLC_CNTL); + if (tmp != rlc) + WREG32(RLC_CNTL, rlc); +} + +static u32 gfx_v6_0_halt_rlc(struct amdgpu_device *adev) +{ + u32 data, orig; + + orig = data = RREG32(RLC_CNTL); + + if (data & RLC_ENABLE) { + data &= ~RLC_ENABLE; + WREG32(RLC_CNTL, data); + + gfx_v6_0_wait_for_rlc_serdes(adev); + } + + return orig; +} + +static void gfx_v6_0_rlc_stop(struct amdgpu_device *adev) +{ + WREG32(RLC_CNTL, 0); + + gfx_v6_0_enable_gui_idle_interrupt(adev, false); + + gfx_v6_0_wait_for_rlc_serdes(adev); +} + +static void gfx_v6_0_rlc_start(struct amdgpu_device *adev) +{ + WREG32(RLC_CNTL, RLC_ENABLE); + + gfx_v6_0_enable_gui_idle_interrupt(adev, true); + + udelay(50); +} + +static void gfx_v6_0_rlc_reset(struct amdgpu_device *adev) +{ + u32 tmp = RREG32(GRBM_SOFT_RESET); + + tmp |= SOFT_RESET_RLC; + WREG32(GRBM_SOFT_RESET, tmp); + udelay(50); + tmp &= ~SOFT_RESET_RLC; + WREG32(GRBM_SOFT_RESET, tmp); + udelay(50); +} + +static bool gfx_v6_0_lbpw_supported(struct amdgpu_device *adev) +{ + u32 tmp; + + /* Enable LBPW only for DDR3 */ + tmp = RREG32(MC_SEQ_MISC0); + if ((tmp & 0xF0000000) == 0xB0000000) + return true; + return false; +} +static void gfx_v6_0_init_cg(struct amdgpu_device *adev) +{ +} + +static int gfx_v6_0_rlc_resume(struct amdgpu_device *adev) +{ + u32 i; + const struct rlc_firmware_header_v1_0 *hdr; + const __le32 *fw_data; + u32 fw_size; + + + if (!adev->gfx.rlc_fw) + return -EINVAL; + + gfx_v6_0_rlc_stop(adev); + + gfx_v6_0_rlc_reset(adev); + + gfx_v6_0_init_pg(adev); + + gfx_v6_0_init_cg(adev); + + WREG32(RLC_RL_BASE, 0); + WREG32(RLC_RL_SIZE, 0); + WREG32(RLC_LB_CNTL, 0); + WREG32(RLC_LB_CNTR_MAX, 0xffffffff); + WREG32(RLC_LB_CNTR_INIT, 0); + WREG32(RLC_LB_INIT_CU_MASK, 0xffffffff); + + WREG32(RLC_MC_CNTL, 0); + WREG32(RLC_UCODE_CNTL, 0); + + hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data; + fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; + fw_data = (const __le32 *) + (adev->gfx.rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + + amdgpu_ucode_print_rlc_hdr(&hdr->header); + + for (i = 0; i < fw_size; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, le32_to_cpup(fw_data++)); + } + WREG32(RLC_UCODE_ADDR, 0); + + gfx_v6_0_enable_lbpw(adev, gfx_v6_0_lbpw_supported(adev)); + + gfx_v6_0_rlc_start(adev); + + return 0; +} + +static void gfx_v6_0_enable_cgcg(struct amdgpu_device *adev, bool enable) +{ + u32 data, orig, tmp; + + orig = data = RREG32(RLC_CGCG_CGLS_CTRL); + + if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) { + gfx_v6_0_enable_gui_idle_interrupt(adev, true); + + WREG32(RLC_GCPM_GENERAL_3, 0x00000080); + + tmp = gfx_v6_0_halt_rlc(adev); + + WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff); + WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff); + WREG32(RLC_SERDES_WR_CTRL, 0x00b000ff); + + gfx_v6_0_wait_for_rlc_serdes(adev); + + gfx_v6_0_update_rlc(adev, tmp); + + WREG32(RLC_SERDES_WR_CTRL, 0x007000ff); + + data |= CGCG_EN | CGLS_EN; + } else { + gfx_v6_0_enable_gui_idle_interrupt(adev, false); + + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + + data &= ~(CGCG_EN | CGLS_EN); + } + + if (orig != data) + WREG32(RLC_CGCG_CGLS_CTRL, data); + +} + +static void gfx_v6_0_enable_mgcg(struct amdgpu_device *adev, bool enable) +{ + + u32 data, orig, tmp = 0; + + if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) { + orig = data = RREG32(CGTS_SM_CTRL_REG); + data = 0x96940200; + if (orig != data) + WREG32(CGTS_SM_CTRL_REG, data); + + if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) { + orig = data = RREG32(CP_MEM_SLP_CNTL); + data |= CP_MEM_LS_EN; + if (orig != data) + WREG32(CP_MEM_SLP_CNTL, data); + } + + orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE); + data &= 0xffffffc0; + if (orig != data) + WREG32(RLC_CGTT_MGCG_OVERRIDE, data); + + tmp = gfx_v6_0_halt_rlc(adev); + + WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff); + WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff); + WREG32(RLC_SERDES_WR_CTRL, 0x00d000ff); + + gfx_v6_0_update_rlc(adev, tmp); + } else { + orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE); + data |= 0x00000003; + if (orig != data) + WREG32(RLC_CGTT_MGCG_OVERRIDE, data); + + data = RREG32(CP_MEM_SLP_CNTL); + if (data & CP_MEM_LS_EN) { + data &= ~CP_MEM_LS_EN; + WREG32(CP_MEM_SLP_CNTL, data); + } + orig = data = RREG32(CGTS_SM_CTRL_REG); + data |= LS_OVERRIDE | OVERRIDE; + if (orig != data) + WREG32(CGTS_SM_CTRL_REG, data); + + tmp = gfx_v6_0_halt_rlc(adev); + + WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff); + WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff); + WREG32(RLC_SERDES_WR_CTRL, 0x00e000ff); + + gfx_v6_0_update_rlc(adev, tmp); + } +} +/* +static void gfx_v6_0_update_cg(struct amdgpu_device *adev, + bool enable) +{ + gfx_v6_0_enable_gui_idle_interrupt(adev, false); + if (enable) { + gfx_v6_0_enable_mgcg(adev, true); + gfx_v6_0_enable_cgcg(adev, true); + } else { + gfx_v6_0_enable_cgcg(adev, false); + gfx_v6_0_enable_mgcg(adev, false); + } + gfx_v6_0_enable_gui_idle_interrupt(adev, true); +} +*/ +static void gfx_v6_0_enable_sclk_slowdown_on_pu(struct amdgpu_device *adev, + bool enable) +{ +} + +static void gfx_v6_0_enable_sclk_slowdown_on_pd(struct amdgpu_device *adev, + bool enable) +{ +} + +static void gfx_v6_0_enable_cp_pg(struct amdgpu_device *adev, bool enable) +{ + u32 data, orig; + + orig = data = RREG32(RLC_PG_CNTL); + if (enable && (adev->pg_flags & AMD_PG_SUPPORT_CP)) + data &= ~0x8000; + else + data |= 0x8000; + if (orig != data) + WREG32(RLC_PG_CNTL, data); +} + +static void gfx_v6_0_enable_gds_pg(struct amdgpu_device *adev, bool enable) +{ +} +/* +static void gfx_v6_0_init_cp_pg_table(struct amdgpu_device *adev) +{ + const __le32 *fw_data; + volatile u32 *dst_ptr; + int me, i, max_me = 4; + u32 bo_offset = 0; + u32 table_offset, table_size; + + if (adev->asic_type == CHIP_KAVERI) + max_me = 5; + + if (adev->gfx.rlc.cp_table_ptr == NULL) + return; + + dst_ptr = adev->gfx.rlc.cp_table_ptr; + for (me = 0; me < max_me; me++) { + if (me == 0) { + const struct gfx_firmware_header_v1_0 *hdr = + (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data; + fw_data = (const __le32 *) + (adev->gfx.ce_fw->data + + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + table_offset = le32_to_cpu(hdr->jt_offset); + table_size = le32_to_cpu(hdr->jt_size); + } else if (me == 1) { + const struct gfx_firmware_header_v1_0 *hdr = + (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data; + fw_data = (const __le32 *) + (adev->gfx.pfp_fw->data + + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + table_offset = le32_to_cpu(hdr->jt_offset); + table_size = le32_to_cpu(hdr->jt_size); + } else if (me == 2) { + const struct gfx_firmware_header_v1_0 *hdr = + (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data; + fw_data = (const __le32 *) + (adev->gfx.me_fw->data + + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + table_offset = le32_to_cpu(hdr->jt_offset); + table_size = le32_to_cpu(hdr->jt_size); + } else if (me == 3) { + const struct gfx_firmware_header_v1_0 *hdr = + (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; + fw_data = (const __le32 *) + (adev->gfx.mec_fw->data + + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + table_offset = le32_to_cpu(hdr->jt_offset); + table_size = le32_to_cpu(hdr->jt_size); + } else { + const struct gfx_firmware_header_v1_0 *hdr = + (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data; + fw_data = (const __le32 *) + (adev->gfx.mec2_fw->data + + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + table_offset = le32_to_cpu(hdr->jt_offset); + table_size = le32_to_cpu(hdr->jt_size); + } + + for (i = 0; i < table_size; i ++) { + dst_ptr[bo_offset + i] = + cpu_to_le32(le32_to_cpu(fw_data[table_offset + i])); + } + + bo_offset += table_size; + } +} +*/ +static void gfx_v6_0_enable_gfx_cgpg(struct amdgpu_device *adev, + bool enable) +{ + + u32 tmp; + + if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) { + tmp = RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10); + WREG32(RLC_TTOP_D, tmp); + + tmp = RREG32(RLC_PG_CNTL); + tmp |= GFX_PG_ENABLE; + WREG32(RLC_PG_CNTL, tmp); + + tmp = RREG32(RLC_AUTO_PG_CTRL); + tmp |= AUTO_PG_EN; + WREG32(RLC_AUTO_PG_CTRL, tmp); + } else { + tmp = RREG32(RLC_AUTO_PG_CTRL); + tmp &= ~AUTO_PG_EN; + WREG32(RLC_AUTO_PG_CTRL, tmp); + + tmp = RREG32(DB_RENDER_CONTROL); + } +} + +static u32 gfx_v6_0_get_cu_active_bitmap(struct amdgpu_device *adev, + u32 se, u32 sh) +{ + + u32 mask = 0, tmp, tmp1; + int i; + + gfx_v6_0_select_se_sh(adev, se, sh, 0xffffffff); + tmp = RREG32(CC_GC_SHADER_ARRAY_CONFIG); + tmp1 = RREG32(GC_USER_SHADER_ARRAY_CONFIG); + gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + + tmp &= 0xffff0000; + + tmp |= tmp1; + tmp >>= 16; + + for (i = 0; i < adev->gfx.config.max_cu_per_sh; i ++) { + mask <<= 1; + mask |= 1; + } + + return (~tmp) & mask; +} + +static void gfx_v6_0_init_ao_cu_mask(struct amdgpu_device *adev) +{ + u32 i, j, k, active_cu_number = 0; + + u32 mask, counter, cu_bitmap; + u32 tmp = 0; + + for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { + for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { + mask = 1; + cu_bitmap = 0; + counter = 0; + for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) { + if (gfx_v6_0_get_cu_active_bitmap(adev, i, j) & mask) { + if (counter < 2) + cu_bitmap |= mask; + counter++; + } + mask <<= 1; + } + + active_cu_number += counter; + tmp |= (cu_bitmap << (i * 16 + j * 8)); + } + } + + WREG32(RLC_PG_AO_CU_MASK, tmp); + + tmp = RREG32(RLC_MAX_PG_CU); + tmp &= ~MAX_PU_CU_MASK; + tmp |= MAX_PU_CU(active_cu_number); + WREG32(RLC_MAX_PG_CU, tmp); +} + +static void gfx_v6_0_enable_gfx_static_mgpg(struct amdgpu_device *adev, + bool enable) +{ + u32 data, orig; + + orig = data = RREG32(RLC_PG_CNTL); + if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG)) + data |= STATIC_PER_CU_PG_ENABLE; + else + data &= ~STATIC_PER_CU_PG_ENABLE; + if (orig != data) + WREG32(RLC_PG_CNTL, data); +} + +static void gfx_v6_0_enable_gfx_dynamic_mgpg(struct amdgpu_device *adev, + bool enable) +{ + u32 data, orig; + + orig = data = RREG32(RLC_PG_CNTL); + if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_DMG)) + data |= DYN_PER_CU_PG_ENABLE; + else + data &= ~DYN_PER_CU_PG_ENABLE; + if (orig != data) + WREG32(RLC_PG_CNTL, data); +} + +static void gfx_v6_0_init_gfx_cgpg(struct amdgpu_device *adev) +{ + u32 tmp; + + WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8); + + tmp = RREG32(RLC_PG_CNTL); + tmp |= GFX_PG_SRC; + WREG32(RLC_PG_CNTL, tmp); + + WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8); + + tmp = RREG32(RLC_AUTO_PG_CTRL); + + tmp &= ~GRBM_REG_SGIT_MASK; + tmp |= GRBM_REG_SGIT(0x700); + tmp &= ~PG_AFTER_GRBM_REG_ST_MASK; + WREG32(RLC_AUTO_PG_CTRL, tmp); +} + +static void gfx_v6_0_update_gfx_pg(struct amdgpu_device *adev, bool enable) +{ + gfx_v6_0_enable_gfx_cgpg(adev, enable); + gfx_v6_0_enable_gfx_static_mgpg(adev, enable); + gfx_v6_0_enable_gfx_dynamic_mgpg(adev, enable); +} + +static u32 gfx_v6_0_get_csb_size(struct amdgpu_device *adev) +{ + u32 count = 0; + const struct cs_section_def *sect = NULL; + const struct cs_extent_def *ext = NULL; + + if (adev->gfx.rlc.cs_data == NULL) + return 0; + + /* begin clear state */ + count += 2; + /* context control state */ + count += 3; + + for (sect = adev->gfx.rlc.cs_data; sect->section != NULL; ++sect) { + for (ext = sect->section; ext->extent != NULL; ++ext) { + if (sect->id == SECT_CONTEXT) + count += 2 + ext->reg_count; + else + return 0; + } + } + /* pa_sc_raster_config */ + count += 3; + /* end clear state */ + count += 2; + /* clear state */ + count += 2; + + return count; +} + +static void gfx_v6_0_get_csb_buffer(struct amdgpu_device *adev, + volatile u32 *buffer) +{ + u32 count = 0, i; + const struct cs_section_def *sect = NULL; + const struct cs_extent_def *ext = NULL; + + if (adev->gfx.rlc.cs_data == NULL) + return; + if (buffer == NULL) + return; + + buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); + + buffer[count++] = cpu_to_le32(PACKET3(PACKET3_CONTEXT_CONTROL, 1)); + buffer[count++] = cpu_to_le32(0x80000000); + buffer[count++] = cpu_to_le32(0x80000000); + + for (sect = adev->gfx.rlc.cs_data; sect->section != NULL; ++sect) { + for (ext = sect->section; ext->extent != NULL; ++ext) { + if (sect->id == SECT_CONTEXT) { + buffer[count++] = + cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, ext->reg_count)); + buffer[count++] = cpu_to_le32(ext->reg_index - 0xa000); + for (i = 0; i < ext->reg_count; i++) + buffer[count++] = cpu_to_le32(ext->extent[i]); + } else { + return; + } + } + } + + buffer[count++] = cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, 1)); + buffer[count++] = cpu_to_le32(PA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START); + + switch (adev->asic_type) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + buffer[count++] = cpu_to_le32(0x2a00126a); + break; + case CHIP_VERDE: + buffer[count++] = cpu_to_le32(0x0000124a); + break; + case CHIP_OLAND: + buffer[count++] = cpu_to_le32(0x00000082); + break; + case CHIP_HAINAN: + buffer[count++] = cpu_to_le32(0x00000000); + break; + default: + buffer[count++] = cpu_to_le32(0x00000000); + break; + } + + buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0)); + buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_END_CLEAR_STATE); + + buffer[count++] = cpu_to_le32(PACKET3(PACKET3_CLEAR_STATE, 0)); + buffer[count++] = cpu_to_le32(0); +} + +static void gfx_v6_0_init_pg(struct amdgpu_device *adev) +{ + if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG | + AMD_PG_SUPPORT_GFX_SMG | + AMD_PG_SUPPORT_GFX_DMG | + AMD_PG_SUPPORT_CP | + AMD_PG_SUPPORT_GDS | + AMD_PG_SUPPORT_RLC_SMU_HS)) { + gfx_v6_0_enable_sclk_slowdown_on_pu(adev, true); + gfx_v6_0_enable_sclk_slowdown_on_pd(adev, true); + if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) { + gfx_v6_0_init_gfx_cgpg(adev); + gfx_v6_0_enable_cp_pg(adev, true); + gfx_v6_0_enable_gds_pg(adev, true); + } else { + WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8); + WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8); + + } + gfx_v6_0_init_ao_cu_mask(adev); + gfx_v6_0_update_gfx_pg(adev, true); + } else { + + WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8); + WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8); + } +} + +static void gfx_v6_0_fini_pg(struct amdgpu_device *adev) +{ + if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG | + AMD_PG_SUPPORT_GFX_SMG | + AMD_PG_SUPPORT_GFX_DMG | + AMD_PG_SUPPORT_CP | + AMD_PG_SUPPORT_GDS | + AMD_PG_SUPPORT_RLC_SMU_HS)) { + gfx_v6_0_update_gfx_pg(adev, false); + if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) { + gfx_v6_0_enable_cp_pg(adev, false); + gfx_v6_0_enable_gds_pg(adev, false); + } + } +} + +static uint64_t gfx_v6_0_get_gpu_clock_counter(struct amdgpu_device *adev) +{ + uint64_t clock; + + mutex_lock(&adev->gfx.gpu_clock_mutex); + WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); + clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | + ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); + mutex_unlock(&adev->gfx.gpu_clock_mutex); + return clock; +} + +static void gfx_v6_0_ring_emit_gds_switch(struct amdgpu_ring *ring, + uint32_t vmid, + uint32_t gds_base, uint32_t gds_size, + uint32_t gws_base, uint32_t gws_size, + uint32_t oa_base, uint32_t oa_size) +{ +} + +static const struct amdgpu_gfx_funcs gfx_v6_0_gfx_funcs = { + .get_gpu_clock_counter = &gfx_v6_0_get_gpu_clock_counter, + .select_se_sh = &gfx_v6_0_select_se_sh, +}; + +static int gfx_v6_0_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + adev->gfx.num_gfx_rings = GFX6_NUM_GFX_RINGS; + adev->gfx.num_compute_rings = GFX6_NUM_COMPUTE_RINGS; + adev->gfx.funcs = &gfx_v6_0_gfx_funcs; + gfx_v6_0_set_ring_funcs(adev); + gfx_v6_0_set_irq_funcs(adev); + + return 0; +} + +static int gfx_v6_0_sw_init(void *handle) +{ + struct amdgpu_ring *ring; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int i, r; + + r = amdgpu_irq_add_id(adev, 181, &adev->gfx.eop_irq); + if (r) + return r; + + r = amdgpu_irq_add_id(adev, 184, &adev->gfx.priv_reg_irq); + if (r) + return r; + + r = amdgpu_irq_add_id(adev, 185, &adev->gfx.priv_inst_irq); + if (r) + return r; + + gfx_v6_0_scratch_init(adev); + + r = gfx_v6_0_init_microcode(adev); + if (r) { + DRM_ERROR("Failed to load gfx firmware!\n"); + return r; + } + + r = gfx_v6_0_rlc_init(adev); + if (r) { + DRM_ERROR("Failed to init rlc BOs!\n"); + return r; + } + + for (i = 0; i < adev->gfx.num_gfx_rings; i++) { + ring = &adev->gfx.gfx_ring[i]; + ring->ring_obj = NULL; + sprintf(ring->name, "gfx"); + r = amdgpu_ring_init(adev, ring, 1024, + 0x80000000, 0xf, + &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP, + AMDGPU_RING_TYPE_GFX); + if (r) + return r; + } + + for (i = 0; i < adev->gfx.num_compute_rings; i++) { + unsigned irq_type; + + if ((i >= 32) || (i >= AMDGPU_MAX_COMPUTE_RINGS)) { + DRM_ERROR("Too many (%d) compute rings!\n", i); + break; + } + ring = &adev->gfx.compute_ring[i]; + ring->ring_obj = NULL; + ring->use_doorbell = false; + ring->doorbell_index = 0; + ring->me = 1; + ring->pipe = i; + ring->queue = i; + sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue); + irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; + r = amdgpu_ring_init(adev, ring, 1024 * 1024, + 0x80000000, 0xf, + &adev->gfx.eop_irq, irq_type, + AMDGPU_RING_TYPE_COMPUTE); + if (r) + return r; + } + + return r; +} + +static int gfx_v6_0_sw_fini(void *handle) +{ + int i; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_bo_unref(&adev->gds.oa_gfx_bo); + amdgpu_bo_unref(&adev->gds.gws_gfx_bo); + amdgpu_bo_unref(&adev->gds.gds_gfx_bo); + + for (i = 0; i < adev->gfx.num_gfx_rings; i++) + amdgpu_ring_fini(&adev->gfx.gfx_ring[i]); + for (i = 0; i < adev->gfx.num_compute_rings; i++) + amdgpu_ring_fini(&adev->gfx.compute_ring[i]); + + gfx_v6_0_cp_compute_fini(adev); + gfx_v6_0_rlc_fini(adev); + + return 0; +} + +static int gfx_v6_0_hw_init(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + gfx_v6_0_gpu_init(adev); + + r = gfx_v6_0_rlc_resume(adev); + if (r) + return r; + + r = gfx_v6_0_cp_resume(adev); + if (r) + return r; + + adev->gfx.ce_ram_size = 0x8000; + + return r; +} + +static int gfx_v6_0_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + gfx_v6_0_cp_enable(adev, false); + gfx_v6_0_rlc_stop(adev); + gfx_v6_0_fini_pg(adev); + + return 0; +} + +static int gfx_v6_0_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return gfx_v6_0_hw_fini(adev); +} + +static int gfx_v6_0_resume(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return gfx_v6_0_hw_init(adev); +} + +static bool gfx_v6_0_is_idle(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (RREG32(GRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK) + return false; + else + return true; +} + +static int gfx_v6_0_wait_for_idle(void *handle) +{ + unsigned i; + u32 tmp; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(GRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK; + + if (!tmp) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int gfx_v6_0_soft_reset(void *handle) +{ + return 0; +} + +static void gfx_v6_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, + enum amdgpu_interrupt_state state) +{ + u32 cp_int_cntl; + + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cp_int_cntl = RREG32(CP_INT_CNTL_RING0); + cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cp_int_cntl = RREG32(CP_INT_CNTL_RING0); + cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + break; + default: + break; + } +} + +static void gfx_v6_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev, + int ring, + enum amdgpu_interrupt_state state) +{ + u32 cp_int_cntl; + switch (state){ + case AMDGPU_IRQ_STATE_DISABLE: + if (ring == 0) { + cp_int_cntl = RREG32(CP_INT_CNTL_RING1); + cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING1, cp_int_cntl); + break; + } else { + cp_int_cntl = RREG32(CP_INT_CNTL_RING2); + cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING2, cp_int_cntl); + break; + + } + case AMDGPU_IRQ_STATE_ENABLE: + if (ring == 0) { + cp_int_cntl = RREG32(CP_INT_CNTL_RING1); + cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING1, cp_int_cntl); + break; + } else { + cp_int_cntl = RREG32(CP_INT_CNTL_RING2); + cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING2, cp_int_cntl); + break; + + } + + default: + BUG(); + break; + + } +} + +static int gfx_v6_0_set_priv_reg_fault_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 cp_int_cntl; + + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cp_int_cntl = RREG32(CP_INT_CNTL_RING0); + cp_int_cntl &= ~CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cp_int_cntl = RREG32(CP_INT_CNTL_RING0); + cp_int_cntl |= CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + break; + default: + break; + } + + return 0; +} + +static int gfx_v6_0_set_priv_inst_fault_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 cp_int_cntl; + + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cp_int_cntl = RREG32(CP_INT_CNTL_RING0); + cp_int_cntl &= ~CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cp_int_cntl = RREG32(CP_INT_CNTL_RING0); + cp_int_cntl |= CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK; + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + break; + default: + break; + } + + return 0; +} + +static int gfx_v6_0_set_eop_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + switch (type) { + case AMDGPU_CP_IRQ_GFX_EOP: + gfx_v6_0_set_gfx_eop_interrupt_state(adev, state); + break; + case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP: + gfx_v6_0_set_compute_eop_interrupt_state(adev, 0, state); + break; + case AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE1_EOP: + gfx_v6_0_set_compute_eop_interrupt_state(adev, 1, state); + break; + default: + break; + } + return 0; +} + +static int gfx_v6_0_eop_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + switch (entry->ring_id) { + case 0: + amdgpu_fence_process(&adev->gfx.gfx_ring[0]); + break; + case 1: + case 2: + amdgpu_fence_process(&adev->gfx.compute_ring[entry->ring_id -1]); + break; + default: + break; + } + return 0; +} + +static int gfx_v6_0_priv_reg_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + DRM_ERROR("Illegal register access in command stream\n"); + schedule_work(&adev->reset_work); + return 0; +} + +static int gfx_v6_0_priv_inst_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + DRM_ERROR("Illegal instruction in command stream\n"); + schedule_work(&adev->reset_work); + return 0; +} + +static int gfx_v6_0_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + bool gate = false; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (state == AMD_CG_STATE_GATE) + gate = true; + + gfx_v6_0_enable_gui_idle_interrupt(adev, false); + if (gate) { + gfx_v6_0_enable_mgcg(adev, true); + gfx_v6_0_enable_cgcg(adev, true); + } else { + gfx_v6_0_enable_cgcg(adev, false); + gfx_v6_0_enable_mgcg(adev, false); + } + gfx_v6_0_enable_gui_idle_interrupt(adev, true); + + return 0; +} + +static int gfx_v6_0_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + bool gate = false; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (state == AMD_PG_STATE_GATE) + gate = true; + + if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG | + AMD_PG_SUPPORT_GFX_SMG | + AMD_PG_SUPPORT_GFX_DMG | + AMD_PG_SUPPORT_CP | + AMD_PG_SUPPORT_GDS | + AMD_PG_SUPPORT_RLC_SMU_HS)) { + gfx_v6_0_update_gfx_pg(adev, gate); + if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) { + gfx_v6_0_enable_cp_pg(adev, gate); + gfx_v6_0_enable_gds_pg(adev, gate); + } + } + + return 0; +} + +const struct amd_ip_funcs gfx_v6_0_ip_funcs = { + .name = "gfx_v6_0", + .early_init = gfx_v6_0_early_init, + .late_init = NULL, + .sw_init = gfx_v6_0_sw_init, + .sw_fini = gfx_v6_0_sw_fini, + .hw_init = gfx_v6_0_hw_init, + .hw_fini = gfx_v6_0_hw_fini, + .suspend = gfx_v6_0_suspend, + .resume = gfx_v6_0_resume, + .is_idle = gfx_v6_0_is_idle, + .wait_for_idle = gfx_v6_0_wait_for_idle, + .soft_reset = gfx_v6_0_soft_reset, + .set_clockgating_state = gfx_v6_0_set_clockgating_state, + .set_powergating_state = gfx_v6_0_set_powergating_state, +}; + +static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { + .get_rptr = gfx_v6_0_ring_get_rptr_gfx, + .get_wptr = gfx_v6_0_ring_get_wptr_gfx, + .set_wptr = gfx_v6_0_ring_set_wptr_gfx, + .parse_cs = NULL, + .emit_ib = gfx_v6_0_ring_emit_ib_gfx, + .emit_fence = gfx_v6_0_ring_emit_fence_gfx, + .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, + .emit_vm_flush = gfx_v6_0_ring_emit_vm_flush, + .emit_gds_switch = gfx_v6_0_ring_emit_gds_switch, + .emit_hdp_flush = gfx_v6_0_ring_emit_hdp_flush, + .emit_hdp_invalidate = gfx_v6_0_ring_emit_hdp_invalidate, + .test_ring = gfx_v6_0_ring_test_ring, + .test_ib = gfx_v6_0_ring_test_ib, + .insert_nop = amdgpu_ring_insert_nop, +}; + +static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { + .get_rptr = gfx_v6_0_ring_get_rptr_compute, + .get_wptr = gfx_v6_0_ring_get_wptr_compute, + .set_wptr = gfx_v6_0_ring_set_wptr_compute, + .parse_cs = NULL, + .emit_ib = gfx_v6_0_ring_emit_ib_compute, + .emit_fence = gfx_v6_0_ring_emit_fence_compute, + .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, + .emit_vm_flush = gfx_v6_0_ring_emit_vm_flush, + .emit_gds_switch = gfx_v6_0_ring_emit_gds_switch, + .emit_hdp_flush = gfx_v6_0_ring_emit_hdp_flush, + .emit_hdp_invalidate = gfx_v6_0_ring_emit_hdp_invalidate, + .test_ring = gfx_v6_0_ring_test_ring, + .test_ib = gfx_v6_0_ring_test_ib, + .insert_nop = amdgpu_ring_insert_nop, +}; + +static void gfx_v6_0_set_ring_funcs(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < adev->gfx.num_gfx_rings; i++) + adev->gfx.gfx_ring[i].funcs = &gfx_v6_0_ring_funcs_gfx; + for (i = 0; i < adev->gfx.num_compute_rings; i++) + adev->gfx.compute_ring[i].funcs = &gfx_v6_0_ring_funcs_compute; +} + +static const struct amdgpu_irq_src_funcs gfx_v6_0_eop_irq_funcs = { + .set = gfx_v6_0_set_eop_interrupt_state, + .process = gfx_v6_0_eop_irq, +}; + +static const struct amdgpu_irq_src_funcs gfx_v6_0_priv_reg_irq_funcs = { + .set = gfx_v6_0_set_priv_reg_fault_state, + .process = gfx_v6_0_priv_reg_irq, +}; + +static const struct amdgpu_irq_src_funcs gfx_v6_0_priv_inst_irq_funcs = { + .set = gfx_v6_0_set_priv_inst_fault_state, + .process = gfx_v6_0_priv_inst_irq, +}; + +static void gfx_v6_0_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST; + adev->gfx.eop_irq.funcs = &gfx_v6_0_eop_irq_funcs; + + adev->gfx.priv_reg_irq.num_types = 1; + adev->gfx.priv_reg_irq.funcs = &gfx_v6_0_priv_reg_irq_funcs; + + adev->gfx.priv_inst_irq.num_types = 1; + adev->gfx.priv_inst_irq.funcs = &gfx_v6_0_priv_inst_irq_funcs; +} + +static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev) +{ + int i, j, k, counter, active_cu_number = 0; + u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0; + struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info; + + memset(cu_info, 0, sizeof(*cu_info)); + + mutex_lock(&adev->grbm_idx_mutex); + for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { + for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { + mask = 1; + ao_bitmap = 0; + counter = 0; + gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff); + bitmap = gfx_v6_0_get_cu_active_bitmap(adev, i, j); + cu_info->bitmap[i][j] = bitmap; + + for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) { + if (bitmap & mask) { + if (counter < 2) + ao_bitmap |= mask; + counter ++; + } + mask <<= 1; + } + active_cu_number += counter; + ao_cu_mask |= (ao_bitmap << (i * 16 + j * 8)); + } + } + gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); + + cu_info->number = active_cu_number; + cu_info->ao_cu_mask = ao_cu_mask; +} diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h new file mode 100644 index 0000000..b9657e7 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h @@ -0,0 +1,29 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __GFX_V6_0_H__ +#define __GFX_V6_0_H__ + +extern const struct amd_ip_funcs gfx_v6_0_ip_funcs; + +#endif -- cgit v1.1 From 30d1574fa4c71cf390ae4af57585a850612db8f7 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 14:05:23 +0800 Subject: drm/amdgpu: add DMA implementation for si v8 v4: rebase fixes v5: use the generic nop fill v6: rebase fixes v7: rebase fixes copy count fixes from Jonathan general cleanup add fill buffer implementation v8: adapt write_pte and copy_pte to latest changes Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 + drivers/gpu/drm/amd/amdgpu/si_dma.c | 917 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/si_dma.h | 29 + drivers/gpu/drm/amd/include/asic_reg/si/sid.h | 2 + 4 files changed, 952 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/si_dma.c create mode 100644 drivers/gpu/drm/amd/amdgpu/si_dma.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e31ffe8..1d29e12 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1706,6 +1706,10 @@ struct amdgpu_sdma_instance { struct amdgpu_sdma { struct amdgpu_sdma_instance instance[AMDGPU_MAX_SDMA_INSTANCES]; +#ifdef CONFIG_DRM_AMDGPU_SI + //SI DMA has a difference trap irq number for the second engine + struct amdgpu_irq_src trap_irq_1; +#endif struct amdgpu_irq_src trap_irq; struct amdgpu_irq_src illegal_inst_irq; int num_instances; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c new file mode 100644 index 0000000..377f4ae --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -0,0 +1,917 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ +#include +#include "amdgpu.h" +#include "amdgpu_trace.h" +#include "si/sid.h" + +const u32 sdma_offsets[SDMA_MAX_INSTANCE] = +{ + DMA0_REGISTER_OFFSET, + DMA1_REGISTER_OFFSET +}; + +static void si_dma_set_ring_funcs(struct amdgpu_device *adev); +static void si_dma_set_buffer_funcs(struct amdgpu_device *adev); +static void si_dma_set_vm_pte_funcs(struct amdgpu_device *adev); +static void si_dma_set_irq_funcs(struct amdgpu_device *adev); + +static uint32_t si_dma_ring_get_rptr(struct amdgpu_ring *ring) +{ + u32 rptr; + + rptr = ring->adev->wb.wb[ring->rptr_offs/4]; + + return rptr; +} + +static uint32_t si_dma_ring_get_wptr(struct amdgpu_ring *ring) +{ + + struct amdgpu_device *adev = ring->adev; + u32 me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1; + + return (RREG32(DMA_RB_WPTR + sdma_offsets[me]) & 0x3fffc) >> 2; +} + +static void si_dma_ring_set_wptr(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + u32 me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1; + + WREG32(DMA_RB_WPTR + sdma_offsets[me], (ring->wptr << 2) & 0x3fffc); +} + +static void si_dma_ring_emit_ib(struct amdgpu_ring *ring, + struct amdgpu_ib *ib, + unsigned vm_id, bool ctx_switch) +{ + /* The indirect buffer packet must end on an 8 DW boundary in the DMA ring. + * Pad as necessary with NOPs. + */ + while ((ring->wptr & 7) != 5) + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); + amdgpu_ring_write(ring, DMA_IB_PACKET(DMA_PACKET_INDIRECT_BUFFER, vm_id, 0)); + amdgpu_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0)); + amdgpu_ring_write(ring, (ib->length_dw << 12) | (upper_32_bits(ib->gpu_addr) & 0xFF)); + +} + +static void si_dma_ring_emit_hdp_flush(struct amdgpu_ring *ring) +{ + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); + amdgpu_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL)); + amdgpu_ring_write(ring, 1); +} + +static void si_dma_ring_emit_hdp_invalidate(struct amdgpu_ring *ring) +{ + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); + amdgpu_ring_write(ring, (0xf << 16) | (HDP_DEBUG0)); + amdgpu_ring_write(ring, 1); +} + +/** + * si_dma_ring_emit_fence - emit a fence on the DMA ring + * + * @ring: amdgpu ring pointer + * @fence: amdgpu fence object + * + * Add a DMA fence packet to the ring to write + * the fence seq number and DMA trap packet to generate + * an interrupt if needed (VI). + */ +static void si_dma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, + unsigned flags) +{ + + bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; + /* write the fence */ + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0, 0, 0)); + amdgpu_ring_write(ring, addr & 0xfffffffc); + amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xff)); + amdgpu_ring_write(ring, seq); + /* optionally write high bits as well */ + if (write64bit) { + addr += 4; + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0, 0, 0)); + amdgpu_ring_write(ring, addr & 0xfffffffc); + amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xff)); + amdgpu_ring_write(ring, upper_32_bits(seq)); + } + /* generate an interrupt */ + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0, 0, 0)); +} + +static void si_dma_stop(struct amdgpu_device *adev) +{ + struct amdgpu_ring *ring; + u32 rb_cntl; + unsigned i; + + for (i = 0; i < adev->sdma.num_instances; i++) { + ring = &adev->sdma.instance[i].ring; + /* dma0 */ + rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]); + rb_cntl &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + sdma_offsets[i], rb_cntl); + + ring->ready = false; + } +} + +static int si_dma_start(struct amdgpu_device *adev) +{ + struct amdgpu_ring *ring; + u32 rb_cntl, dma_cntl, ib_cntl, rb_bufsz; + int i, r; + uint64_t rptr_addr; + + for (i = 0; i < adev->sdma.num_instances; i++) { + ring = &adev->sdma.instance[i].ring; + + WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL + sdma_offsets[i], 0); + WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i], 0); + + /* Set ring buffer size in dwords */ + rb_bufsz = order_base_2(ring->ring_size / 4); + rb_cntl = rb_bufsz << 1; +#ifdef __BIG_ENDIAN + rb_cntl |= DMA_RB_SWAP_ENABLE | DMA_RPTR_WRITEBACK_SWAP_ENABLE; +#endif + WREG32(DMA_RB_CNTL + sdma_offsets[i], rb_cntl); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(DMA_RB_RPTR + sdma_offsets[i], 0); + WREG32(DMA_RB_WPTR + sdma_offsets[i], 0); + + rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); + + WREG32(DMA_RB_RPTR_ADDR_LO + sdma_offsets[i], lower_32_bits(rptr_addr)); + WREG32(DMA_RB_RPTR_ADDR_HI + sdma_offsets[i], upper_32_bits(rptr_addr) & 0xFF); + + rb_cntl |= DMA_RPTR_WRITEBACK_ENABLE; + + WREG32(DMA_RB_BASE + sdma_offsets[i], ring->gpu_addr >> 8); + + /* enable DMA IBs */ + ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE; +#ifdef __BIG_ENDIAN + ib_cntl |= DMA_IB_SWAP_ENABLE; +#endif + WREG32(DMA_IB_CNTL + sdma_offsets[i], ib_cntl); + + dma_cntl = RREG32(DMA_CNTL + sdma_offsets[i]); + dma_cntl &= ~CTXEMPTY_INT_ENABLE; + WREG32(DMA_CNTL + sdma_offsets[i], dma_cntl); + + ring->wptr = 0; + WREG32(DMA_RB_WPTR + sdma_offsets[i], ring->wptr << 2); + + WREG32(DMA_RB_CNTL + sdma_offsets[i], rb_cntl | DMA_RB_ENABLE); + + ring->ready = true; + + r = amdgpu_ring_test_ring(ring); + if (r) { + ring->ready = false; + return r; + } + } + + return 0; +} + +/** + * si_dma_ring_test_ring - simple async dma engine test + * + * @ring: amdgpu_ring structure holding ring information + * + * Test the DMA engine by writing using it to write an + * value to memory. (VI). + * Returns 0 for success, error for failure. + */ +static int si_dma_ring_test_ring(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + unsigned i; + unsigned index; + int r; + u32 tmp; + u64 gpu_addr; + + r = amdgpu_wb_get(adev, &index); + if (r) { + dev_err(adev->dev, "(%d) failed to allocate wb slot\n", r); + return r; + } + + gpu_addr = adev->wb.gpu_addr + (index * 4); + tmp = 0xCAFEDEAD; + adev->wb.wb[index] = cpu_to_le32(tmp); + + r = amdgpu_ring_alloc(ring, 4); + if (r) { + DRM_ERROR("amdgpu: dma failed to lock ring %d (%d).\n", ring->idx, r); + amdgpu_wb_free(adev, index); + return r; + } + + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, 1)); + amdgpu_ring_write(ring, lower_32_bits(gpu_addr)); + amdgpu_ring_write(ring, upper_32_bits(gpu_addr) & 0xff); + amdgpu_ring_write(ring, 0xDEADBEEF); + amdgpu_ring_commit(ring); + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = le32_to_cpu(adev->wb.wb[index]); + if (tmp == 0xDEADBEEF) + break; + DRM_UDELAY(1); + } + + if (i < adev->usec_timeout) { + DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); + } else { + DRM_ERROR("amdgpu: ring %d test failed (0x%08X)\n", + ring->idx, tmp); + r = -EINVAL; + } + amdgpu_wb_free(adev, index); + + return r; +} + +/** + * si_dma_ring_test_ib - test an IB on the DMA engine + * + * @ring: amdgpu_ring structure holding ring information + * + * Test a simple IB in the DMA ring (VI). + * Returns 0 on success, error on failure. + */ +static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout) +{ + struct amdgpu_device *adev = ring->adev; + struct amdgpu_ib ib; + struct fence *f = NULL; + unsigned index; + u32 tmp = 0; + u64 gpu_addr; + long r; + + r = amdgpu_wb_get(adev, &index); + if (r) { + dev_err(adev->dev, "(%ld) failed to allocate wb slot\n", r); + return r; + } + + gpu_addr = adev->wb.gpu_addr + (index * 4); + tmp = 0xCAFEDEAD; + adev->wb.wb[index] = cpu_to_le32(tmp); + memset(&ib, 0, sizeof(ib)); + r = amdgpu_ib_get(adev, NULL, 256, &ib); + if (r) { + DRM_ERROR("amdgpu: failed to get ib (%ld).\n", r); + goto err0; + } + + ib.ptr[0] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, 1); + ib.ptr[1] = lower_32_bits(gpu_addr); + ib.ptr[2] = upper_32_bits(gpu_addr) & 0xff; + ib.ptr[3] = 0xDEADBEEF; + ib.length_dw = 4; + r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f); + if (r) + goto err1; + + r = fence_wait_timeout(f, false, timeout); + if (r == 0) { + DRM_ERROR("amdgpu: IB test timed out\n"); + r = -ETIMEDOUT; + goto err1; + } else if (r < 0) { + DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); + goto err1; + } + tmp = le32_to_cpu(adev->wb.wb[index]); + if (tmp == 0xDEADBEEF) { + DRM_INFO("ib test on ring %d succeeded\n", ring->idx); + r = 0; + } else { + DRM_ERROR("amdgpu: ib test failed (0x%08X)\n", tmp); + r = -EINVAL; + } + +err1: + amdgpu_ib_free(adev, &ib, NULL); + fence_put(f); +err0: + amdgpu_wb_free(adev, index); + return r; +} + +/** + * cik_dma_vm_copy_pte - update PTEs by copying them from the GART + * + * @ib: indirect buffer to fill with commands + * @pe: addr of the page entry + * @src: src addr to copy from + * @count: number of page entries to update + * + * Update PTEs by copying them from the GART using DMA (SI). + */ +static void si_dma_vm_copy_pte(struct amdgpu_ib *ib, + uint64_t pe, uint64_t src, + unsigned count) +{ + unsigned bytes = count * 8; + + ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY, + 1, 0, 0, bytes); + ib->ptr[ib->length_dw++] = lower_32_bits(pe); + ib->ptr[ib->length_dw++] = lower_32_bits(src); + ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; + ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff; +} + +/** + * si_dma_vm_write_pte - update PTEs by writing them manually + * + * @ib: indirect buffer to fill with commands + * @pe: addr of the page entry + * @value: dst addr to write into pe + * @count: number of page entries to update + * @incr: increase next addr by incr bytes + * + * Update PTEs by writing them manually using DMA (SI). + */ +static void si_dma_vm_write_pte(struct amdgpu_ib *ib, uint64_t pe, + uint64_t value, unsigned count, + uint32_t incr) +{ + unsigned ndw = count * 2; + + ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw); + ib->ptr[ib->length_dw++] = lower_32_bits(pe); + ib->ptr[ib->length_dw++] = upper_32_bits(pe); + for (; ndw > 0; ndw -= 2) { + ib->ptr[ib->length_dw++] = lower_32_bits(value); + ib->ptr[ib->length_dw++] = upper_32_bits(value); + value += incr; + } +} + +/** + * si_dma_vm_set_pte_pde - update the page tables using sDMA + * + * @ib: indirect buffer to fill with commands + * @pe: addr of the page entry + * @addr: dst addr to write into pe + * @count: number of page entries to update + * @incr: increase next addr by incr bytes + * @flags: access flags + * + * Update the page tables using sDMA (CIK). + */ +static void si_dma_vm_set_pte_pde(struct amdgpu_ib *ib, + uint64_t pe, + uint64_t addr, unsigned count, + uint32_t incr, uint32_t flags) +{ + uint64_t value; + unsigned ndw; + + while (count) { + ndw = count * 2; + if (ndw > 0xFFFFE) + ndw = 0xFFFFE; + + if (flags & AMDGPU_PTE_VALID) + value = addr; + else + value = 0; + + /* for physically contiguous pages (vram) */ + ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw); + ib->ptr[ib->length_dw++] = pe; /* dst addr */ + ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; + ib->ptr[ib->length_dw++] = flags; /* mask */ + ib->ptr[ib->length_dw++] = 0; + ib->ptr[ib->length_dw++] = value; /* value */ + ib->ptr[ib->length_dw++] = upper_32_bits(value); + ib->ptr[ib->length_dw++] = incr; /* increment size */ + ib->ptr[ib->length_dw++] = 0; + pe += ndw * 4; + addr += (ndw / 2) * incr; + count -= ndw / 2; + } +} + +/** + * si_dma_pad_ib - pad the IB to the required number of dw + * + * @ib: indirect buffer to fill with padding + * + */ +static void si_dma_ring_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib) +{ + while (ib->length_dw & 0x7) + ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0); +} + +/** + * cik_sdma_ring_emit_pipeline_sync - sync the pipeline + * + * @ring: amdgpu_ring pointer + * + * Make sure all previous operations are completed (CIK). + */ +static void si_dma_ring_emit_pipeline_sync(struct amdgpu_ring *ring) +{ + uint32_t seq = ring->fence_drv.sync_seq; + uint64_t addr = ring->fence_drv.gpu_addr; + + /* wait for idle */ + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_POLL_REG_MEM, 0, 0, 0, 0) | + (1 << 27)); /* Poll memory */ + amdgpu_ring_write(ring, lower_32_bits(addr)); + amdgpu_ring_write(ring, (0xff << 16) | upper_32_bits(addr)); /* retry, addr_hi */ + amdgpu_ring_write(ring, 0xffffffff); /* mask */ + amdgpu_ring_write(ring, seq); /* value */ + amdgpu_ring_write(ring, (3 << 28) | 0x20); /* func(equal) | poll interval */ +} + +/** + * si_dma_ring_emit_vm_flush - cik vm flush using sDMA + * + * @ring: amdgpu_ring pointer + * @vm: amdgpu_vm pointer + * + * Update the page table base and flush the VM TLB + * using sDMA (VI). + */ +static void si_dma_ring_emit_vm_flush(struct amdgpu_ring *ring, + unsigned vm_id, uint64_t pd_addr) +{ + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); + if (vm_id < 8) { + amdgpu_ring_write(ring, (0xf << 16) | (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + vm_id)); + } else { + amdgpu_ring_write(ring, (0xf << 16) | (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + (vm_id - 8))); + } + amdgpu_ring_write(ring, pd_addr >> 12); + + /* bits 0-7 are the VM contexts0-7 */ + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); + amdgpu_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST)); + amdgpu_ring_write(ring, 1 << vm_id); + + /* wait for invalidate to complete */ + amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_POLL_REG_MEM, 0, 0, 0, 0)); + amdgpu_ring_write(ring, VM_INVALIDATE_REQUEST); + amdgpu_ring_write(ring, 0xff << 16); /* retry */ + amdgpu_ring_write(ring, 1 << vm_id); /* mask */ + amdgpu_ring_write(ring, 0); /* value */ + amdgpu_ring_write(ring, (0 << 28) | 0x20); /* func(always) | poll interval */ +} + +static int si_dma_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + adev->sdma.num_instances = 2; + + si_dma_set_ring_funcs(adev); + si_dma_set_buffer_funcs(adev); + si_dma_set_vm_pte_funcs(adev); + si_dma_set_irq_funcs(adev); + + return 0; +} + +static int si_dma_sw_init(void *handle) +{ + struct amdgpu_ring *ring; + int r, i; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + /* DMA0 trap event */ + r = amdgpu_irq_add_id(adev, 224, &adev->sdma.trap_irq); + if (r) + return r; + + /* DMA1 trap event */ + r = amdgpu_irq_add_id(adev, 244, &adev->sdma.trap_irq_1); + if (r) + return r; + + for (i = 0; i < adev->sdma.num_instances; i++) { + ring = &adev->sdma.instance[i].ring; + ring->ring_obj = NULL; + ring->use_doorbell = false; + sprintf(ring->name, "sdma%d", i); + r = amdgpu_ring_init(adev, ring, 1024, + DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0), 0xf, + &adev->sdma.trap_irq, + (i == 0) ? + AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1, + AMDGPU_RING_TYPE_SDMA); + if (r) + return r; + } + + return r; +} + +static int si_dma_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int i; + + for (i = 0; i < adev->sdma.num_instances; i++) + amdgpu_ring_fini(&adev->sdma.instance[i].ring); + + return 0; +} + +static int si_dma_hw_init(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + r = si_dma_start(adev); + if (r) + return r; + + return r; +} + +static int si_dma_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + si_dma_stop(adev); + + return 0; +} + +static int si_dma_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return si_dma_hw_fini(adev); +} + +static int si_dma_resume(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return si_dma_hw_init(adev); +} + +static bool si_dma_is_idle(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + u32 tmp = RREG32(SRBM_STATUS2); + + if (tmp & (DMA_BUSY_MASK | DMA1_BUSY_MASK)) + return false; + + return true; +} + +static int si_dma_wait_for_idle(void *handle) +{ + unsigned i; + u32 tmp; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(SRBM_STATUS2) & (DMA_BUSY_MASK | DMA1_BUSY_MASK); + + if (!tmp) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int si_dma_soft_reset(void *handle) +{ + DRM_INFO("si_dma_soft_reset --- not implemented !!!!!!!\n"); + return 0; +} + +static int si_dma_set_trap_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 sdma_cntl; + + switch (type) { + case AMDGPU_SDMA_IRQ_TRAP0: + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + sdma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET); + sdma_cntl &= ~TRAP_ENABLE; + WREG32(DMA_CNTL + DMA0_REGISTER_OFFSET, sdma_cntl); + break; + case AMDGPU_IRQ_STATE_ENABLE: + sdma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET); + sdma_cntl |= TRAP_ENABLE; + WREG32(DMA_CNTL + DMA0_REGISTER_OFFSET, sdma_cntl); + break; + default: + break; + } + break; + case AMDGPU_SDMA_IRQ_TRAP1: + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + sdma_cntl = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET); + sdma_cntl &= ~TRAP_ENABLE; + WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, sdma_cntl); + break; + case AMDGPU_IRQ_STATE_ENABLE: + sdma_cntl = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET); + sdma_cntl |= TRAP_ENABLE; + WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, sdma_cntl); + break; + default: + break; + } + break; + default: + break; + } + return 0; +} + +static int si_dma_process_trap_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + u8 instance_id, queue_id; + + instance_id = (entry->ring_id & 0x3) >> 0; + queue_id = (entry->ring_id & 0xc) >> 2; + + amdgpu_fence_process(&adev->sdma.instance[0].ring); + + return 0; +} + +static int si_dma_process_trap_irq_1(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + u8 instance_id, queue_id; + + instance_id = (entry->ring_id & 0x3) >> 0; + queue_id = (entry->ring_id & 0xc) >> 2; + + amdgpu_fence_process(&adev->sdma.instance[1].ring); + + return 0; +} + +static int si_dma_process_illegal_inst_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + DRM_ERROR("Illegal instruction in SDMA command stream\n"); + schedule_work(&adev->reset_work); + return 0; +} + +static int si_dma_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + u32 orig, data, offset; + int i; + bool enable; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + enable = (state == AMD_CG_STATE_GATE) ? true : false; + + if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) { + for (i = 0; i < adev->sdma.num_instances; i++) { + if (i == 0) + offset = DMA0_REGISTER_OFFSET; + else + offset = DMA1_REGISTER_OFFSET; + orig = data = RREG32(DMA_POWER_CNTL + offset); + data &= ~MEM_POWER_OVERRIDE; + if (data != orig) + WREG32(DMA_POWER_CNTL + offset, data); + WREG32(DMA_CLK_CTRL + offset, 0x00000100); + } + } else { + for (i = 0; i < adev->sdma.num_instances; i++) { + if (i == 0) + offset = DMA0_REGISTER_OFFSET; + else + offset = DMA1_REGISTER_OFFSET; + orig = data = RREG32(DMA_POWER_CNTL + offset); + data |= MEM_POWER_OVERRIDE; + if (data != orig) + WREG32(DMA_POWER_CNTL + offset, data); + + orig = data = RREG32(DMA_CLK_CTRL + offset); + data = 0xff000000; + if (data != orig) + WREG32(DMA_CLK_CTRL + offset, data); + } + } + + return 0; +} + +static int si_dma_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + u32 tmp; + + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + WREG32(DMA_PGFSM_WRITE, 0x00002000); + WREG32(DMA_PGFSM_CONFIG, 0x100010ff); + + for (tmp = 0; tmp < 5; tmp++) + WREG32(DMA_PGFSM_WRITE, 0); + + return 0; +} + +const struct amd_ip_funcs si_dma_ip_funcs = { + .name = "si_dma", + .early_init = si_dma_early_init, + .late_init = NULL, + .sw_init = si_dma_sw_init, + .sw_fini = si_dma_sw_fini, + .hw_init = si_dma_hw_init, + .hw_fini = si_dma_hw_fini, + .suspend = si_dma_suspend, + .resume = si_dma_resume, + .is_idle = si_dma_is_idle, + .wait_for_idle = si_dma_wait_for_idle, + .soft_reset = si_dma_soft_reset, + .set_clockgating_state = si_dma_set_clockgating_state, + .set_powergating_state = si_dma_set_powergating_state, +}; + +static const struct amdgpu_ring_funcs si_dma_ring_funcs = { + .get_rptr = si_dma_ring_get_rptr, + .get_wptr = si_dma_ring_get_wptr, + .set_wptr = si_dma_ring_set_wptr, + .parse_cs = NULL, + .emit_ib = si_dma_ring_emit_ib, + .emit_fence = si_dma_ring_emit_fence, + .emit_pipeline_sync = si_dma_ring_emit_pipeline_sync, + .emit_vm_flush = si_dma_ring_emit_vm_flush, + .emit_hdp_flush = si_dma_ring_emit_hdp_flush, + .emit_hdp_invalidate = si_dma_ring_emit_hdp_invalidate, + .test_ring = si_dma_ring_test_ring, + .test_ib = si_dma_ring_test_ib, + .insert_nop = amdgpu_ring_insert_nop, + .pad_ib = si_dma_ring_pad_ib, +}; + +static void si_dma_set_ring_funcs(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < adev->sdma.num_instances; i++) + adev->sdma.instance[i].ring.funcs = &si_dma_ring_funcs; +} + +static const struct amdgpu_irq_src_funcs si_dma_trap_irq_funcs = { + .set = si_dma_set_trap_irq_state, + .process = si_dma_process_trap_irq, +}; + +static const struct amdgpu_irq_src_funcs si_dma_trap_irq_funcs_1 = { + .set = si_dma_set_trap_irq_state, + .process = si_dma_process_trap_irq_1, +}; + +static const struct amdgpu_irq_src_funcs si_dma_illegal_inst_irq_funcs = { + .process = si_dma_process_illegal_inst_irq, +}; + +static void si_dma_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->sdma.trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST; + adev->sdma.trap_irq.funcs = &si_dma_trap_irq_funcs; + adev->sdma.trap_irq_1.funcs = &si_dma_trap_irq_funcs_1; + adev->sdma.illegal_inst_irq.funcs = &si_dma_illegal_inst_irq_funcs; +} + +/** + * si_dma_emit_copy_buffer - copy buffer using the sDMA engine + * + * @ring: amdgpu_ring structure holding ring information + * @src_offset: src GPU address + * @dst_offset: dst GPU address + * @byte_count: number of bytes to xfer + * + * Copy GPU buffers using the DMA engine (VI). + * Used by the amdgpu ttm implementation to move pages if + * registered as the asic copy callback. + */ +static void si_dma_emit_copy_buffer(struct amdgpu_ib *ib, + uint64_t src_offset, + uint64_t dst_offset, + uint32_t byte_count) +{ + ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY, + 1, 0, 0, byte_count); + ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset); + ib->ptr[ib->length_dw++] = lower_32_bits(src_offset); + ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset) & 0xff; + ib->ptr[ib->length_dw++] = upper_32_bits(src_offset) & 0xff; +} + +/** + * si_dma_emit_fill_buffer - fill buffer using the sDMA engine + * + * @ring: amdgpu_ring structure holding ring information + * @src_data: value to write to buffer + * @dst_offset: dst GPU address + * @byte_count: number of bytes to xfer + * + * Fill GPU buffers using the DMA engine (VI). + */ +static void si_dma_emit_fill_buffer(struct amdgpu_ib *ib, + uint32_t src_data, + uint64_t dst_offset, + uint32_t byte_count) +{ + ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_CONSTANT_FILL, + 0, 0, 0, byte_count / 4); + ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset); + ib->ptr[ib->length_dw++] = src_data; + ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset) << 16; +} + + +static const struct amdgpu_buffer_funcs si_dma_buffer_funcs = { + .copy_max_bytes = 0xffff8, + .copy_num_dw = 5, + .emit_copy_buffer = si_dma_emit_copy_buffer, + + .fill_max_bytes = 0xffff8, + .fill_num_dw = 4, + .emit_fill_buffer = si_dma_emit_fill_buffer, +}; + +static void si_dma_set_buffer_funcs(struct amdgpu_device *adev) +{ + if (adev->mman.buffer_funcs == NULL) { + adev->mman.buffer_funcs = &si_dma_buffer_funcs; + adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring; + } +} + +static const struct amdgpu_vm_pte_funcs si_dma_vm_pte_funcs = { + .copy_pte = si_dma_vm_copy_pte, + .write_pte = si_dma_vm_write_pte, + .set_pte_pde = si_dma_vm_set_pte_pde, +}; + +static void si_dma_set_vm_pte_funcs(struct amdgpu_device *adev) +{ + unsigned i; + + if (adev->vm_manager.vm_pte_funcs == NULL) { + adev->vm_manager.vm_pte_funcs = &si_dma_vm_pte_funcs; + for (i = 0; i < adev->sdma.num_instances; i++) + adev->vm_manager.vm_pte_rings[i] = + &adev->sdma.instance[i].ring; + + adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.h b/drivers/gpu/drm/amd/amdgpu/si_dma.h new file mode 100644 index 0000000..3a3e0c7 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.h @@ -0,0 +1,29 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __SI_DMA_H__ +#define __SI_DMA_H__ + +extern const struct amd_ip_funcs si_dma_ip_funcs; + +#endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/si/sid.h b/drivers/gpu/drm/amd/include/asic_reg/si/sid.h index a96d930..f30e57d 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/si/sid.h +++ b/drivers/gpu/drm/amd/include/asic_reg/si/sid.h @@ -642,6 +642,8 @@ #define HDP_NONSURFACE_INFO 0xB02 #define HDP_NONSURFACE_SIZE 0xB03 +#define HDP_DEBUG0 0xBCC + #define HDP_ADDR_CONFIG 0xBD2 #define HDP_MISC_CNTL 0xBD3 #define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) -- cgit v1.1 From 62a37553414a344491c64e8fd89577dcc1b8bcbb Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 14:08:49 +0800 Subject: drm/amdgpu: add si implementation v10 v5: rebase fixes v6: add mgcg arrays v7: rebase fixes v8: rebase fixes v9: add get_disabled_bios(), make get_xclk static v10: fix oland and hainan asic specific handle at si_program_aspm Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 1963 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/si.h | 33 + drivers/gpu/drm/amd/include/asic_reg/si/sid.h | 45 + 3 files changed, 2041 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/si.c create mode 100644 drivers/gpu/drm/amd/amdgpu/si.h diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c new file mode 100644 index 0000000..74dbfca --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -0,0 +1,1963 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include "drmP.h" +#include "amdgpu.h" +#include "amdgpu_atombios.h" +#include "amdgpu_ih.h" +#include "amdgpu_uvd.h" +#include "amdgpu_vce.h" +#include "atom.h" +#include "amdgpu_powerplay.h" +#include "si/sid.h" +#include "si_ih.h" +#include "gfx_v6_0.h" +#include "gmc_v6_0.h" +#include "si_dma.h" +#include "dce_v6_0.h" +#include "si.h" + +static const u32 tahiti_golden_registers[] = +{ + 0x2684, 0x00010000, 0x00018208, + 0x260c, 0xffffffff, 0x00000000, + 0x260d, 0xf00fffff, 0x00000400, + 0x260e, 0x0002021c, 0x00020200, + 0x031e, 0x00000080, 0x00000000, + 0x340c, 0x000300c0, 0x00800040, + 0x360c, 0x000300c0, 0x00800040, + 0x16ec, 0x000000f0, 0x00000070, + 0x16f0, 0x00200000, 0x50100000, + 0x1c0c, 0x31000311, 0x00000011, + 0x09df, 0x00000003, 0x000007ff, + 0x0903, 0x000007ff, 0x00000000, + 0x2285, 0xf000001f, 0x00000007, + 0x22c9, 0xffffffff, 0x00ffffff, + 0x22c4, 0x0000ff0f, 0x00000000, + 0xa293, 0x07ffffff, 0x4e000000, + 0xa0d4, 0x3f3f3fff, 0x2a00126a, + 0x000c, 0x000000ff, 0x0040, + 0x000d, 0x00000040, 0x00004040, + 0x2440, 0x07ffffff, 0x03000000, + 0x23a2, 0x01ff1f3f, 0x00000000, + 0x23a1, 0x01ff1f3f, 0x00000000, + 0x2418, 0x0000007f, 0x00000020, + 0x2542, 0x00010000, 0x00010000, + 0x2b05, 0x00000200, 0x000002fb, + 0x2b04, 0xffffffff, 0x0000543b, + 0x2b03, 0xffffffff, 0xa9210876, + 0x2234, 0xffffffff, 0x000fff40, + 0x2235, 0x0000001f, 0x00000010, + 0x0504, 0x20000000, 0x20fffed8, + 0x0570, 0x000c0fc0, 0x000c0400 +}; + +static const u32 tahiti_golden_registers2[] = +{ + 0x0319, 0x00000001, 0x00000001 +}; + +static const u32 tahiti_golden_rlc_registers[] = +{ + 0x3109, 0xffffffff, 0x00601005, + 0x311f, 0xffffffff, 0x10104040, + 0x3122, 0xffffffff, 0x0100000a, + 0x30c5, 0xffffffff, 0x00000800, + 0x30c3, 0xffffffff, 0x800000f4, + 0x3d2a, 0xffffffff, 0x00000000 +}; + +static const u32 pitcairn_golden_registers[] = +{ + 0x2684, 0x00010000, 0x00018208, + 0x260c, 0xffffffff, 0x00000000, + 0x260d, 0xf00fffff, 0x00000400, + 0x260e, 0x0002021c, 0x00020200, + 0x031e, 0x00000080, 0x00000000, + 0x340c, 0x000300c0, 0x00800040, + 0x360c, 0x000300c0, 0x00800040, + 0x16ec, 0x000000f0, 0x00000070, + 0x16f0, 0x00200000, 0x50100000, + 0x1c0c, 0x31000311, 0x00000011, + 0x0ab9, 0x00073ffe, 0x000022a2, + 0x0903, 0x000007ff, 0x00000000, + 0x2285, 0xf000001f, 0x00000007, + 0x22c9, 0xffffffff, 0x00ffffff, + 0x22c4, 0x0000ff0f, 0x00000000, + 0xa293, 0x07ffffff, 0x4e000000, + 0xa0d4, 0x3f3f3fff, 0x2a00126a, + 0x000c, 0x000000ff, 0x0040, + 0x000d, 0x00000040, 0x00004040, + 0x2440, 0x07ffffff, 0x03000000, + 0x2418, 0x0000007f, 0x00000020, + 0x2542, 0x00010000, 0x00010000, + 0x2b05, 0x000003ff, 0x000000f7, + 0x2b04, 0xffffffff, 0x00000000, + 0x2b03, 0xffffffff, 0x32761054, + 0x2235, 0x0000001f, 0x00000010, + 0x0570, 0x000c0fc0, 0x000c0400 +}; + +static const u32 pitcairn_golden_rlc_registers[] = +{ + 0x3109, 0xffffffff, 0x00601004, + 0x311f, 0xffffffff, 0x10102020, + 0x3122, 0xffffffff, 0x01000020, + 0x30c5, 0xffffffff, 0x00000800, + 0x30c3, 0xffffffff, 0x800000a4 +}; + +static const u32 verde_pg_init[] = +{ + 0xd4f, 0xffffffff, 0x40000, + 0xd4e, 0xffffffff, 0x200010ff, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x7007, + 0xd4e, 0xffffffff, 0x300010ff, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x400000, + 0xd4e, 0xffffffff, 0x100010ff, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x120200, + 0xd4e, 0xffffffff, 0x500010ff, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x1e1e16, + 0xd4e, 0xffffffff, 0x600010ff, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x171f1e, + 0xd4e, 0xffffffff, 0x700010ff, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4f, 0xffffffff, 0x0, + 0xd4e, 0xffffffff, 0x9ff, + 0xd40, 0xffffffff, 0x0, + 0xd41, 0xffffffff, 0x10000800, + 0xd41, 0xffffffff, 0xf, + 0xd41, 0xffffffff, 0xf, + 0xd40, 0xffffffff, 0x4, + 0xd41, 0xffffffff, 0x1000051e, + 0xd41, 0xffffffff, 0xffff, + 0xd41, 0xffffffff, 0xffff, + 0xd40, 0xffffffff, 0x8, + 0xd41, 0xffffffff, 0x80500, + 0xd40, 0xffffffff, 0x12, + 0xd41, 0xffffffff, 0x9050c, + 0xd40, 0xffffffff, 0x1d, + 0xd41, 0xffffffff, 0xb052c, + 0xd40, 0xffffffff, 0x2a, + 0xd41, 0xffffffff, 0x1053e, + 0xd40, 0xffffffff, 0x2d, + 0xd41, 0xffffffff, 0x10546, + 0xd40, 0xffffffff, 0x30, + 0xd41, 0xffffffff, 0xa054e, + 0xd40, 0xffffffff, 0x3c, + 0xd41, 0xffffffff, 0x1055f, + 0xd40, 0xffffffff, 0x3f, + 0xd41, 0xffffffff, 0x10567, + 0xd40, 0xffffffff, 0x42, + 0xd41, 0xffffffff, 0x1056f, + 0xd40, 0xffffffff, 0x45, + 0xd41, 0xffffffff, 0x10572, + 0xd40, 0xffffffff, 0x48, + 0xd41, 0xffffffff, 0x20575, + 0xd40, 0xffffffff, 0x4c, + 0xd41, 0xffffffff, 0x190801, + 0xd40, 0xffffffff, 0x67, + 0xd41, 0xffffffff, 0x1082a, + 0xd40, 0xffffffff, 0x6a, + 0xd41, 0xffffffff, 0x1b082d, + 0xd40, 0xffffffff, 0x87, + 0xd41, 0xffffffff, 0x310851, + 0xd40, 0xffffffff, 0xba, + 0xd41, 0xffffffff, 0x891, + 0xd40, 0xffffffff, 0xbc, + 0xd41, 0xffffffff, 0x893, + 0xd40, 0xffffffff, 0xbe, + 0xd41, 0xffffffff, 0x20895, + 0xd40, 0xffffffff, 0xc2, + 0xd41, 0xffffffff, 0x20899, + 0xd40, 0xffffffff, 0xc6, + 0xd41, 0xffffffff, 0x2089d, + 0xd40, 0xffffffff, 0xca, + 0xd41, 0xffffffff, 0x8a1, + 0xd40, 0xffffffff, 0xcc, + 0xd41, 0xffffffff, 0x8a3, + 0xd40, 0xffffffff, 0xce, + 0xd41, 0xffffffff, 0x308a5, + 0xd40, 0xffffffff, 0xd3, + 0xd41, 0xffffffff, 0x6d08cd, + 0xd40, 0xffffffff, 0x142, + 0xd41, 0xffffffff, 0x2000095a, + 0xd41, 0xffffffff, 0x1, + 0xd40, 0xffffffff, 0x144, + 0xd41, 0xffffffff, 0x301f095b, + 0xd40, 0xffffffff, 0x165, + 0xd41, 0xffffffff, 0xc094d, + 0xd40, 0xffffffff, 0x173, + 0xd41, 0xffffffff, 0xf096d, + 0xd40, 0xffffffff, 0x184, + 0xd41, 0xffffffff, 0x15097f, + 0xd40, 0xffffffff, 0x19b, + 0xd41, 0xffffffff, 0xc0998, + 0xd40, 0xffffffff, 0x1a9, + 0xd41, 0xffffffff, 0x409a7, + 0xd40, 0xffffffff, 0x1af, + 0xd41, 0xffffffff, 0xcdc, + 0xd40, 0xffffffff, 0x1b1, + 0xd41, 0xffffffff, 0x800, + 0xd42, 0xffffffff, 0x6c9b2000, + 0xd44, 0xfc00, 0x2000, + 0xd51, 0xffffffff, 0xfc0, + 0xa35, 0x00000100, 0x100 +}; + +static const u32 verde_golden_rlc_registers[] = +{ + 0x3109, 0xffffffff, 0x033f1005, + 0x311f, 0xffffffff, 0x10808020, + 0x3122, 0xffffffff, 0x00800008, + 0x30c5, 0xffffffff, 0x00001000, + 0x30c3, 0xffffffff, 0x80010014 +}; + +static const u32 verde_golden_registers[] = +{ + 0x2684, 0x00010000, 0x00018208, + 0x260c, 0xffffffff, 0x00000000, + 0x260d, 0xf00fffff, 0x00000400, + 0x260e, 0x0002021c, 0x00020200, + 0x031e, 0x00000080, 0x00000000, + 0x340c, 0x000300c0, 0x00800040, + 0x340c, 0x000300c0, 0x00800040, + 0x360c, 0x000300c0, 0x00800040, + 0x360c, 0x000300c0, 0x00800040, + 0x16ec, 0x000000f0, 0x00000070, + 0x16f0, 0x00200000, 0x50100000, + + 0x1c0c, 0x31000311, 0x00000011, + 0x0ab9, 0x00073ffe, 0x000022a2, + 0x0ab9, 0x00073ffe, 0x000022a2, + 0x0ab9, 0x00073ffe, 0x000022a2, + 0x0903, 0x000007ff, 0x00000000, + 0x0903, 0x000007ff, 0x00000000, + 0x0903, 0x000007ff, 0x00000000, + 0x2285, 0xf000001f, 0x00000007, + 0x2285, 0xf000001f, 0x00000007, + 0x2285, 0xf000001f, 0x00000007, + 0x2285, 0xffffffff, 0x00ffffff, + 0x22c4, 0x0000ff0f, 0x00000000, + + 0xa293, 0x07ffffff, 0x4e000000, + 0xa0d4, 0x3f3f3fff, 0x0000124a, + 0xa0d4, 0x3f3f3fff, 0x0000124a, + 0xa0d4, 0x3f3f3fff, 0x0000124a, + 0x000c, 0x000000ff, 0x0040, + 0x000d, 0x00000040, 0x00004040, + 0x2440, 0x07ffffff, 0x03000000, + 0x2440, 0x07ffffff, 0x03000000, + 0x23a2, 0x01ff1f3f, 0x00000000, + 0x23a3, 0x01ff1f3f, 0x00000000, + 0x23a2, 0x01ff1f3f, 0x00000000, + 0x23a1, 0x01ff1f3f, 0x00000000, + 0x23a1, 0x01ff1f3f, 0x00000000, + + 0x23a1, 0x01ff1f3f, 0x00000000, + 0x2418, 0x0000007f, 0x00000020, + 0x2542, 0x00010000, 0x00010000, + 0x2b01, 0x000003ff, 0x00000003, + 0x2b05, 0x000003ff, 0x00000003, + 0x2b05, 0x000003ff, 0x00000003, + 0x2b04, 0xffffffff, 0x00000000, + 0x2b04, 0xffffffff, 0x00000000, + 0x2b04, 0xffffffff, 0x00000000, + 0x2b03, 0xffffffff, 0x00001032, + 0x2b03, 0xffffffff, 0x00001032, + 0x2b03, 0xffffffff, 0x00001032, + 0x2235, 0x0000001f, 0x00000010, + 0x2235, 0x0000001f, 0x00000010, + 0x2235, 0x0000001f, 0x00000010, + 0x0570, 0x000c0fc0, 0x000c0400 +}; + +static const u32 oland_golden_registers[] = +{ + 0x2684, 0x00010000, 0x00018208, + 0x260c, 0xffffffff, 0x00000000, + 0x260d, 0xf00fffff, 0x00000400, + 0x260e, 0x0002021c, 0x00020200, + 0x031e, 0x00000080, 0x00000000, + 0x340c, 0x000300c0, 0x00800040, + 0x360c, 0x000300c0, 0x00800040, + 0x16ec, 0x000000f0, 0x00000070, + 0x16f9, 0x00200000, 0x50100000, + 0x1c0c, 0x31000311, 0x00000011, + 0x0ab9, 0x00073ffe, 0x000022a2, + 0x0903, 0x000007ff, 0x00000000, + 0x2285, 0xf000001f, 0x00000007, + 0x22c9, 0xffffffff, 0x00ffffff, + 0x22c4, 0x0000ff0f, 0x00000000, + 0xa293, 0x07ffffff, 0x4e000000, + 0xa0d4, 0x3f3f3fff, 0x00000082, + 0x000c, 0x000000ff, 0x0040, + 0x000d, 0x00000040, 0x00004040, + 0x2440, 0x07ffffff, 0x03000000, + 0x2418, 0x0000007f, 0x00000020, + 0x2542, 0x00010000, 0x00010000, + 0x2b05, 0x000003ff, 0x000000f3, + 0x2b04, 0xffffffff, 0x00000000, + 0x2b03, 0xffffffff, 0x00003210, + 0x2235, 0x0000001f, 0x00000010, + 0x0570, 0x000c0fc0, 0x000c0400 +}; + +static const u32 oland_golden_rlc_registers[] = +{ + 0x3109, 0xffffffff, 0x00601005, + 0x311f, 0xffffffff, 0x10104040, + 0x3122, 0xffffffff, 0x0100000a, + 0x30c5, 0xffffffff, 0x00000800, + 0x30c3, 0xffffffff, 0x800000f4 +}; + +static const u32 hainan_golden_registers[] = +{ + 0x2684, 0x00010000, 0x00018208, + 0x260c, 0xffffffff, 0x00000000, + 0x260d, 0xf00fffff, 0x00000400, + 0x260e, 0x0002021c, 0x00020200, + 0x4595, 0xff000fff, 0x00000100, + 0x340c, 0x000300c0, 0x00800040, + 0x3630, 0xff000fff, 0x00000100, + 0x360c, 0x000300c0, 0x00800040, + 0x0ab9, 0x00073ffe, 0x000022a2, + 0x0903, 0x000007ff, 0x00000000, + 0x2285, 0xf000001f, 0x00000007, + 0x22c9, 0xffffffff, 0x00ffffff, + 0x22c4, 0x0000ff0f, 0x00000000, + 0xa393, 0x07ffffff, 0x4e000000, + 0xa0d4, 0x3f3f3fff, 0x00000000, + 0x000c, 0x000000ff, 0x0040, + 0x000d, 0x00000040, 0x00004040, + 0x2440, 0x03e00000, 0x03600000, + 0x2418, 0x0000007f, 0x00000020, + 0x2542, 0x00010000, 0x00010000, + 0x2b05, 0x000003ff, 0x000000f1, + 0x2b04, 0xffffffff, 0x00000000, + 0x2b03, 0xffffffff, 0x00003210, + 0x2235, 0x0000001f, 0x00000010, + 0x0570, 0x000c0fc0, 0x000c0400 +}; + +static const u32 hainan_golden_registers2[] = +{ + 0x263e, 0xffffffff, 0x02010001 +}; + +static const u32 tahiti_mgcg_cgcg_init[] = +{ + 0x3100, 0xffffffff, 0xfffffffc, + 0x200b, 0xffffffff, 0xe0000000, + 0x2698, 0xffffffff, 0x00000100, + 0x24a9, 0xffffffff, 0x00000100, + 0x3059, 0xffffffff, 0x00000100, + 0x25dd, 0xffffffff, 0x00000100, + 0x2261, 0xffffffff, 0x06000100, + 0x2286, 0xffffffff, 0x00000100, + 0x24a8, 0xffffffff, 0x00000100, + 0x30e0, 0xffffffff, 0x00000100, + 0x22ca, 0xffffffff, 0x00000100, + 0x2451, 0xffffffff, 0x00000100, + 0x2362, 0xffffffff, 0x00000100, + 0x2363, 0xffffffff, 0x00000100, + 0x240c, 0xffffffff, 0x00000100, + 0x240d, 0xffffffff, 0x00000100, + 0x240e, 0xffffffff, 0x00000100, + 0x240f, 0xffffffff, 0x00000100, + 0x2b60, 0xffffffff, 0x00000100, + 0x2b15, 0xffffffff, 0x00000100, + 0x225f, 0xffffffff, 0x06000100, + 0x261a, 0xffffffff, 0x00000100, + 0x2544, 0xffffffff, 0x00000100, + 0x2bc1, 0xffffffff, 0x00000100, + 0x2b81, 0xffffffff, 0x00000100, + 0x2527, 0xffffffff, 0x00000100, + 0x200b, 0xffffffff, 0xe0000000, + 0x2458, 0xffffffff, 0x00010000, + 0x2459, 0xffffffff, 0x00030002, + 0x245a, 0xffffffff, 0x00040007, + 0x245b, 0xffffffff, 0x00060005, + 0x245c, 0xffffffff, 0x00090008, + 0x245d, 0xffffffff, 0x00020001, + 0x245e, 0xffffffff, 0x00040003, + 0x245f, 0xffffffff, 0x00000007, + 0x2460, 0xffffffff, 0x00060005, + 0x2461, 0xffffffff, 0x00090008, + 0x2462, 0xffffffff, 0x00030002, + 0x2463, 0xffffffff, 0x00050004, + 0x2464, 0xffffffff, 0x00000008, + 0x2465, 0xffffffff, 0x00070006, + 0x2466, 0xffffffff, 0x000a0009, + 0x2467, 0xffffffff, 0x00040003, + 0x2468, 0xffffffff, 0x00060005, + 0x2469, 0xffffffff, 0x00000009, + 0x246a, 0xffffffff, 0x00080007, + 0x246b, 0xffffffff, 0x000b000a, + 0x246c, 0xffffffff, 0x00050004, + 0x246d, 0xffffffff, 0x00070006, + 0x246e, 0xffffffff, 0x0008000b, + 0x246f, 0xffffffff, 0x000a0009, + 0x2470, 0xffffffff, 0x000d000c, + 0x2471, 0xffffffff, 0x00060005, + 0x2472, 0xffffffff, 0x00080007, + 0x2473, 0xffffffff, 0x0000000b, + 0x2474, 0xffffffff, 0x000a0009, + 0x2475, 0xffffffff, 0x000d000c, + 0x2476, 0xffffffff, 0x00070006, + 0x2477, 0xffffffff, 0x00090008, + 0x2478, 0xffffffff, 0x0000000c, + 0x2479, 0xffffffff, 0x000b000a, + 0x247a, 0xffffffff, 0x000e000d, + 0x247b, 0xffffffff, 0x00080007, + 0x247c, 0xffffffff, 0x000a0009, + 0x247d, 0xffffffff, 0x0000000d, + 0x247e, 0xffffffff, 0x000c000b, + 0x247f, 0xffffffff, 0x000f000e, + 0x2480, 0xffffffff, 0x00090008, + 0x2481, 0xffffffff, 0x000b000a, + 0x2482, 0xffffffff, 0x000c000f, + 0x2483, 0xffffffff, 0x000e000d, + 0x2484, 0xffffffff, 0x00110010, + 0x2485, 0xffffffff, 0x000a0009, + 0x2486, 0xffffffff, 0x000c000b, + 0x2487, 0xffffffff, 0x0000000f, + 0x2488, 0xffffffff, 0x000e000d, + 0x2489, 0xffffffff, 0x00110010, + 0x248a, 0xffffffff, 0x000b000a, + 0x248b, 0xffffffff, 0x000d000c, + 0x248c, 0xffffffff, 0x00000010, + 0x248d, 0xffffffff, 0x000f000e, + 0x248e, 0xffffffff, 0x00120011, + 0x248f, 0xffffffff, 0x000c000b, + 0x2490, 0xffffffff, 0x000e000d, + 0x2491, 0xffffffff, 0x00000011, + 0x2492, 0xffffffff, 0x0010000f, + 0x2493, 0xffffffff, 0x00130012, + 0x2494, 0xffffffff, 0x000d000c, + 0x2495, 0xffffffff, 0x000f000e, + 0x2496, 0xffffffff, 0x00100013, + 0x2497, 0xffffffff, 0x00120011, + 0x2498, 0xffffffff, 0x00150014, + 0x2499, 0xffffffff, 0x000e000d, + 0x249a, 0xffffffff, 0x0010000f, + 0x249b, 0xffffffff, 0x00000013, + 0x249c, 0xffffffff, 0x00120011, + 0x249d, 0xffffffff, 0x00150014, + 0x249e, 0xffffffff, 0x000f000e, + 0x249f, 0xffffffff, 0x00110010, + 0x24a0, 0xffffffff, 0x00000014, + 0x24a1, 0xffffffff, 0x00130012, + 0x24a2, 0xffffffff, 0x00160015, + 0x24a3, 0xffffffff, 0x0010000f, + 0x24a4, 0xffffffff, 0x00120011, + 0x24a5, 0xffffffff, 0x00000015, + 0x24a6, 0xffffffff, 0x00140013, + 0x24a7, 0xffffffff, 0x00170016, + 0x2454, 0xffffffff, 0x96940200, + 0x21c2, 0xffffffff, 0x00900100, + 0x311e, 0xffffffff, 0x00000080, + 0x3101, 0xffffffff, 0x0020003f, + 0xc, 0xffffffff, 0x0000001c, + 0xd, 0x000f0000, 0x000f0000, + 0x583, 0xffffffff, 0x00000100, + 0x409, 0xffffffff, 0x00000100, + 0x40b, 0x00000101, 0x00000000, + 0x82a, 0xffffffff, 0x00000104, + 0x993, 0x000c0000, 0x000c0000, + 0x992, 0x000c0000, 0x000c0000, + 0x1579, 0xff000fff, 0x00000100, + 0x157a, 0x00000001, 0x00000001, + 0xbd4, 0x00000001, 0x00000001, + 0xc33, 0xc0000fff, 0x00000104, + 0x3079, 0x00000001, 0x00000001, + 0x3430, 0xfffffff0, 0x00000100, + 0x3630, 0xfffffff0, 0x00000100 +}; +static const u32 pitcairn_mgcg_cgcg_init[] = +{ + 0x3100, 0xffffffff, 0xfffffffc, + 0x200b, 0xffffffff, 0xe0000000, + 0x2698, 0xffffffff, 0x00000100, + 0x24a9, 0xffffffff, 0x00000100, + 0x3059, 0xffffffff, 0x00000100, + 0x25dd, 0xffffffff, 0x00000100, + 0x2261, 0xffffffff, 0x06000100, + 0x2286, 0xffffffff, 0x00000100, + 0x24a8, 0xffffffff, 0x00000100, + 0x30e0, 0xffffffff, 0x00000100, + 0x22ca, 0xffffffff, 0x00000100, + 0x2451, 0xffffffff, 0x00000100, + 0x2362, 0xffffffff, 0x00000100, + 0x2363, 0xffffffff, 0x00000100, + 0x240c, 0xffffffff, 0x00000100, + 0x240d, 0xffffffff, 0x00000100, + 0x240e, 0xffffffff, 0x00000100, + 0x240f, 0xffffffff, 0x00000100, + 0x2b60, 0xffffffff, 0x00000100, + 0x2b15, 0xffffffff, 0x00000100, + 0x225f, 0xffffffff, 0x06000100, + 0x261a, 0xffffffff, 0x00000100, + 0x2544, 0xffffffff, 0x00000100, + 0x2bc1, 0xffffffff, 0x00000100, + 0x2b81, 0xffffffff, 0x00000100, + 0x2527, 0xffffffff, 0x00000100, + 0x200b, 0xffffffff, 0xe0000000, + 0x2458, 0xffffffff, 0x00010000, + 0x2459, 0xffffffff, 0x00030002, + 0x245a, 0xffffffff, 0x00040007, + 0x245b, 0xffffffff, 0x00060005, + 0x245c, 0xffffffff, 0x00090008, + 0x245d, 0xffffffff, 0x00020001, + 0x245e, 0xffffffff, 0x00040003, + 0x245f, 0xffffffff, 0x00000007, + 0x2460, 0xffffffff, 0x00060005, + 0x2461, 0xffffffff, 0x00090008, + 0x2462, 0xffffffff, 0x00030002, + 0x2463, 0xffffffff, 0x00050004, + 0x2464, 0xffffffff, 0x00000008, + 0x2465, 0xffffffff, 0x00070006, + 0x2466, 0xffffffff, 0x000a0009, + 0x2467, 0xffffffff, 0x00040003, + 0x2468, 0xffffffff, 0x00060005, + 0x2469, 0xffffffff, 0x00000009, + 0x246a, 0xffffffff, 0x00080007, + 0x246b, 0xffffffff, 0x000b000a, + 0x246c, 0xffffffff, 0x00050004, + 0x246d, 0xffffffff, 0x00070006, + 0x246e, 0xffffffff, 0x0008000b, + 0x246f, 0xffffffff, 0x000a0009, + 0x2470, 0xffffffff, 0x000d000c, + 0x2480, 0xffffffff, 0x00090008, + 0x2481, 0xffffffff, 0x000b000a, + 0x2482, 0xffffffff, 0x000c000f, + 0x2483, 0xffffffff, 0x000e000d, + 0x2484, 0xffffffff, 0x00110010, + 0x2485, 0xffffffff, 0x000a0009, + 0x2486, 0xffffffff, 0x000c000b, + 0x2487, 0xffffffff, 0x0000000f, + 0x2488, 0xffffffff, 0x000e000d, + 0x2489, 0xffffffff, 0x00110010, + 0x248a, 0xffffffff, 0x000b000a, + 0x248b, 0xffffffff, 0x000d000c, + 0x248c, 0xffffffff, 0x00000010, + 0x248d, 0xffffffff, 0x000f000e, + 0x248e, 0xffffffff, 0x00120011, + 0x248f, 0xffffffff, 0x000c000b, + 0x2490, 0xffffffff, 0x000e000d, + 0x2491, 0xffffffff, 0x00000011, + 0x2492, 0xffffffff, 0x0010000f, + 0x2493, 0xffffffff, 0x00130012, + 0x2494, 0xffffffff, 0x000d000c, + 0x2495, 0xffffffff, 0x000f000e, + 0x2496, 0xffffffff, 0x00100013, + 0x2497, 0xffffffff, 0x00120011, + 0x2498, 0xffffffff, 0x00150014, + 0x2454, 0xffffffff, 0x96940200, + 0x21c2, 0xffffffff, 0x00900100, + 0x311e, 0xffffffff, 0x00000080, + 0x3101, 0xffffffff, 0x0020003f, + 0xc, 0xffffffff, 0x0000001c, + 0xd, 0x000f0000, 0x000f0000, + 0x583, 0xffffffff, 0x00000100, + 0x409, 0xffffffff, 0x00000100, + 0x40b, 0x00000101, 0x00000000, + 0x82a, 0xffffffff, 0x00000104, + 0x1579, 0xff000fff, 0x00000100, + 0x157a, 0x00000001, 0x00000001, + 0xbd4, 0x00000001, 0x00000001, + 0xc33, 0xc0000fff, 0x00000104, + 0x3079, 0x00000001, 0x00000001, + 0x3430, 0xfffffff0, 0x00000100, + 0x3630, 0xfffffff0, 0x00000100 +}; +static const u32 verde_mgcg_cgcg_init[] = +{ + 0x3100, 0xffffffff, 0xfffffffc, + 0x200b, 0xffffffff, 0xe0000000, + 0x2698, 0xffffffff, 0x00000100, + 0x24a9, 0xffffffff, 0x00000100, + 0x3059, 0xffffffff, 0x00000100, + 0x25dd, 0xffffffff, 0x00000100, + 0x2261, 0xffffffff, 0x06000100, + 0x2286, 0xffffffff, 0x00000100, + 0x24a8, 0xffffffff, 0x00000100, + 0x30e0, 0xffffffff, 0x00000100, + 0x22ca, 0xffffffff, 0x00000100, + 0x2451, 0xffffffff, 0x00000100, + 0x2362, 0xffffffff, 0x00000100, + 0x2363, 0xffffffff, 0x00000100, + 0x240c, 0xffffffff, 0x00000100, + 0x240d, 0xffffffff, 0x00000100, + 0x240e, 0xffffffff, 0x00000100, + 0x240f, 0xffffffff, 0x00000100, + 0x2b60, 0xffffffff, 0x00000100, + 0x2b15, 0xffffffff, 0x00000100, + 0x225f, 0xffffffff, 0x06000100, + 0x261a, 0xffffffff, 0x00000100, + 0x2544, 0xffffffff, 0x00000100, + 0x2bc1, 0xffffffff, 0x00000100, + 0x2b81, 0xffffffff, 0x00000100, + 0x2527, 0xffffffff, 0x00000100, + 0x200b, 0xffffffff, 0xe0000000, + 0x2458, 0xffffffff, 0x00010000, + 0x2459, 0xffffffff, 0x00030002, + 0x245a, 0xffffffff, 0x00040007, + 0x245b, 0xffffffff, 0x00060005, + 0x245c, 0xffffffff, 0x00090008, + 0x245d, 0xffffffff, 0x00020001, + 0x245e, 0xffffffff, 0x00040003, + 0x245f, 0xffffffff, 0x00000007, + 0x2460, 0xffffffff, 0x00060005, + 0x2461, 0xffffffff, 0x00090008, + 0x2462, 0xffffffff, 0x00030002, + 0x2463, 0xffffffff, 0x00050004, + 0x2464, 0xffffffff, 0x00000008, + 0x2465, 0xffffffff, 0x00070006, + 0x2466, 0xffffffff, 0x000a0009, + 0x2467, 0xffffffff, 0x00040003, + 0x2468, 0xffffffff, 0x00060005, + 0x2469, 0xffffffff, 0x00000009, + 0x246a, 0xffffffff, 0x00080007, + 0x246b, 0xffffffff, 0x000b000a, + 0x246c, 0xffffffff, 0x00050004, + 0x246d, 0xffffffff, 0x00070006, + 0x246e, 0xffffffff, 0x0008000b, + 0x246f, 0xffffffff, 0x000a0009, + 0x2470, 0xffffffff, 0x000d000c, + 0x2480, 0xffffffff, 0x00090008, + 0x2481, 0xffffffff, 0x000b000a, + 0x2482, 0xffffffff, 0x000c000f, + 0x2483, 0xffffffff, 0x000e000d, + 0x2484, 0xffffffff, 0x00110010, + 0x2485, 0xffffffff, 0x000a0009, + 0x2486, 0xffffffff, 0x000c000b, + 0x2487, 0xffffffff, 0x0000000f, + 0x2488, 0xffffffff, 0x000e000d, + 0x2489, 0xffffffff, 0x00110010, + 0x248a, 0xffffffff, 0x000b000a, + 0x248b, 0xffffffff, 0x000d000c, + 0x248c, 0xffffffff, 0x00000010, + 0x248d, 0xffffffff, 0x000f000e, + 0x248e, 0xffffffff, 0x00120011, + 0x248f, 0xffffffff, 0x000c000b, + 0x2490, 0xffffffff, 0x000e000d, + 0x2491, 0xffffffff, 0x00000011, + 0x2492, 0xffffffff, 0x0010000f, + 0x2493, 0xffffffff, 0x00130012, + 0x2494, 0xffffffff, 0x000d000c, + 0x2495, 0xffffffff, 0x000f000e, + 0x2496, 0xffffffff, 0x00100013, + 0x2497, 0xffffffff, 0x00120011, + 0x2498, 0xffffffff, 0x00150014, + 0x2454, 0xffffffff, 0x96940200, + 0x21c2, 0xffffffff, 0x00900100, + 0x311e, 0xffffffff, 0x00000080, + 0x3101, 0xffffffff, 0x0020003f, + 0xc, 0xffffffff, 0x0000001c, + 0xd, 0x000f0000, 0x000f0000, + 0x583, 0xffffffff, 0x00000100, + 0x409, 0xffffffff, 0x00000100, + 0x40b, 0x00000101, 0x00000000, + 0x82a, 0xffffffff, 0x00000104, + 0x993, 0x000c0000, 0x000c0000, + 0x992, 0x000c0000, 0x000c0000, + 0x1579, 0xff000fff, 0x00000100, + 0x157a, 0x00000001, 0x00000001, + 0xbd4, 0x00000001, 0x00000001, + 0xc33, 0xc0000fff, 0x00000104, + 0x3079, 0x00000001, 0x00000001, + 0x3430, 0xfffffff0, 0x00000100, + 0x3630, 0xfffffff0, 0x00000100 +}; +static const u32 oland_mgcg_cgcg_init[] = +{ + 0x3100, 0xffffffff, 0xfffffffc, + 0x200b, 0xffffffff, 0xe0000000, + 0x2698, 0xffffffff, 0x00000100, + 0x24a9, 0xffffffff, 0x00000100, + 0x3059, 0xffffffff, 0x00000100, + 0x25dd, 0xffffffff, 0x00000100, + 0x2261, 0xffffffff, 0x06000100, + 0x2286, 0xffffffff, 0x00000100, + 0x24a8, 0xffffffff, 0x00000100, + 0x30e0, 0xffffffff, 0x00000100, + 0x22ca, 0xffffffff, 0x00000100, + 0x2451, 0xffffffff, 0x00000100, + 0x2362, 0xffffffff, 0x00000100, + 0x2363, 0xffffffff, 0x00000100, + 0x240c, 0xffffffff, 0x00000100, + 0x240d, 0xffffffff, 0x00000100, + 0x240e, 0xffffffff, 0x00000100, + 0x240f, 0xffffffff, 0x00000100, + 0x2b60, 0xffffffff, 0x00000100, + 0x2b15, 0xffffffff, 0x00000100, + 0x225f, 0xffffffff, 0x06000100, + 0x261a, 0xffffffff, 0x00000100, + 0x2544, 0xffffffff, 0x00000100, + 0x2bc1, 0xffffffff, 0x00000100, + 0x2b81, 0xffffffff, 0x00000100, + 0x2527, 0xffffffff, 0x00000100, + 0x200b, 0xffffffff, 0xe0000000, + 0x2458, 0xffffffff, 0x00010000, + 0x2459, 0xffffffff, 0x00030002, + 0x245a, 0xffffffff, 0x00040007, + 0x245b, 0xffffffff, 0x00060005, + 0x245c, 0xffffffff, 0x00090008, + 0x245d, 0xffffffff, 0x00020001, + 0x245e, 0xffffffff, 0x00040003, + 0x245f, 0xffffffff, 0x00000007, + 0x2460, 0xffffffff, 0x00060005, + 0x2461, 0xffffffff, 0x00090008, + 0x2462, 0xffffffff, 0x00030002, + 0x2463, 0xffffffff, 0x00050004, + 0x2464, 0xffffffff, 0x00000008, + 0x2465, 0xffffffff, 0x00070006, + 0x2466, 0xffffffff, 0x000a0009, + 0x2467, 0xffffffff, 0x00040003, + 0x2468, 0xffffffff, 0x00060005, + 0x2469, 0xffffffff, 0x00000009, + 0x246a, 0xffffffff, 0x00080007, + 0x246b, 0xffffffff, 0x000b000a, + 0x246c, 0xffffffff, 0x00050004, + 0x246d, 0xffffffff, 0x00070006, + 0x246e, 0xffffffff, 0x0008000b, + 0x246f, 0xffffffff, 0x000a0009, + 0x2470, 0xffffffff, 0x000d000c, + 0x2471, 0xffffffff, 0x00060005, + 0x2472, 0xffffffff, 0x00080007, + 0x2473, 0xffffffff, 0x0000000b, + 0x2474, 0xffffffff, 0x000a0009, + 0x2475, 0xffffffff, 0x000d000c, + 0x2454, 0xffffffff, 0x96940200, + 0x21c2, 0xffffffff, 0x00900100, + 0x311e, 0xffffffff, 0x00000080, + 0x3101, 0xffffffff, 0x0020003f, + 0xc, 0xffffffff, 0x0000001c, + 0xd, 0x000f0000, 0x000f0000, + 0x583, 0xffffffff, 0x00000100, + 0x409, 0xffffffff, 0x00000100, + 0x40b, 0x00000101, 0x00000000, + 0x82a, 0xffffffff, 0x00000104, + 0x993, 0x000c0000, 0x000c0000, + 0x992, 0x000c0000, 0x000c0000, + 0x1579, 0xff000fff, 0x00000100, + 0x157a, 0x00000001, 0x00000001, + 0xbd4, 0x00000001, 0x00000001, + 0xc33, 0xc0000fff, 0x00000104, + 0x3079, 0x00000001, 0x00000001, + 0x3430, 0xfffffff0, 0x00000100, + 0x3630, 0xfffffff0, 0x00000100 +}; +static const u32 hainan_mgcg_cgcg_init[] = +{ + 0x3100, 0xffffffff, 0xfffffffc, + 0x200b, 0xffffffff, 0xe0000000, + 0x2698, 0xffffffff, 0x00000100, + 0x24a9, 0xffffffff, 0x00000100, + 0x3059, 0xffffffff, 0x00000100, + 0x25dd, 0xffffffff, 0x00000100, + 0x2261, 0xffffffff, 0x06000100, + 0x2286, 0xffffffff, 0x00000100, + 0x24a8, 0xffffffff, 0x00000100, + 0x30e0, 0xffffffff, 0x00000100, + 0x22ca, 0xffffffff, 0x00000100, + 0x2451, 0xffffffff, 0x00000100, + 0x2362, 0xffffffff, 0x00000100, + 0x2363, 0xffffffff, 0x00000100, + 0x240c, 0xffffffff, 0x00000100, + 0x240d, 0xffffffff, 0x00000100, + 0x240e, 0xffffffff, 0x00000100, + 0x240f, 0xffffffff, 0x00000100, + 0x2b60, 0xffffffff, 0x00000100, + 0x2b15, 0xffffffff, 0x00000100, + 0x225f, 0xffffffff, 0x06000100, + 0x261a, 0xffffffff, 0x00000100, + 0x2544, 0xffffffff, 0x00000100, + 0x2bc1, 0xffffffff, 0x00000100, + 0x2b81, 0xffffffff, 0x00000100, + 0x2527, 0xffffffff, 0x00000100, + 0x200b, 0xffffffff, 0xe0000000, + 0x2458, 0xffffffff, 0x00010000, + 0x2459, 0xffffffff, 0x00030002, + 0x245a, 0xffffffff, 0x00040007, + 0x245b, 0xffffffff, 0x00060005, + 0x245c, 0xffffffff, 0x00090008, + 0x245d, 0xffffffff, 0x00020001, + 0x245e, 0xffffffff, 0x00040003, + 0x245f, 0xffffffff, 0x00000007, + 0x2460, 0xffffffff, 0x00060005, + 0x2461, 0xffffffff, 0x00090008, + 0x2462, 0xffffffff, 0x00030002, + 0x2463, 0xffffffff, 0x00050004, + 0x2464, 0xffffffff, 0x00000008, + 0x2465, 0xffffffff, 0x00070006, + 0x2466, 0xffffffff, 0x000a0009, + 0x2467, 0xffffffff, 0x00040003, + 0x2468, 0xffffffff, 0x00060005, + 0x2469, 0xffffffff, 0x00000009, + 0x246a, 0xffffffff, 0x00080007, + 0x246b, 0xffffffff, 0x000b000a, + 0x246c, 0xffffffff, 0x00050004, + 0x246d, 0xffffffff, 0x00070006, + 0x246e, 0xffffffff, 0x0008000b, + 0x246f, 0xffffffff, 0x000a0009, + 0x2470, 0xffffffff, 0x000d000c, + 0x2471, 0xffffffff, 0x00060005, + 0x2472, 0xffffffff, 0x00080007, + 0x2473, 0xffffffff, 0x0000000b, + 0x2474, 0xffffffff, 0x000a0009, + 0x2475, 0xffffffff, 0x000d000c, + 0x2454, 0xffffffff, 0x96940200, + 0x21c2, 0xffffffff, 0x00900100, + 0x311e, 0xffffffff, 0x00000080, + 0x3101, 0xffffffff, 0x0020003f, + 0xc, 0xffffffff, 0x0000001c, + 0xd, 0x000f0000, 0x000f0000, + 0x583, 0xffffffff, 0x00000100, + 0x409, 0xffffffff, 0x00000100, + 0x82a, 0xffffffff, 0x00000104, + 0x993, 0x000c0000, 0x000c0000, + 0x992, 0x000c0000, 0x000c0000, + 0xbd4, 0x00000001, 0x00000001, + 0xc33, 0xc0000fff, 0x00000104, + 0x3079, 0x00000001, 0x00000001, + 0x3430, 0xfffffff0, 0x00000100, + 0x3630, 0xfffffff0, 0x00000100 +}; + +static u32 si_pcie_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(AMDGPU_PCIE_INDEX, reg); + (void)RREG32(AMDGPU_PCIE_INDEX); + r = RREG32(AMDGPU_PCIE_DATA); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + return r; +} + +static void si_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(AMDGPU_PCIE_INDEX, reg); + (void)RREG32(AMDGPU_PCIE_INDEX); + WREG32(AMDGPU_PCIE_DATA, v); + (void)RREG32(AMDGPU_PCIE_DATA); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} + +static u32 si_smc_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + WREG32(SMC_IND_INDEX_0, (reg)); + r = RREG32(SMC_IND_DATA_0); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + return r; +} + +static void si_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + WREG32(SMC_IND_INDEX_0, (reg)); + WREG32(SMC_IND_DATA_0, (v)); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); +} + +static u32 si_get_virtual_caps(struct amdgpu_device *adev) +{ + /* SI does not support SR-IOV */ + return 0; +} + +static struct amdgpu_allowed_register_entry si_allowed_read_registers[] = { + {GRBM_STATUS, false}, + {GB_ADDR_CONFIG, false}, + {MC_ARB_RAMCFG, false}, + {GB_TILE_MODE0, false}, + {GB_TILE_MODE1, false}, + {GB_TILE_MODE2, false}, + {GB_TILE_MODE3, false}, + {GB_TILE_MODE4, false}, + {GB_TILE_MODE5, false}, + {GB_TILE_MODE6, false}, + {GB_TILE_MODE7, false}, + {GB_TILE_MODE8, false}, + {GB_TILE_MODE9, false}, + {GB_TILE_MODE10, false}, + {GB_TILE_MODE11, false}, + {GB_TILE_MODE12, false}, + {GB_TILE_MODE13, false}, + {GB_TILE_MODE14, false}, + {GB_TILE_MODE15, false}, + {GB_TILE_MODE16, false}, + {GB_TILE_MODE17, false}, + {GB_TILE_MODE18, false}, + {GB_TILE_MODE19, false}, + {GB_TILE_MODE20, false}, + {GB_TILE_MODE21, false}, + {GB_TILE_MODE22, false}, + {GB_TILE_MODE23, false}, + {GB_TILE_MODE24, false}, + {GB_TILE_MODE25, false}, + {GB_TILE_MODE26, false}, + {GB_TILE_MODE27, false}, + {GB_TILE_MODE28, false}, + {GB_TILE_MODE29, false}, + {GB_TILE_MODE30, false}, + {GB_TILE_MODE31, false}, + {CC_RB_BACKEND_DISABLE, false, true}, + {GC_USER_RB_BACKEND_DISABLE, false, true}, + {PA_SC_RASTER_CONFIG, false, true}, +}; + +static uint32_t si_read_indexed_register(struct amdgpu_device *adev, + u32 se_num, u32 sh_num, + u32 reg_offset) +{ + uint32_t val; + + mutex_lock(&adev->grbm_idx_mutex); + if (se_num != 0xffffffff || sh_num != 0xffffffff) + amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff); + + val = RREG32(reg_offset); + + if (se_num != 0xffffffff || sh_num != 0xffffffff) + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); + return val; +} + +static int si_read_register(struct amdgpu_device *adev, u32 se_num, + u32 sh_num, u32 reg_offset, u32 *value) +{ + uint32_t i; + + *value = 0; + for (i = 0; i < ARRAY_SIZE(si_allowed_read_registers); i++) { + if (reg_offset != si_allowed_read_registers[i].reg_offset) + continue; + + if (!si_allowed_read_registers[i].untouched) + *value = si_allowed_read_registers[i].grbm_indexed ? + si_read_indexed_register(adev, se_num, + sh_num, reg_offset) : + RREG32(reg_offset); + return 0; + } + return -EINVAL; +} + +static bool si_read_disabled_bios(struct amdgpu_device *adev) +{ + u32 bus_cntl; + u32 d1vga_control = 0; + u32 d2vga_control = 0; + u32 vga_render_control = 0; + u32 rom_cntl; + bool r; + + bus_cntl = RREG32(R600_BUS_CNTL); + if (adev->mode_info.num_crtc) { + d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); + d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); + vga_render_control = RREG32(VGA_RENDER_CONTROL); + } + rom_cntl = RREG32(R600_ROM_CNTL); + + /* enable the rom */ + WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + if (adev->mode_info.num_crtc) { + /* Disable VGA mode */ + WREG32(AVIVO_D1VGA_CONTROL, + (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(AVIVO_D2VGA_CONTROL, + (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | + AVIVO_DVGA_CONTROL_TIMING_SELECT))); + WREG32(VGA_RENDER_CONTROL, + (vga_render_control & C_000300_VGA_VSTATUS_CNTL)); + } + WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); + + r = amdgpu_read_bios(adev); + + /* restore regs */ + WREG32(R600_BUS_CNTL, bus_cntl); + if (adev->mode_info.num_crtc) { + WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); + WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); + WREG32(VGA_RENDER_CONTROL, vga_render_control); + } + WREG32(R600_ROM_CNTL, rom_cntl); + return r; +} + +//xxx: not implemented +static int si_asic_reset(struct amdgpu_device *adev) +{ + return 0; +} + +static void si_vga_set_state(struct amdgpu_device *adev, bool state) +{ + uint32_t temp; + + temp = RREG32(CONFIG_CNTL); + if (state == false) { + temp &= ~(1<<0); + temp |= (1<<1); + } else { + temp &= ~(1<<1); + } + WREG32(CONFIG_CNTL, temp); +} + +static u32 si_get_xclk(struct amdgpu_device *adev) +{ + u32 reference_clock = adev->clock.spll.reference_freq; + u32 tmp; + + tmp = RREG32(CG_CLKPIN_CNTL_2); + if (tmp & MUX_TCLK_TO_XCLK) + return TCLK; + + tmp = RREG32(CG_CLKPIN_CNTL); + if (tmp & XTALIN_DIVIDE) + return reference_clock / 4; + + return reference_clock; +} +//xxx:not implemented +static int si_set_uvd_clocks(struct amdgpu_device *adev, u32 vclk, u32 dclk) +{ + return 0; +} + +static const struct amdgpu_asic_funcs si_asic_funcs = +{ + .read_disabled_bios = &si_read_disabled_bios, + .read_register = &si_read_register, + .reset = &si_asic_reset, + .set_vga_state = &si_vga_set_state, + .get_xclk = &si_get_xclk, + .set_uvd_clocks = &si_set_uvd_clocks, + .set_vce_clocks = NULL, + .get_virtual_caps = &si_get_virtual_caps, +}; + +static uint32_t si_get_rev_id(struct amdgpu_device *adev) +{ + return (RREG32(CC_DRM_ID_STRAPS) & CC_DRM_ID_STRAPS__ATI_REV_ID_MASK) + >> CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT; +} + +static int si_common_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + adev->smc_rreg = &si_smc_rreg; + adev->smc_wreg = &si_smc_wreg; + adev->pcie_rreg = &si_pcie_rreg; + adev->pcie_wreg = &si_pcie_wreg; + adev->uvd_ctx_rreg = NULL; + adev->uvd_ctx_wreg = NULL; + adev->didt_rreg = NULL; + adev->didt_wreg = NULL; + + adev->asic_funcs = &si_asic_funcs; + + adev->rev_id = si_get_rev_id(adev); + adev->external_rev_id = 0xFF; + switch (adev->asic_type) { + case CHIP_TAHITI: + adev->cg_flags = + AMD_CG_SUPPORT_GFX_MGCG | + AMD_CG_SUPPORT_GFX_MGLS | + /*AMD_CG_SUPPORT_GFX_CGCG |*/ + AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_GFX_CGTS | + AMD_CG_SUPPORT_GFX_CP_LS | + AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_SDMA_MGCG | + AMD_CG_SUPPORT_BIF_LS | + AMD_CG_SUPPORT_VCE_MGCG | + AMD_CG_SUPPORT_UVD_MGCG | + AMD_CG_SUPPORT_HDP_LS | + AMD_CG_SUPPORT_HDP_MGCG; + adev->pg_flags = 0; + break; + case CHIP_PITCAIRN: + adev->cg_flags = + AMD_CG_SUPPORT_GFX_MGCG | + AMD_CG_SUPPORT_GFX_MGLS | + /*AMD_CG_SUPPORT_GFX_CGCG |*/ + AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_GFX_CGTS | + AMD_CG_SUPPORT_GFX_CP_LS | + AMD_CG_SUPPORT_GFX_RLC_LS | + AMD_CG_SUPPORT_MC_LS | + AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_SDMA_MGCG | + AMD_CG_SUPPORT_BIF_LS | + AMD_CG_SUPPORT_VCE_MGCG | + AMD_CG_SUPPORT_UVD_MGCG | + AMD_CG_SUPPORT_HDP_LS | + AMD_CG_SUPPORT_HDP_MGCG; + adev->pg_flags = 0; + break; + + case CHIP_VERDE: + adev->cg_flags = + AMD_CG_SUPPORT_GFX_MGCG | + AMD_CG_SUPPORT_GFX_MGLS | + AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_GFX_CGTS | + AMD_CG_SUPPORT_GFX_CGTS_LS | + AMD_CG_SUPPORT_GFX_CP_LS | + AMD_CG_SUPPORT_MC_LS | + AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_SDMA_MGCG | + AMD_CG_SUPPORT_SDMA_LS | + AMD_CG_SUPPORT_BIF_LS | + AMD_CG_SUPPORT_VCE_MGCG | + AMD_CG_SUPPORT_UVD_MGCG | + AMD_CG_SUPPORT_HDP_LS | + AMD_CG_SUPPORT_HDP_MGCG; + adev->pg_flags = 0; + //??? + adev->external_rev_id = adev->rev_id + 0x14; + break; + case CHIP_OLAND: + adev->cg_flags = + AMD_CG_SUPPORT_GFX_MGCG | + AMD_CG_SUPPORT_GFX_MGLS | + /*AMD_CG_SUPPORT_GFX_CGCG |*/ + AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_GFX_CGTS | + AMD_CG_SUPPORT_GFX_CP_LS | + AMD_CG_SUPPORT_GFX_RLC_LS | + AMD_CG_SUPPORT_MC_LS | + AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_SDMA_MGCG | + AMD_CG_SUPPORT_BIF_LS | + AMD_CG_SUPPORT_UVD_MGCG | + AMD_CG_SUPPORT_HDP_LS | + AMD_CG_SUPPORT_HDP_MGCG; + adev->pg_flags = 0; + break; + case CHIP_HAINAN: + adev->cg_flags = + AMD_CG_SUPPORT_GFX_MGCG | + AMD_CG_SUPPORT_GFX_MGLS | + /*AMD_CG_SUPPORT_GFX_CGCG |*/ + AMD_CG_SUPPORT_GFX_CGLS | + AMD_CG_SUPPORT_GFX_CGTS | + AMD_CG_SUPPORT_GFX_CP_LS | + AMD_CG_SUPPORT_GFX_RLC_LS | + AMD_CG_SUPPORT_MC_LS | + AMD_CG_SUPPORT_MC_MGCG | + AMD_CG_SUPPORT_SDMA_MGCG | + AMD_CG_SUPPORT_BIF_LS | + AMD_CG_SUPPORT_HDP_LS | + AMD_CG_SUPPORT_HDP_MGCG; + adev->pg_flags = 0; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int si_common_sw_init(void *handle) +{ + return 0; +} + +static int si_common_sw_fini(void *handle) +{ + return 0; +} + + +static void si_init_golden_registers(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_TAHITI: + amdgpu_program_register_sequence(adev, + tahiti_golden_registers, + (const u32)ARRAY_SIZE(tahiti_golden_registers)); + amdgpu_program_register_sequence(adev, + tahiti_golden_rlc_registers, + (const u32)ARRAY_SIZE(tahiti_golden_rlc_registers)); + amdgpu_program_register_sequence(adev, + tahiti_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(tahiti_mgcg_cgcg_init)); + amdgpu_program_register_sequence(adev, + tahiti_golden_registers2, + (const u32)ARRAY_SIZE(tahiti_golden_registers2)); + break; + case CHIP_PITCAIRN: + amdgpu_program_register_sequence(adev, + pitcairn_golden_registers, + (const u32)ARRAY_SIZE(pitcairn_golden_registers)); + amdgpu_program_register_sequence(adev, + pitcairn_golden_rlc_registers, + (const u32)ARRAY_SIZE(pitcairn_golden_rlc_registers)); + amdgpu_program_register_sequence(adev, + pitcairn_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(pitcairn_mgcg_cgcg_init)); + case CHIP_VERDE: + amdgpu_program_register_sequence(adev, + verde_golden_registers, + (const u32)ARRAY_SIZE(verde_golden_registers)); + amdgpu_program_register_sequence(adev, + verde_golden_rlc_registers, + (const u32)ARRAY_SIZE(verde_golden_rlc_registers)); + amdgpu_program_register_sequence(adev, + verde_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(verde_mgcg_cgcg_init)); + amdgpu_program_register_sequence(adev, + verde_pg_init, + (const u32)ARRAY_SIZE(verde_pg_init)); + break; + case CHIP_OLAND: + amdgpu_program_register_sequence(adev, + oland_golden_registers, + (const u32)ARRAY_SIZE(oland_golden_registers)); + amdgpu_program_register_sequence(adev, + oland_golden_rlc_registers, + (const u32)ARRAY_SIZE(oland_golden_rlc_registers)); + amdgpu_program_register_sequence(adev, + oland_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(oland_mgcg_cgcg_init)); + case CHIP_HAINAN: + amdgpu_program_register_sequence(adev, + hainan_golden_registers, + (const u32)ARRAY_SIZE(hainan_golden_registers)); + amdgpu_program_register_sequence(adev, + hainan_golden_registers2, + (const u32)ARRAY_SIZE(hainan_golden_registers2)); + amdgpu_program_register_sequence(adev, + hainan_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(hainan_mgcg_cgcg_init)); + break; + + + default: + BUG(); + } +} + +u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); + (void)RREG32(PCIE_PORT_INDEX); + r = RREG32(PCIE_PORT_DATA); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + return r; +} + +void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); + (void)RREG32(PCIE_PORT_INDEX); + WREG32(PCIE_PORT_DATA, (v)); + (void)RREG32(PCIE_PORT_DATA); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} + +static void si_pcie_gen3_enable(struct amdgpu_device *adev) +{ + struct pci_dev *root = adev->pdev->bus->self; + int bridge_pos, gpu_pos; + u32 speed_cntl, mask, current_data_rate; + int ret, i; + u16 tmp16; + + if (pci_is_root_bus(adev->pdev->bus)) + return; + + if (amdgpu_pcie_gen2 == 0) + return; + + if (adev->flags & AMD_IS_APU) + return; + + ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); + if (ret != 0) + return; + + if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) + return; + + speed_cntl = si_pciep_rreg(adev,PCIE_LC_SPEED_CNTL); + current_data_rate = (speed_cntl & LC_CURRENT_DATA_RATE_MASK) >> + LC_CURRENT_DATA_RATE_SHIFT; + if (mask & DRM_PCIE_SPEED_80) { + if (current_data_rate == 2) { + DRM_INFO("PCIE gen 3 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 3 link speeds, disable with amdgpu.pcie_gen2=0\n"); + } else if (mask & DRM_PCIE_SPEED_50) { + if (current_data_rate == 1) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 2 link speeds, disable with amdgpu.pcie_gen2=0\n"); + } + + bridge_pos = pci_pcie_cap(root); + if (!bridge_pos) + return; + + gpu_pos = pci_pcie_cap(adev->pdev); + if (!gpu_pos) + return; + + if (mask & DRM_PCIE_SPEED_80) { + if (current_data_rate != 2) { + u16 bridge_cfg, gpu_cfg; + u16 bridge_cfg2, gpu_cfg2; + u32 max_lw, current_lw, tmp; + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg); + pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg); + + tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD; + pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16); + + tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD; + pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16); + + tmp = RREG32_PCIE(PCIE_LC_STATUS1); + max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT; + current_lw = (tmp & LC_OPERATING_LINK_WIDTH_MASK) >> LC_OPERATING_LINK_WIDTH_SHIFT; + + if (current_lw < max_lw) { + tmp = si_pciep_rreg(adev, PCIE_LC_LINK_WIDTH_CNTL); + if (tmp & LC_RENEGOTIATION_SUPPORT) { + tmp &= ~(LC_LINK_WIDTH_MASK | LC_UPCONFIGURE_DIS); + tmp |= (max_lw << LC_LINK_WIDTH_SHIFT); + tmp |= LC_UPCONFIGURE_SUPPORT | LC_RENEGOTIATE_EN | LC_RECONFIG_NOW; + si_pciep_wreg(adev, PCIE_LC_LINK_WIDTH_CNTL, tmp); + } + } + + for (i = 0; i < 10; i++) { + pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_DEVSTA, &tmp16); + if (tmp16 & PCI_EXP_DEVSTA_TRPND) + break; + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg); + pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg); + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &bridge_cfg2); + pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &gpu_cfg2); + + tmp = si_pciep_rreg(adev, PCIE_LC_CNTL4); + tmp |= LC_SET_QUIESCE; + si_pciep_wreg(adev,PCIE_LC_CNTL4, tmp); + + tmp = si_pciep_rreg(adev, PCIE_LC_CNTL4); + tmp |= LC_REDO_EQ; + si_pciep_wreg(adev, PCIE_LC_CNTL4, tmp); + + mdelay(100); + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &tmp16); + tmp16 &= ~PCI_EXP_LNKCTL_HAWD; + tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD); + pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16); + + pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &tmp16); + tmp16 &= ~PCI_EXP_LNKCTL_HAWD; + tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD); + pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16); + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &tmp16); + tmp16 &= ~((1 << 4) | (7 << 9)); + tmp16 |= (bridge_cfg2 & ((1 << 4) | (7 << 9))); + pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, tmp16); + + pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16); + tmp16 &= ~((1 << 4) | (7 << 9)); + tmp16 |= (gpu_cfg2 & ((1 << 4) | (7 << 9))); + pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16); + + tmp = si_pciep_rreg(adev, PCIE_LC_CNTL4); + tmp &= ~LC_SET_QUIESCE; + si_pciep_wreg(adev, PCIE_LC_CNTL4, tmp); + } + } + } + + speed_cntl |= LC_FORCE_EN_SW_SPEED_CHANGE | LC_FORCE_DIS_HW_SPEED_CHANGE; + speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE; + si_pciep_wreg(adev, PCIE_LC_SPEED_CNTL, speed_cntl); + + pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16); + tmp16 &= ~0xf; + if (mask & DRM_PCIE_SPEED_80) + tmp16 |= 3; + else if (mask & DRM_PCIE_SPEED_50) + tmp16 |= 2; + else + tmp16 |= 1; + pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16); + + speed_cntl = si_pciep_rreg(adev, PCIE_LC_SPEED_CNTL); + speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE; + si_pciep_wreg(adev, PCIE_LC_SPEED_CNTL, speed_cntl); + + for (i = 0; i < adev->usec_timeout; i++) { + speed_cntl = si_pciep_rreg(adev, PCIE_LC_SPEED_CNTL); + if ((speed_cntl & LC_INITIATE_LINK_SPEED_CHANGE) == 0) + break; + udelay(1); + } +} + +static inline u32 si_pif_phy0_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); + r = RREG32(EVERGREEN_PIF_PHY0_DATA); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + return r; +} + +static inline void si_pif_phy0_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); + WREG32(EVERGREEN_PIF_PHY0_DATA, (v)); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} + +static inline u32 si_pif_phy1_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); + r = RREG32(EVERGREEN_PIF_PHY1_DATA); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + return r; +} + +static inline void si_pif_phy1_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); + WREG32(EVERGREEN_PIF_PHY1_DATA, (v)); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} +static void si_program_aspm(struct amdgpu_device *adev) +{ + u32 data, orig; + bool disable_l0s = false, disable_l1 = false, disable_plloff_in_l1 = false; + bool disable_clkreq = false; + + if (amdgpu_aspm == 0) + return; + + if (adev->flags & AMD_IS_APU) + return; + orig = data = si_pciep_rreg(adev, PCIE_LC_N_FTS_CNTL); + data &= ~LC_XMIT_N_FTS_MASK; + data |= LC_XMIT_N_FTS(0x24) | LC_XMIT_N_FTS_OVERRIDE_EN; + if (orig != data) + si_pciep_wreg(adev, PCIE_LC_N_FTS_CNTL, data); + + orig = data = si_pciep_rreg(adev, PCIE_LC_CNTL3); + data |= LC_GO_TO_RECOVERY; + if (orig != data) + si_pciep_wreg(adev, PCIE_LC_CNTL3, data); + + orig = data = RREG32_PCIE(PCIE_P_CNTL); + data |= P_IGNORE_EDB_ERR; + if (orig != data) + WREG32_PCIE(PCIE_P_CNTL, data); + + orig = data = si_pciep_rreg(adev, PCIE_LC_CNTL); + data &= ~(LC_L0S_INACTIVITY_MASK | LC_L1_INACTIVITY_MASK); + data |= LC_PMI_TO_L1_DIS; + if (!disable_l0s) + data |= LC_L0S_INACTIVITY(7); + + if (!disable_l1) { + data |= LC_L1_INACTIVITY(7); + data &= ~LC_PMI_TO_L1_DIS; + if (orig != data) + si_pciep_wreg(adev, PCIE_LC_CNTL, data); + + if (!disable_plloff_in_l1) { + bool clk_req_support; + + orig = data = si_pif_phy0_rreg(adev,PB0_PIF_PWRDOWN_0); + data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK); + data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7); + if (orig != data) + si_pif_phy0_wreg(adev,PB0_PIF_PWRDOWN_0, data); + + orig = data = si_pif_phy0_rreg(adev,PB0_PIF_PWRDOWN_1); + data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK); + data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7); + if (orig != data) + si_pif_phy0_wreg(adev,PB0_PIF_PWRDOWN_1, data); + + orig = data = si_pif_phy1_rreg(adev,PB1_PIF_PWRDOWN_0); + data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK); + data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7); + if (orig != data) + si_pif_phy1_wreg(adev,PB1_PIF_PWRDOWN_0, data); + + orig = data = si_pif_phy1_rreg(adev,PB1_PIF_PWRDOWN_1); + data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK); + data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7); + if (orig != data) + si_pif_phy1_wreg(adev,PB1_PIF_PWRDOWN_1, data); + + if ((adev->family != CHIP_OLAND) && (adev->family != CHIP_HAINAN)) { + orig = data = si_pif_phy0_rreg(adev,PB0_PIF_PWRDOWN_0); + data &= ~PLL_RAMP_UP_TIME_0_MASK; + if (orig != data) + si_pif_phy0_wreg(adev,PB0_PIF_PWRDOWN_0, data); + + orig = data = si_pif_phy0_rreg(adev,PB0_PIF_PWRDOWN_1); + data &= ~PLL_RAMP_UP_TIME_1_MASK; + if (orig != data) + si_pif_phy0_wreg(adev,PB0_PIF_PWRDOWN_1, data); + + orig = data = si_pif_phy0_rreg(adev,PB0_PIF_PWRDOWN_2); + data &= ~PLL_RAMP_UP_TIME_2_MASK; + if (orig != data) + si_pif_phy0_wreg(adev,PB0_PIF_PWRDOWN_2, data); + + orig = data = si_pif_phy0_rreg(adev,PB0_PIF_PWRDOWN_3); + data &= ~PLL_RAMP_UP_TIME_3_MASK; + if (orig != data) + si_pif_phy0_wreg(adev,PB0_PIF_PWRDOWN_3, data); + + orig = data = si_pif_phy1_rreg(adev,PB1_PIF_PWRDOWN_0); + data &= ~PLL_RAMP_UP_TIME_0_MASK; + if (orig != data) + si_pif_phy1_wreg(adev,PB1_PIF_PWRDOWN_0, data); + + orig = data = si_pif_phy1_rreg(adev,PB1_PIF_PWRDOWN_1); + data &= ~PLL_RAMP_UP_TIME_1_MASK; + if (orig != data) + si_pif_phy1_wreg(adev,PB1_PIF_PWRDOWN_1, data); + + orig = data = si_pif_phy1_rreg(adev,PB1_PIF_PWRDOWN_2); + data &= ~PLL_RAMP_UP_TIME_2_MASK; + if (orig != data) + si_pif_phy1_wreg(adev,PB1_PIF_PWRDOWN_2, data); + + orig = data = si_pif_phy1_rreg(adev,PB1_PIF_PWRDOWN_3); + data &= ~PLL_RAMP_UP_TIME_3_MASK; + if (orig != data) + si_pif_phy1_wreg(adev,PB1_PIF_PWRDOWN_3, data); + } + orig = data = si_pciep_rreg(adev, PCIE_LC_LINK_WIDTH_CNTL); + data &= ~LC_DYN_LANES_PWR_STATE_MASK; + data |= LC_DYN_LANES_PWR_STATE(3); + if (orig != data) + si_pciep_wreg(adev, PCIE_LC_LINK_WIDTH_CNTL, data); + + orig = data = si_pif_phy0_rreg(adev,PB0_PIF_CNTL); + data &= ~LS2_EXIT_TIME_MASK; + if ((adev->family == CHIP_OLAND) || (adev->family == CHIP_HAINAN)) + data |= LS2_EXIT_TIME(5); + if (orig != data) + si_pif_phy0_wreg(adev,PB0_PIF_CNTL, data); + + orig = data = si_pif_phy1_rreg(adev,PB1_PIF_CNTL); + data &= ~LS2_EXIT_TIME_MASK; + if ((adev->family == CHIP_OLAND) || (adev->family == CHIP_HAINAN)) + data |= LS2_EXIT_TIME(5); + if (orig != data) + si_pif_phy1_wreg(adev,PB1_PIF_CNTL, data); + + if (!disable_clkreq && + !pci_is_root_bus(adev->pdev->bus)) { + struct pci_dev *root = adev->pdev->bus->self; + u32 lnkcap; + + clk_req_support = false; + pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap); + if (lnkcap & PCI_EXP_LNKCAP_CLKPM) + clk_req_support = true; + } else { + clk_req_support = false; + } + + if (clk_req_support) { + orig = data = si_pciep_rreg(adev, PCIE_LC_CNTL2); + data |= LC_ALLOW_PDWN_IN_L1 | LC_ALLOW_PDWN_IN_L23; + if (orig != data) + si_pciep_wreg(adev, PCIE_LC_CNTL2, data); + + orig = data = RREG32(THM_CLK_CNTL); + data &= ~(CMON_CLK_SEL_MASK | TMON_CLK_SEL_MASK); + data |= CMON_CLK_SEL(1) | TMON_CLK_SEL(1); + if (orig != data) + WREG32(THM_CLK_CNTL, data); + + orig = data = RREG32(MISC_CLK_CNTL); + data &= ~(DEEP_SLEEP_CLK_SEL_MASK | ZCLK_SEL_MASK); + data |= DEEP_SLEEP_CLK_SEL(1) | ZCLK_SEL(1); + if (orig != data) + WREG32(MISC_CLK_CNTL, data); + + orig = data = RREG32(CG_CLKPIN_CNTL); + data &= ~BCLK_AS_XCLK; + if (orig != data) + WREG32(CG_CLKPIN_CNTL, data); + + orig = data = RREG32(CG_CLKPIN_CNTL_2); + data &= ~FORCE_BIF_REFCLK_EN; + if (orig != data) + WREG32(CG_CLKPIN_CNTL_2, data); + + orig = data = RREG32(MPLL_BYPASSCLK_SEL); + data &= ~MPLL_CLKOUT_SEL_MASK; + data |= MPLL_CLKOUT_SEL(4); + if (orig != data) + WREG32(MPLL_BYPASSCLK_SEL, data); + + orig = data = RREG32(SPLL_CNTL_MODE); + data &= ~SPLL_REFCLK_SEL_MASK; + if (orig != data) + WREG32(SPLL_CNTL_MODE, data); + } + } + } else { + if (orig != data) + si_pciep_wreg(adev, PCIE_LC_CNTL, data); + } + + orig = data = RREG32_PCIE(PCIE_CNTL2); + data |= SLV_MEM_LS_EN | MST_MEM_LS_EN | REPLAY_MEM_LS_EN; + if (orig != data) + WREG32_PCIE(PCIE_CNTL2, data); + + if (!disable_l0s) { + data = si_pciep_rreg(adev, PCIE_LC_N_FTS_CNTL); + if((data & LC_N_FTS_MASK) == LC_N_FTS_MASK) { + data = RREG32_PCIE(PCIE_LC_STATUS1); + if ((data & LC_REVERSE_XMIT) && (data & LC_REVERSE_RCVR)) { + orig = data = si_pciep_rreg(adev, PCIE_LC_CNTL); + data &= ~LC_L0S_INACTIVITY_MASK; + if (orig != data) + si_pciep_wreg(adev, PCIE_LC_CNTL, data); + } + } + } +} + +static void si_fix_pci_max_read_req_size(struct amdgpu_device *adev) +{ + int readrq; + u16 v; + + readrq = pcie_get_readrq(adev->pdev); + v = ffs(readrq) - 8; + if ((v == 0) || (v == 6) || (v == 7)) + pcie_set_readrq(adev->pdev, 512); +} + +static int si_common_hw_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + si_fix_pci_max_read_req_size(adev); + si_init_golden_registers(adev); + si_pcie_gen3_enable(adev); + si_program_aspm(adev); + + return 0; +} + +static int si_common_hw_fini(void *handle) +{ + return 0; +} + +static int si_common_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return si_common_hw_fini(adev); +} + +static int si_common_resume(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + return si_common_hw_init(adev); +} + +static bool si_common_is_idle(void *handle) +{ + return true; +} + +static int si_common_wait_for_idle(void *handle) +{ + return 0; +} + +static int si_common_soft_reset(void *handle) +{ + return 0; +} + +static int si_common_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int si_common_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +const struct amd_ip_funcs si_common_ip_funcs = { + .name = "si_common", + .early_init = si_common_early_init, + .late_init = NULL, + .sw_init = si_common_sw_init, + .sw_fini = si_common_sw_fini, + .hw_init = si_common_hw_init, + .hw_fini = si_common_hw_fini, + .suspend = si_common_suspend, + .resume = si_common_resume, + .is_idle = si_common_is_idle, + .wait_for_idle = si_common_wait_for_idle, + .soft_reset = si_common_soft_reset, + .set_clockgating_state = si_common_set_clockgating_state, + .set_powergating_state = si_common_set_powergating_state, +}; + +static const struct amdgpu_ip_block_version verde_ip_blocks[] = +{ + { + .type = AMD_IP_BLOCK_TYPE_COMMON, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_common_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gmc_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_ih_ip_funcs, + }, +/* { + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &si_null_ip_funcs, + }, + */ + { + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &dce_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gfx_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_dma_ip_funcs, + }, +/* { + .type = AMD_IP_BLOCK_TYPE_UVD, + .major = 3, + .minor = 1, + .rev = 0, + .funcs = &si_null_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_VCE, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_null_ip_funcs, + }, + */ +}; + + +static const struct amdgpu_ip_block_version hainan_ip_blocks[] = +{ + { + .type = AMD_IP_BLOCK_TYPE_COMMON, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_common_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_GMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gmc_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_IH, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_ih_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &si_null_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_GFX, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &gfx_v6_0_ip_funcs, + }, + { + .type = AMD_IP_BLOCK_TYPE_SDMA, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &si_dma_ip_funcs, + }, +}; + +int si_set_ip_blocks(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_VERDE: + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_OLAND: + adev->ip_blocks = verde_ip_blocks; + adev->num_ip_blocks = ARRAY_SIZE(verde_ip_blocks); + break; + case CHIP_HAINAN: + adev->ip_blocks = hainan_ip_blocks; + adev->num_ip_blocks = ARRAY_SIZE(hainan_ip_blocks); + break; + default: + BUG(); + } + return 0; +} + diff --git a/drivers/gpu/drm/amd/amdgpu/si.h b/drivers/gpu/drm/amd/amdgpu/si.h new file mode 100644 index 0000000..959d7b6 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si.h @@ -0,0 +1,33 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __SI_H__ +#define __SI_H__ + +extern const struct amd_ip_funcs si_common_ip_funcs; + +void si_srbm_select(struct amdgpu_device *adev, + u32 me, u32 pipe, u32 queue, u32 vmid); +int si_set_ip_blocks(struct amdgpu_device *adev); + +#endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/si/sid.h b/drivers/gpu/drm/amd/include/asic_reg/si/sid.h index f30e57d..8c5608a 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/si/sid.h +++ b/drivers/gpu/drm/amd/include/asic_reg/si/sid.h @@ -1221,6 +1221,37 @@ # define ADDR_SURF_4_BANK 1 # define ADDR_SURF_8_BANK 2 # define ADDR_SURF_16_BANK 3 +#define GB_TILE_MODE1 0x2645 +#define GB_TILE_MODE2 0x2646 +#define GB_TILE_MODE3 0x2647 +#define GB_TILE_MODE4 0x2648 +#define GB_TILE_MODE5 0x2649 +#define GB_TILE_MODE6 0x264a +#define GB_TILE_MODE7 0x264b +#define GB_TILE_MODE8 0x264c +#define GB_TILE_MODE9 0x264d +#define GB_TILE_MODE10 0x264e +#define GB_TILE_MODE11 0x264f +#define GB_TILE_MODE12 0x2650 +#define GB_TILE_MODE13 0x2651 +#define GB_TILE_MODE14 0x2652 +#define GB_TILE_MODE15 0x2653 +#define GB_TILE_MODE16 0x2654 +#define GB_TILE_MODE17 0x2655 +#define GB_TILE_MODE18 0x2656 +#define GB_TILE_MODE19 0x2657 +#define GB_TILE_MODE20 0x2658 +#define GB_TILE_MODE21 0x2659 +#define GB_TILE_MODE22 0x265a +#define GB_TILE_MODE23 0x265b +#define GB_TILE_MODE24 0x265c +#define GB_TILE_MODE25 0x265d +#define GB_TILE_MODE26 0x265e +#define GB_TILE_MODE27 0x265f +#define GB_TILE_MODE28 0x2660 +#define GB_TILE_MODE29 0x2661 +#define GB_TILE_MODE30 0x2662 +#define GB_TILE_MODE31 0x2663 #define CB_PERFCOUNTER0_SELECT0 0x2688 #define CB_PERFCOUNTER0_SELECT1 0x2689 @@ -2017,8 +2048,22 @@ #define R600_D1GRPH_SWAP_ENDIAN_64BIT (3 << 0) #define AVIVO_D1VGA_CONTROL 0x00cc +# define AVIVO_DVGA_CONTROL_MODE_ENABLE (1 << 0) +# define AVIVO_DVGA_CONTROL_TIMING_SELECT (1 << 8) +# define AVIVO_DVGA_CONTROL_SYNC_POLARITY_SELECT (1 << 9) +# define AVIVO_DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1 << 10) +# define AVIVO_DVGA_CONTROL_OVERSCAN_COLOR_EN (1 << 16) +# define AVIVO_DVGA_CONTROL_ROTATE (1 << 24) #define AVIVO_D2VGA_CONTROL 0x00ce +#define R600_BUS_CNTL 0x1508 +# define R600_BIOS_ROM_DIS (1 << 1) + +#define R600_ROM_CNTL 0x580 +# define R600_SCK_OVERWRITE (1 << 1) +# define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28 +# define R600_SCK_PRESCALE_CRYSTAL_CLK_MASK (0xf << 28) + #define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK 0x1 #define FMT_BIT_DEPTH_CONTROL 0x1bf2 -- cgit v1.1 From 36b9a952bbf6881eef9e0f1920d6ce354c195553 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 31 Aug 2016 13:23:25 +0800 Subject: drm/amdgpu: introduce pcie port read/write entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds pcie port read/write entry, because it will be also used on si dpm part. Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 + drivers/gpu/drm/amd/amdgpu/si.c | 106 +++++++++++++++-------------- 3 files changed, 60 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 1d29e12..1902f9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2000,6 +2000,8 @@ struct amdgpu_device { spinlock_t pcie_idx_lock; amdgpu_rreg_t pcie_rreg; amdgpu_wreg_t pcie_wreg; + amdgpu_rreg_t pciep_rreg; + amdgpu_wreg_t pciep_wreg; /* protects concurrent UVD register access */ spinlock_t uvd_ctx_idx_lock; amdgpu_rreg_t uvd_ctx_rreg; @@ -2148,6 +2150,8 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v); #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) #define RREG32_PCIE(reg) adev->pcie_rreg(adev, (reg)) #define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v)) +#define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg)) +#define WREG32_PCIE_PORT(reg, v) adev->pciep_wreg(adev, (reg), (v)) #define RREG32_SMC(reg) adev->smc_rreg(adev, (reg)) #define WREG32_SMC(reg, v) adev->smc_wreg(adev, (reg), (v)) #define RREG32_UVD_CTX(reg) adev->uvd_ctx_rreg(adev, (reg)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 71fe5c1..27bfee2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1514,6 +1514,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->smc_wreg = &amdgpu_invalid_wreg; adev->pcie_rreg = &amdgpu_invalid_rreg; adev->pcie_wreg = &amdgpu_invalid_wreg; + adev->pciep_rreg = &amdgpu_invalid_rreg; + adev->pciep_wreg = &amdgpu_invalid_wreg; adev->uvd_ctx_rreg = &amdgpu_invalid_rreg; adev->uvd_ctx_wreg = &amdgpu_invalid_wreg; adev->didt_rreg = &amdgpu_invalid_rreg; diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 74dbfca..c905470 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -905,6 +905,31 @@ static void si_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); } +u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); + (void)RREG32(PCIE_PORT_INDEX); + r = RREG32(PCIE_PORT_DATA); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + return r; +} + +void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); + (void)RREG32(PCIE_PORT_INDEX); + WREG32(PCIE_PORT_DATA, (v)); + (void)RREG32(PCIE_PORT_DATA); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} + static u32 si_smc_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags; @@ -1124,6 +1149,8 @@ static int si_common_early_init(void *handle) adev->smc_wreg = &si_smc_wreg; adev->pcie_rreg = &si_pcie_rreg; adev->pcie_wreg = &si_pcie_wreg; + adev->pciep_rreg = &si_pciep_rreg; + adev->pciep_wreg = &si_pciep_wreg; adev->uvd_ctx_rreg = NULL; adev->uvd_ctx_wreg = NULL; adev->didt_rreg = NULL; @@ -1315,31 +1342,6 @@ static void si_init_golden_registers(struct amdgpu_device *adev) } } -u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg) -{ - unsigned long flags; - u32 r; - - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); - (void)RREG32(PCIE_PORT_INDEX); - r = RREG32(PCIE_PORT_DATA); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); - return r; -} - -void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v) -{ - unsigned long flags; - - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); - (void)RREG32(PCIE_PORT_INDEX); - WREG32(PCIE_PORT_DATA, (v)); - (void)RREG32(PCIE_PORT_DATA); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); -} - static void si_pcie_gen3_enable(struct amdgpu_device *adev) { struct pci_dev *root = adev->pdev->bus->self; @@ -1364,7 +1366,7 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) return; - speed_cntl = si_pciep_rreg(adev,PCIE_LC_SPEED_CNTL); + speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); current_data_rate = (speed_cntl & LC_CURRENT_DATA_RATE_MASK) >> LC_CURRENT_DATA_RATE_SHIFT; if (mask & DRM_PCIE_SPEED_80) { @@ -1409,12 +1411,12 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) current_lw = (tmp & LC_OPERATING_LINK_WIDTH_MASK) >> LC_OPERATING_LINK_WIDTH_SHIFT; if (current_lw < max_lw) { - tmp = si_pciep_rreg(adev, PCIE_LC_LINK_WIDTH_CNTL); + tmp = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); if (tmp & LC_RENEGOTIATION_SUPPORT) { tmp &= ~(LC_LINK_WIDTH_MASK | LC_UPCONFIGURE_DIS); tmp |= (max_lw << LC_LINK_WIDTH_SHIFT); tmp |= LC_UPCONFIGURE_SUPPORT | LC_RENEGOTIATE_EN | LC_RECONFIG_NOW; - si_pciep_wreg(adev, PCIE_LC_LINK_WIDTH_CNTL, tmp); + WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, tmp); } } @@ -1429,13 +1431,13 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &bridge_cfg2); pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &gpu_cfg2); - tmp = si_pciep_rreg(adev, PCIE_LC_CNTL4); + tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4); tmp |= LC_SET_QUIESCE; - si_pciep_wreg(adev,PCIE_LC_CNTL4, tmp); + WREG32_PCIE_PORT(PCIE_LC_CNTL4, tmp); - tmp = si_pciep_rreg(adev, PCIE_LC_CNTL4); + tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4); tmp |= LC_REDO_EQ; - si_pciep_wreg(adev, PCIE_LC_CNTL4, tmp); + WREG32_PCIE_PORT(PCIE_LC_CNTL4, tmp); mdelay(100); @@ -1459,16 +1461,16 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) tmp16 |= (gpu_cfg2 & ((1 << 4) | (7 << 9))); pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16); - tmp = si_pciep_rreg(adev, PCIE_LC_CNTL4); + tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4); tmp &= ~LC_SET_QUIESCE; - si_pciep_wreg(adev, PCIE_LC_CNTL4, tmp); + WREG32_PCIE_PORT(PCIE_LC_CNTL4, tmp); } } } speed_cntl |= LC_FORCE_EN_SW_SPEED_CHANGE | LC_FORCE_DIS_HW_SPEED_CHANGE; speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE; - si_pciep_wreg(adev, PCIE_LC_SPEED_CNTL, speed_cntl); + WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16); tmp16 &= ~0xf; @@ -1480,12 +1482,12 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) tmp16 |= 1; pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16); - speed_cntl = si_pciep_rreg(adev, PCIE_LC_SPEED_CNTL); + speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE; - si_pciep_wreg(adev, PCIE_LC_SPEED_CNTL, speed_cntl); + WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); for (i = 0; i < adev->usec_timeout; i++) { - speed_cntl = si_pciep_rreg(adev, PCIE_LC_SPEED_CNTL); + speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); if ((speed_cntl & LC_INITIATE_LINK_SPEED_CHANGE) == 0) break; udelay(1); @@ -1546,23 +1548,23 @@ static void si_program_aspm(struct amdgpu_device *adev) if (adev->flags & AMD_IS_APU) return; - orig = data = si_pciep_rreg(adev, PCIE_LC_N_FTS_CNTL); + orig = data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL); data &= ~LC_XMIT_N_FTS_MASK; data |= LC_XMIT_N_FTS(0x24) | LC_XMIT_N_FTS_OVERRIDE_EN; if (orig != data) - si_pciep_wreg(adev, PCIE_LC_N_FTS_CNTL, data); + WREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL, data); - orig = data = si_pciep_rreg(adev, PCIE_LC_CNTL3); + orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL3); data |= LC_GO_TO_RECOVERY; if (orig != data) - si_pciep_wreg(adev, PCIE_LC_CNTL3, data); + WREG32_PCIE_PORT(PCIE_LC_CNTL3, data); orig = data = RREG32_PCIE(PCIE_P_CNTL); data |= P_IGNORE_EDB_ERR; if (orig != data) WREG32_PCIE(PCIE_P_CNTL, data); - orig = data = si_pciep_rreg(adev, PCIE_LC_CNTL); + orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL); data &= ~(LC_L0S_INACTIVITY_MASK | LC_L1_INACTIVITY_MASK); data |= LC_PMI_TO_L1_DIS; if (!disable_l0s) @@ -1572,7 +1574,7 @@ static void si_program_aspm(struct amdgpu_device *adev) data |= LC_L1_INACTIVITY(7); data &= ~LC_PMI_TO_L1_DIS; if (orig != data) - si_pciep_wreg(adev, PCIE_LC_CNTL, data); + WREG32_PCIE_PORT(PCIE_LC_CNTL, data); if (!disable_plloff_in_l1) { bool clk_req_support; @@ -1642,11 +1644,11 @@ static void si_program_aspm(struct amdgpu_device *adev) if (orig != data) si_pif_phy1_wreg(adev,PB1_PIF_PWRDOWN_3, data); } - orig = data = si_pciep_rreg(adev, PCIE_LC_LINK_WIDTH_CNTL); + orig = data = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); data &= ~LC_DYN_LANES_PWR_STATE_MASK; data |= LC_DYN_LANES_PWR_STATE(3); if (orig != data) - si_pciep_wreg(adev, PCIE_LC_LINK_WIDTH_CNTL, data); + WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data); orig = data = si_pif_phy0_rreg(adev,PB0_PIF_CNTL); data &= ~LS2_EXIT_TIME_MASK; @@ -1676,10 +1678,10 @@ static void si_program_aspm(struct amdgpu_device *adev) } if (clk_req_support) { - orig = data = si_pciep_rreg(adev, PCIE_LC_CNTL2); + orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL2); data |= LC_ALLOW_PDWN_IN_L1 | LC_ALLOW_PDWN_IN_L23; if (orig != data) - si_pciep_wreg(adev, PCIE_LC_CNTL2, data); + WREG32_PCIE_PORT(PCIE_LC_CNTL2, data); orig = data = RREG32(THM_CLK_CNTL); data &= ~(CMON_CLK_SEL_MASK | TMON_CLK_SEL_MASK); @@ -1717,7 +1719,7 @@ static void si_program_aspm(struct amdgpu_device *adev) } } else { if (orig != data) - si_pciep_wreg(adev, PCIE_LC_CNTL, data); + WREG32_PCIE_PORT(PCIE_LC_CNTL, data); } orig = data = RREG32_PCIE(PCIE_CNTL2); @@ -1726,14 +1728,14 @@ static void si_program_aspm(struct amdgpu_device *adev) WREG32_PCIE(PCIE_CNTL2, data); if (!disable_l0s) { - data = si_pciep_rreg(adev, PCIE_LC_N_FTS_CNTL); + data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL); if((data & LC_N_FTS_MASK) == LC_N_FTS_MASK) { data = RREG32_PCIE(PCIE_LC_STATUS1); if ((data & LC_REVERSE_XMIT) && (data & LC_REVERSE_RCVR)) { - orig = data = si_pciep_rreg(adev, PCIE_LC_CNTL); + orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL); data &= ~LC_L0S_INACTIVITY_MASK; if (orig != data) - si_pciep_wreg(adev, PCIE_LC_CNTL, data); + WREG32_PCIE_PORT(PCIE_LC_CNTL, data); } } } -- cgit v1.1 From a036db18c61d9a8ae6619cbb3dca8b1f2df68103 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 19 Jan 2016 14:19:53 +0800 Subject: drm/amdgpu: add all the components for si into Makefile/kconfig v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Kconfig | 7 +++++++ drivers/gpu/drm/amd/amdgpu/Makefile | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index f3cb69d..53cf397 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig @@ -1,3 +1,10 @@ +config DRM_AMDGPU_SI + bool "Enable amdgpu support for SI parts" + depends on DRM_AMDGPU + help + Choose this option if you want to enable experimental support + for SI asics. + config DRM_AMDGPU_CIK bool "Enable amdgpu support for CIK parts" depends on DRM_AMDGPU diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 21dd7c0..5ebea9d 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -30,6 +30,8 @@ amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \ amdgpu_amdkfd_gfx_v7.o +amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o + amdgpu-y += \ vi.o -- cgit v1.1 From 33f34802686c8bcfd236e085208ea6338d220251 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 21 Jan 2016 17:29:41 +0800 Subject: drm/amdgpu: add si ip blocks setup v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 27bfee2..abea6f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -41,6 +41,9 @@ #include "atom.h" #include "amdgpu_atombios.h" #include "amd_pcie.h" +#ifdef CONFIG_DRM_AMDGPU_SI +#include "si.h" +#endif #ifdef CONFIG_DRM_AMDGPU_CIK #include "cik.h" #endif @@ -1231,6 +1234,17 @@ static int amdgpu_early_init(struct amdgpu_device *adev) if (r) return r; break; +#ifdef CONFIG_DRM_AMDGPU_SI + case CHIP_VERDE: + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_OLAND: + case CHIP_HAINAN: + r = si_set_ip_blocks(adev); + if (r) + return r; + break; +#endif #ifdef CONFIG_DRM_AMDGPU_CIK case CHIP_BONAIRE: case CHIP_HAWAII: -- cgit v1.1 From da69c161448d6a682b3761d9bc444161cbf25337 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 21 Jan 2016 19:08:55 +0800 Subject: drm/amdgpu: add si specific logic into the device initialize function v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v3: guard doorbell_fini as well Reviewed-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index abea6f2..aef9a9a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -55,6 +55,11 @@ static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev); static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev); static const char *amdgpu_asic_name[] = { + "TAHITI", + "PITCAIRN", + "VERDE", + "OLAND", + "HAINAN", "BONAIRE", "KAVERI", "KABINI", @@ -1571,8 +1576,13 @@ int amdgpu_device_init(struct amdgpu_device *adev, INIT_LIST_HEAD(&adev->shadow_list); mutex_init(&adev->shadow_list_lock); - adev->rmmio_base = pci_resource_start(adev->pdev, 5); - adev->rmmio_size = pci_resource_len(adev->pdev, 5); + if (adev->asic_type >= CHIP_BONAIRE) { + adev->rmmio_base = pci_resource_start(adev->pdev, 5); + adev->rmmio_size = pci_resource_len(adev->pdev, 5); + } else { + adev->rmmio_base = pci_resource_start(adev->pdev, 2); + adev->rmmio_size = pci_resource_len(adev->pdev, 2); + } adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size); if (adev->rmmio == NULL) { return -ENOMEM; @@ -1580,8 +1590,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base); DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size); - /* doorbell bar mapping */ - amdgpu_doorbell_init(adev); + if (adev->asic_type >= CHIP_BONAIRE) + /* doorbell bar mapping */ + amdgpu_doorbell_init(adev); /* io port mapping */ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { @@ -1790,7 +1801,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) adev->rio_mem = NULL; iounmap(adev->rmmio); adev->rmmio = NULL; - amdgpu_doorbell_fini(adev); + if (adev->asic_type >= CHIP_BONAIRE) + amdgpu_doorbell_fini(adev); amdgpu_debugfs_regs_cleanup(adev); amdgpu_debugfs_remove_files(adev); } -- cgit v1.1 From 9139d731fdaa52b85543f2713d65ca860e0ce884 Mon Sep 17 00:00:00 2001 From: Maruthi Srinivas Bayyavarapu Date: Tue, 26 Apr 2016 20:24:38 +0530 Subject: drm/amdgpu: add si dpm support in amdgpu_atombios v2: renamed _atom_ to _atombios_ for consistency added ulClockParams to _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 and _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 to avoid build break Signed-off-by: Maruthi Bayyavarapu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 158 +++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 16 ++- drivers/gpu/drm/amd/include/atombios.h | 2 + 3 files changed, 175 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 1b62116..59961db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -978,6 +978,48 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, return -EINVAL; switch (crev) { + case 2: + case 3: + case 5: + /* r6xx, r7xx, evergreen, ni, si. + * TODO: add support for asic_type <= CHIP_RV770*/ + if (clock_type == COMPUTE_ENGINE_PLL_PARAM) { + args.v3.ulClockParams = cpu_to_le32((clock_type << 24) | clock); + + amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); + + dividers->post_div = args.v3.ucPostDiv; + dividers->enable_post_div = (args.v3.ucCntlFlag & + ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; + dividers->enable_dithen = (args.v3.ucCntlFlag & + ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; + dividers->whole_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv); + dividers->frac_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac); + dividers->ref_div = args.v3.ucRefDiv; + dividers->vco_mode = (args.v3.ucCntlFlag & + ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; + } else { + /* for SI we use ComputeMemoryClockParam for memory plls */ + if (adev->asic_type >= CHIP_TAHITI) + return -EINVAL; + args.v5.ulClockParams = cpu_to_le32((clock_type << 24) | clock); + if (strobe_mode) + args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN; + + amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); + + dividers->post_div = args.v5.ucPostDiv; + dividers->enable_post_div = (args.v5.ucCntlFlag & + ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; + dividers->enable_dithen = (args.v5.ucCntlFlag & + ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; + dividers->whole_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDiv); + dividers->frac_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac); + dividers->ref_div = args.v5.ucRefDiv; + dividers->vco_mode = (args.v5.ucCntlFlag & + ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; + } + break; case 4: /* fusion */ args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */ @@ -1122,6 +1164,32 @@ void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev, amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); } +void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, + u16 *vddc, u16 *vddci, u16 *mvdd) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + u8 frev, crev; + u16 data_offset; + union firmware_info *firmware_info; + + *vddc = 0; + *vddci = 0; + *mvdd = 0; + + if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + firmware_info = + (union firmware_info *)(mode_info->atom_context->bios + + data_offset); + *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); + if ((frev == 2) && (crev >= 2)) { + *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage); + *mvdd = le16_to_cpu(firmware_info->info_22.usBootUpMVDDCVoltage); + } + } +} + union set_voltage { struct _SET_VOLTAGE_PS_ALLOCATION alloc; struct _SET_VOLTAGE_PARAMETERS v1; @@ -1129,6 +1197,52 @@ union set_voltage { struct _SET_VOLTAGE_PARAMETERS_V1_3 v3; }; +int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, + u16 voltage_id, u16 *voltage) +{ + union set_voltage args; + int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); + u8 frev, crev; + + if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev)) + return -EINVAL; + + switch (crev) { + case 1: + return -EINVAL; + case 2: + args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; + args.v2.ucVoltageMode = 0; + args.v2.usVoltageLevel = 0; + + amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); + + *voltage = le16_to_cpu(args.v2.usVoltageLevel); + break; + case 3: + args.v3.ucVoltageType = voltage_type; + args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL; + args.v3.usVoltageLevel = cpu_to_le16(voltage_id); + + amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); + + *voltage = le16_to_cpu(args.v3.usVoltageLevel); + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + return -EINVAL; + } + + return 0; +} + +int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, + u16 *voltage, + u16 leakage_idx) +{ + return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage); +} + void amdgpu_atombios_set_voltage(struct amdgpu_device *adev, u16 voltage_level, u8 voltage_type) @@ -1349,6 +1463,50 @@ static ATOM_VOLTAGE_OBJECT_V3 *amdgpu_atombios_lookup_voltage_object_v3(ATOM_VOL return NULL; } +int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, + u8 voltage_type, + u8 *svd_gpio_id, u8 *svc_gpio_id) +{ + int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); + u8 frev, crev; + u16 data_offset, size; + union voltage_object_info *voltage_info; + union voltage_object *voltage_object = NULL; + + if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size, + &frev, &crev, &data_offset)) { + voltage_info = (union voltage_object_info *) + (adev->mode_info.atom_context->bios + data_offset); + + switch (frev) { + case 3: + switch (crev) { + case 1: + voltage_object = (union voltage_object *) + amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3, + voltage_type, + VOLTAGE_OBJ_SVID2); + if (voltage_object) { + *svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId; + *svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId; + } else { + return -EINVAL; + } + break; + default: + DRM_ERROR("unknown voltage object table\n"); + return -EINVAL; + } + break; + default: + DRM_ERROR("unknown voltage object table\n"); + return -EINVAL; + } + + } + return 0; +} + bool amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev, u8 voltage_type, u8 voltage_mode) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h index 15dd43e..1735615 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h @@ -208,5 +208,19 @@ void amdgpu_atombios_scratch_regs_save(struct amdgpu_device *adev); void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev); void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); - +int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, + u16 voltage_id, u16 *voltage); +int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, + u16 *voltage, + u16 leakage_idx); +void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, + u16 *vddc, u16 *vddci, u16 *mvdd); +int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, + u8 clock_type, + u32 clock, + bool strobe_mode, + struct atom_clock_dividers *dividers); +int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, + u8 voltage_type, + u8 *svd_gpio_id, u8 *svc_gpio_id); #endif diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index 3493da5..4a4d379 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -494,6 +494,7 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 union { ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter + ULONG ulClockParams; //ULONG access for BE ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter }; UCHAR ucRefDiv; //Output Parameter @@ -526,6 +527,7 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 union { ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter + ULONG ulClockParams; //ULONG access for BE ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter }; UCHAR ucRefDiv; //Output Parameter -- cgit v1.1 From 0c34f45368422dc34545a56a60f3884ffc3a4a3b Mon Sep 17 00:00:00 2001 From: Maruthi Srinivas Bayyavarapu Date: Tue, 26 Apr 2016 20:31:54 +0530 Subject: drm/amdgpu: add SI SMC support Signed-off-by: Maruthi Bayyavarapu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_smc.c | 280 ++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/sislands_smc.h | 423 ++++++++++++++++++++++++++++++ 2 files changed, 703 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/si_smc.c create mode 100644 drivers/gpu/drm/amd/amdgpu/sislands_smc.h diff --git a/drivers/gpu/drm/amd/amdgpu/si_smc.c b/drivers/gpu/drm/amd/amdgpu/si_smc.c new file mode 100644 index 0000000..214f37c --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si_smc.c @@ -0,0 +1,280 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include +#include "drmP.h" +#include "amdgpu.h" +#include "si/sid.h" +#include "ppsmc.h" +#include "amdgpu_ucode.h" +#include "sislands_smc.h" + +static int si_set_smc_sram_address(struct amdgpu_device *adev, + u32 smc_address, u32 limit) +{ + if (smc_address & 3) + return -EINVAL; + if ((smc_address + 3) > limit) + return -EINVAL; + + WREG32(SMC_IND_INDEX_0, smc_address); + WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); + + return 0; +} + +int si_copy_bytes_to_smc(struct amdgpu_device *adev, + u32 smc_start_address, + const u8 *src, u32 byte_count, u32 limit) +{ + unsigned long flags; + int ret = 0; + u32 data, original_data, addr, extra_shift; + + if (smc_start_address & 3) + return -EINVAL; + if ((smc_start_address + byte_count) > limit) + return -EINVAL; + + addr = smc_start_address; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + while (byte_count >= 4) { + /* SMC address space is BE */ + data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; + + ret = si_set_smc_sram_address(adev, addr, limit); + if (ret) + goto done; + + WREG32(SMC_IND_DATA_0, data); + + src += 4; + byte_count -= 4; + addr += 4; + } + + /* RMW for the final bytes */ + if (byte_count > 0) { + data = 0; + + ret = si_set_smc_sram_address(adev, addr, limit); + if (ret) + goto done; + + original_data = RREG32(SMC_IND_DATA_0); + + extra_shift = 8 * (4 - byte_count); + + while (byte_count > 0) { + /* SMC address space is BE */ + data = (data << 8) + *src++; + byte_count--; + } + + data <<= extra_shift; + + data |= (original_data & ~((~0UL) << extra_shift)); + + ret = si_set_smc_sram_address(adev, addr, limit); + if (ret) + goto done; + + WREG32(SMC_IND_DATA_0, data); + } + +done: + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return ret; +} + +void si_start_smc(struct amdgpu_device *adev) +{ + u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); + + tmp &= ~RST_REG; + + WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); +} + +void si_reset_smc(struct amdgpu_device *adev) +{ + u32 tmp; + + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + + tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); + tmp |= RST_REG; + WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); +} + +int si_program_jump_on_start(struct amdgpu_device *adev) +{ + static const u8 data[] = { 0x0E, 0x00, 0x40, 0x40 }; + + return si_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1); +} + +void si_stop_smc_clock(struct amdgpu_device *adev) +{ + u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); + + tmp |= CK_DISABLE; + + WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); +} + +void si_start_smc_clock(struct amdgpu_device *adev) +{ + u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); + + tmp &= ~CK_DISABLE; + + WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); +} + +bool si_is_smc_running(struct amdgpu_device *adev) +{ + u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL); + u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); + + if (!(rst & RST_REG) && !(clk & CK_DISABLE)) + return true; + + return false; +} + +PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg) +{ + u32 tmp; + int i; + + if (!si_is_smc_running(adev)) + return PPSMC_Result_Failed; + + WREG32(SMC_MESSAGE_0, msg); + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(SMC_RESP_0); + if (tmp != 0) + break; + udelay(1); + } + tmp = RREG32(SMC_RESP_0); + + return (PPSMC_Result)tmp; +} + +PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev) +{ + u32 tmp; + int i; + + if (!si_is_smc_running(adev)) + return PPSMC_Result_OK; + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); + if ((tmp & CKEN) == 0) + break; + udelay(1); + } + + return PPSMC_Result_OK; +} + +int si_load_smc_ucode(struct amdgpu_device *adev, u32 limit) +{ + const struct smc_firmware_header_v1_0 *hdr; + unsigned long flags; + u32 ucode_start_address; + u32 ucode_size; + const u8 *src; + u32 data; + + if (!adev->pm.fw) + return -EINVAL; + + hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data; + + amdgpu_ucode_print_smc_hdr(&hdr->header); + + ucode_start_address = le32_to_cpu(hdr->ucode_start_addr); + ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); + src = (const u8 *) + (adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + if (ucode_size & 3) + return -EINVAL; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + WREG32(SMC_IND_INDEX_0, ucode_start_address); + WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); + while (ucode_size >= 4) { + /* SMC address space is BE */ + data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; + + WREG32(SMC_IND_DATA_0, data); + + src += 4; + ucode_size -= 4; + } + WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return 0; +} + +int si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 *value, u32 limit) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + ret = si_set_smc_sram_address(adev, smc_address, limit); + if (ret == 0) + *value = RREG32(SMC_IND_DATA_0); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return ret; +} + +int si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 value, u32 limit) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + ret = si_set_smc_sram_address(adev, smc_address, limit); + if (ret == 0) + WREG32(SMC_IND_DATA_0, value); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h new file mode 100644 index 0000000..542ab46 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h @@ -0,0 +1,423 @@ +/* + * Copyright 2013 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef PP_SISLANDS_SMC_H +#define PP_SISLANDS_SMC_H + +#include "ppsmc.h" + +#pragma pack(push, 1) + +#define SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 + +struct PP_SIslands_Dpm2PerfLevel +{ + uint8_t MaxPS; + uint8_t TgtAct; + uint8_t MaxPS_StepInc; + uint8_t MaxPS_StepDec; + uint8_t PSSamplingTime; + uint8_t NearTDPDec; + uint8_t AboveSafeInc; + uint8_t BelowSafeInc; + uint8_t PSDeltaLimit; + uint8_t PSDeltaWin; + uint16_t PwrEfficiencyRatio; + uint8_t Reserved[4]; +}; + +typedef struct PP_SIslands_Dpm2PerfLevel PP_SIslands_Dpm2PerfLevel; + +struct PP_SIslands_DPM2Status +{ + uint32_t dpm2Flags; + uint8_t CurrPSkip; + uint8_t CurrPSkipPowerShift; + uint8_t CurrPSkipTDP; + uint8_t CurrPSkipOCP; + uint8_t MaxSPLLIndex; + uint8_t MinSPLLIndex; + uint8_t CurrSPLLIndex; + uint8_t InfSweepMode; + uint8_t InfSweepDir; + uint8_t TDPexceeded; + uint8_t reserved; + uint8_t SwitchDownThreshold; + uint32_t SwitchDownCounter; + uint32_t SysScalingFactor; +}; + +typedef struct PP_SIslands_DPM2Status PP_SIslands_DPM2Status; + +struct PP_SIslands_DPM2Parameters +{ + uint32_t TDPLimit; + uint32_t NearTDPLimit; + uint32_t SafePowerLimit; + uint32_t PowerBoostLimit; + uint32_t MinLimitDelta; +}; +typedef struct PP_SIslands_DPM2Parameters PP_SIslands_DPM2Parameters; + +struct PP_SIslands_PAPMStatus +{ + uint32_t EstimatedDGPU_T; + uint32_t EstimatedDGPU_P; + uint32_t EstimatedAPU_T; + uint32_t EstimatedAPU_P; + uint8_t dGPU_T_Limit_Exceeded; + uint8_t reserved[3]; +}; +typedef struct PP_SIslands_PAPMStatus PP_SIslands_PAPMStatus; + +struct PP_SIslands_PAPMParameters +{ + uint32_t NearTDPLimitTherm; + uint32_t NearTDPLimitPAPM; + uint32_t PlatformPowerLimit; + uint32_t dGPU_T_Limit; + uint32_t dGPU_T_Warning; + uint32_t dGPU_T_Hysteresis; +}; +typedef struct PP_SIslands_PAPMParameters PP_SIslands_PAPMParameters; + +struct SISLANDS_SMC_SCLK_VALUE +{ + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_FUNC_CNTL_4; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t sclk_value; +}; + +typedef struct SISLANDS_SMC_SCLK_VALUE SISLANDS_SMC_SCLK_VALUE; + +struct SISLANDS_SMC_MCLK_VALUE +{ + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL_1; + uint32_t vMPLL_FUNC_CNTL_2; + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vDLL_CNTL; + uint32_t vMPLL_SS; + uint32_t vMPLL_SS2; + uint32_t mclk_value; +}; + +typedef struct SISLANDS_SMC_MCLK_VALUE SISLANDS_SMC_MCLK_VALUE; + +struct SISLANDS_SMC_VOLTAGE_VALUE +{ + uint16_t value; + uint8_t index; + uint8_t phase_settings; +}; + +typedef struct SISLANDS_SMC_VOLTAGE_VALUE SISLANDS_SMC_VOLTAGE_VALUE; + +struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL +{ + uint8_t ACIndex; + uint8_t displayWatermark; + uint8_t gen2PCIE; + uint8_t UVDWatermark; + uint8_t VCEWatermark; + uint8_t strobeMode; + uint8_t mcFlags; + uint8_t padding; + uint32_t aT; + uint32_t bSP; + SISLANDS_SMC_SCLK_VALUE sclk; + SISLANDS_SMC_MCLK_VALUE mclk; + SISLANDS_SMC_VOLTAGE_VALUE vddc; + SISLANDS_SMC_VOLTAGE_VALUE mvdd; + SISLANDS_SMC_VOLTAGE_VALUE vddci; + SISLANDS_SMC_VOLTAGE_VALUE std_vddc; + uint8_t hysteresisUp; + uint8_t hysteresisDown; + uint8_t stateFlags; + uint8_t arbRefreshState; + uint32_t SQPowerThrottle; + uint32_t SQPowerThrottle_2; + uint32_t MaxPoweredUpCU; + SISLANDS_SMC_VOLTAGE_VALUE high_temp_vddc; + SISLANDS_SMC_VOLTAGE_VALUE low_temp_vddc; + uint32_t reserved[2]; + PP_SIslands_Dpm2PerfLevel dpm2; +}; + +#define SISLANDS_SMC_STROBE_RATIO 0x0F +#define SISLANDS_SMC_STROBE_ENABLE 0x10 + +#define SISLANDS_SMC_MC_EDC_RD_FLAG 0x01 +#define SISLANDS_SMC_MC_EDC_WR_FLAG 0x02 +#define SISLANDS_SMC_MC_RTT_ENABLE 0x04 +#define SISLANDS_SMC_MC_STUTTER_EN 0x08 +#define SISLANDS_SMC_MC_PG_EN 0x10 + +typedef struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL SISLANDS_SMC_HW_PERFORMANCE_LEVEL; + +struct SISLANDS_SMC_SWSTATE +{ + uint8_t flags; + uint8_t levelCount; + uint8_t padding2; + uint8_t padding3; + SISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[1]; +}; + +typedef struct SISLANDS_SMC_SWSTATE SISLANDS_SMC_SWSTATE; + +#define SISLANDS_SMC_VOLTAGEMASK_VDDC 0 +#define SISLANDS_SMC_VOLTAGEMASK_MVDD 1 +#define SISLANDS_SMC_VOLTAGEMASK_VDDCI 2 +#define SISLANDS_SMC_VOLTAGEMASK_MAX 4 + +struct SISLANDS_SMC_VOLTAGEMASKTABLE +{ + uint32_t lowMask[SISLANDS_SMC_VOLTAGEMASK_MAX]; +}; + +typedef struct SISLANDS_SMC_VOLTAGEMASKTABLE SISLANDS_SMC_VOLTAGEMASKTABLE; + +#define SISLANDS_MAX_NO_VREG_STEPS 32 + +struct SISLANDS_SMC_STATETABLE +{ + uint8_t thermalProtectType; + uint8_t systemFlags; + uint8_t maxVDDCIndexInPPTable; + uint8_t extraFlags; + uint32_t lowSMIO[SISLANDS_MAX_NO_VREG_STEPS]; + SISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable; + SISLANDS_SMC_VOLTAGEMASKTABLE phaseMaskTable; + PP_SIslands_DPM2Parameters dpm2Params; + SISLANDS_SMC_SWSTATE initialState; + SISLANDS_SMC_SWSTATE ACPIState; + SISLANDS_SMC_SWSTATE ULVState; + SISLANDS_SMC_SWSTATE driverState; + SISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1]; +}; + +typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE; + +#define SI_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0 +#define SI_SMC_SOFT_REGISTER_delay_vreg 0xC +#define SI_SMC_SOFT_REGISTER_delay_acpi 0x28 +#define SI_SMC_SOFT_REGISTER_seq_index 0x5C +#define SI_SMC_SOFT_REGISTER_mvdd_chg_time 0x60 +#define SI_SMC_SOFT_REGISTER_mclk_switch_lim 0x70 +#define SI_SMC_SOFT_REGISTER_watermark_threshold 0x78 +#define SI_SMC_SOFT_REGISTER_phase_shedding_delay 0x88 +#define SI_SMC_SOFT_REGISTER_ulv_volt_change_delay 0x8C +#define SI_SMC_SOFT_REGISTER_mc_block_delay 0x98 +#define SI_SMC_SOFT_REGISTER_ticks_per_us 0xA8 +#define SI_SMC_SOFT_REGISTER_crtc_index 0xC4 +#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min 0xC8 +#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max 0xCC +#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4 +#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC +#define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100 +#define SI_SMC_SOFT_REGISTER_svi_rework_plat_type 0x118 +#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c +#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120 + +struct PP_SIslands_FanTable +{ + uint8_t fdo_mode; + uint8_t padding; + int16_t temp_min; + int16_t temp_med; + int16_t temp_max; + int16_t slope1; + int16_t slope2; + int16_t fdo_min; + int16_t hys_up; + int16_t hys_down; + int16_t hys_slope; + int16_t temp_resp_lim; + int16_t temp_curr; + int16_t slope_curr; + int16_t pwm_curr; + uint32_t refresh_period; + int16_t fdo_max; + uint8_t temp_src; + int8_t padding2; +}; + +typedef struct PP_SIslands_FanTable PP_SIslands_FanTable; + +#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 +#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32 + +#define SMC_SISLANDS_SCALE_I 7 +#define SMC_SISLANDS_SCALE_R 12 + +struct PP_SIslands_CacConfig +{ + uint16_t cac_lkge_lut[SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES]; + uint32_t lkge_lut_V0; + uint32_t lkge_lut_Vstep; + uint32_t WinTime; + uint32_t R_LL; + uint32_t calculation_repeats; + uint32_t l2numWin_TDP; + uint32_t dc_cac; + uint8_t lts_truncate_n; + uint8_t SHIFT_N; + uint8_t log2_PG_LKG_SCALE; + uint8_t cac_temp; + uint32_t lkge_lut_T0; + uint32_t lkge_lut_Tstep; +}; + +typedef struct PP_SIslands_CacConfig PP_SIslands_CacConfig; + +#define SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE 16 +#define SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20 + +struct SMC_SIslands_MCRegisterAddress +{ + uint16_t s0; + uint16_t s1; +}; + +typedef struct SMC_SIslands_MCRegisterAddress SMC_SIslands_MCRegisterAddress; + +struct SMC_SIslands_MCRegisterSet +{ + uint32_t value[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +typedef struct SMC_SIslands_MCRegisterSet SMC_SIslands_MCRegisterSet; + +struct SMC_SIslands_MCRegisters +{ + uint8_t last; + uint8_t reserved[3]; + SMC_SIslands_MCRegisterAddress address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; + SMC_SIslands_MCRegisterSet data[SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT]; +}; + +typedef struct SMC_SIslands_MCRegisters SMC_SIslands_MCRegisters; + +struct SMC_SIslands_MCArbDramTimingRegisterSet +{ + uint32_t mc_arb_dram_timing; + uint32_t mc_arb_dram_timing2; + uint8_t mc_arb_rfsh_rate; + uint8_t mc_arb_burst_time; + uint8_t padding[2]; +}; + +typedef struct SMC_SIslands_MCArbDramTimingRegisterSet SMC_SIslands_MCArbDramTimingRegisterSet; + +struct SMC_SIslands_MCArbDramTimingRegisters +{ + uint8_t arb_current; + uint8_t reserved[3]; + SMC_SIslands_MCArbDramTimingRegisterSet data[16]; +}; + +typedef struct SMC_SIslands_MCArbDramTimingRegisters SMC_SIslands_MCArbDramTimingRegisters; + +struct SMC_SISLANDS_SPLL_DIV_TABLE +{ + uint32_t freq[256]; + uint32_t ss[256]; +}; + +#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK 0x01ffffff +#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT 0 +#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK 0xfe000000 +#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT 25 +#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK 0x000fffff +#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT 0 +#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK 0xfff00000 +#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT 20 + +typedef struct SMC_SISLANDS_SPLL_DIV_TABLE SMC_SISLANDS_SPLL_DIV_TABLE; + +#define SMC_SISLANDS_DTE_MAX_FILTER_STAGES 5 + +#define SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE 16 + +struct Smc_SIslands_DTE_Configuration +{ + uint32_t tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; + uint32_t R[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; + uint32_t K; + uint32_t T0; + uint32_t MaxT; + uint8_t WindowSize; + uint8_t Tdep_count; + uint8_t temp_select; + uint8_t DTE_mode; + uint8_t T_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + uint32_t Tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + uint32_t Tdep_R[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + uint32_t Tthreshold; +}; + +typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration; + +#define SMC_SISLANDS_DTE_STATUS_FLAG_DTE_ON 1 + +#define SISLANDS_SMC_FIRMWARE_HEADER_LOCATION 0x10000 + +#define SISLANDS_SMC_FIRMWARE_HEADER_version 0x0 +#define SISLANDS_SMC_FIRMWARE_HEADER_flags 0x4 +#define SISLANDS_SMC_FIRMWARE_HEADER_softRegisters 0xC +#define SISLANDS_SMC_FIRMWARE_HEADER_stateTable 0x10 +#define SISLANDS_SMC_FIRMWARE_HEADER_fanTable 0x14 +#define SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable 0x18 +#define SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable 0x24 +#define SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable 0x30 +#define SISLANDS_SMC_FIRMWARE_HEADER_spllTable 0x38 +#define SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration 0x40 +#define SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters 0x48 + +#pragma pack(pop) + +int si_copy_bytes_to_smc(struct amdgpu_device *adev, + u32 smc_start_address, + const u8 *src, u32 byte_count, u32 limit); +void si_start_smc(struct amdgpu_device *adev); +void si_reset_smc(struct amdgpu_device *adev); +int si_program_jump_on_start(struct amdgpu_device *adev); +void si_stop_smc_clock(struct amdgpu_device *adev); +void si_start_smc_clock(struct amdgpu_device *adev); +bool si_is_smc_running(struct amdgpu_device *adev); +PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg); +PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev); +int si_load_smc_ucode(struct amdgpu_device *adev, u32 limit); +int si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 *value, u32 limit); +int si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 value, u32 limit); + +#endif + -- cgit v1.1 From 841686df9f7d2942cfd94d024b8591fa3f74ef7c Mon Sep 17 00:00:00 2001 From: Maruthi Bayyavarapu Date: Mon, 1 Aug 2016 12:42:32 -0400 Subject: drm/amdgpu: add SI DPM support (v4) v2: corrected register offset shift v3: rebase fixes v4: fix firmware paths add SI smc firmware versions for sysfs dump remove unused function forward define fix the tahiti specific value of DEEP_SLEEP_CLK_SEL field fix to miss adding thermal controller use vram_type instead of checking mem_gddr5 flag fix incorrect index of CG_FFCT_0 register fix incorrect reading method at si_get_current_pcie_speed Signed-off-by: Maruthi Bayyavarapu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 + drivers/gpu/drm/amd/amdgpu/r600_dpm.h | 127 + drivers/gpu/drm/amd/amdgpu/si_dpm.c | 7986 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/si_dpm.h | 1015 +++++ drivers/gpu/drm/amd/amdgpu/si_smc.c | 1 + 5 files changed, 9135 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/r600_dpm.h create mode 100644 drivers/gpu/drm/amd/amdgpu/si_dpm.c create mode 100644 drivers/gpu/drm/amd/amdgpu/si_dpm.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 1902f9f..86762cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1826,6 +1826,9 @@ struct amdgpu_asic_funcs { int (*set_vce_clocks)(struct amdgpu_device *adev, u32 evclk, u32 ecclk); /* query virtual capabilities */ u32 (*get_virtual_caps)(struct amdgpu_device *adev); + /* static power management */ + int (*get_pcie_lanes)(struct amdgpu_device *adev); + void (*set_pcie_lanes)(struct amdgpu_device *adev, int lanes); }; /* @@ -2242,6 +2245,9 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_asic_set_uvd_clocks(adev, v, d) (adev)->asic_funcs->set_uvd_clocks((adev), (v), (d)) #define amdgpu_asic_set_vce_clocks(adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec)) #define amdgpu_asic_get_virtual_caps(adev) ((adev)->asic_funcs->get_virtual_caps((adev))) +#define amdgpu_get_pcie_lanes(adev) (adev)->asic_funcs->get_pcie_lanes((adev)) +#define amdgpu_set_pcie_lanes(adev, l) (adev)->asic_funcs->set_pcie_lanes((adev), (l)) +#define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev)) #define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev)) #define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l)) #define amdgpu_asic_read_register(adev, se, sh, offset, v)((adev)->asic_funcs->read_register((adev), (se), (sh), (offset), (v))) diff --git a/drivers/gpu/drm/amd/amdgpu/r600_dpm.h b/drivers/gpu/drm/amd/amdgpu/r600_dpm.h new file mode 100644 index 0000000..055321f --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/r600_dpm.h @@ -0,0 +1,127 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __R600_DPM_H__ +#define __R600_DPM_H__ + +#define R600_ASI_DFLT 10000 +#define R600_BSP_DFLT 0x41EB +#define R600_BSU_DFLT 0x2 +#define R600_AH_DFLT 5 +#define R600_RLP_DFLT 25 +#define R600_RMP_DFLT 65 +#define R600_LHP_DFLT 40 +#define R600_LMP_DFLT 15 +#define R600_TD_DFLT 0 +#define R600_UTC_DFLT_00 0x24 +#define R600_UTC_DFLT_01 0x22 +#define R600_UTC_DFLT_02 0x22 +#define R600_UTC_DFLT_03 0x22 +#define R600_UTC_DFLT_04 0x22 +#define R600_UTC_DFLT_05 0x22 +#define R600_UTC_DFLT_06 0x22 +#define R600_UTC_DFLT_07 0x22 +#define R600_UTC_DFLT_08 0x22 +#define R600_UTC_DFLT_09 0x22 +#define R600_UTC_DFLT_10 0x22 +#define R600_UTC_DFLT_11 0x22 +#define R600_UTC_DFLT_12 0x22 +#define R600_UTC_DFLT_13 0x22 +#define R600_UTC_DFLT_14 0x22 +#define R600_DTC_DFLT_00 0x24 +#define R600_DTC_DFLT_01 0x22 +#define R600_DTC_DFLT_02 0x22 +#define R600_DTC_DFLT_03 0x22 +#define R600_DTC_DFLT_04 0x22 +#define R600_DTC_DFLT_05 0x22 +#define R600_DTC_DFLT_06 0x22 +#define R600_DTC_DFLT_07 0x22 +#define R600_DTC_DFLT_08 0x22 +#define R600_DTC_DFLT_09 0x22 +#define R600_DTC_DFLT_10 0x22 +#define R600_DTC_DFLT_11 0x22 +#define R600_DTC_DFLT_12 0x22 +#define R600_DTC_DFLT_13 0x22 +#define R600_DTC_DFLT_14 0x22 +#define R600_VRC_DFLT 0x0000C003 +#define R600_VOLTAGERESPONSETIME_DFLT 1000 +#define R600_BACKBIASRESPONSETIME_DFLT 1000 +#define R600_VRU_DFLT 0x3 +#define R600_SPLLSTEPTIME_DFLT 0x1000 +#define R600_SPLLSTEPUNIT_DFLT 0x3 +#define R600_TPU_DFLT 0 +#define R600_TPC_DFLT 0x200 +#define R600_SSTU_DFLT 0 +#define R600_SST_DFLT 0x00C8 +#define R600_GICST_DFLT 0x200 +#define R600_FCT_DFLT 0x0400 +#define R600_FCTU_DFLT 0 +#define R600_CTXCGTT3DRPHC_DFLT 0x20 +#define R600_CTXCGTT3DRSDC_DFLT 0x40 +#define R600_VDDC3DOORPHC_DFLT 0x100 +#define R600_VDDC3DOORSDC_DFLT 0x7 +#define R600_VDDC3DOORSU_DFLT 0 +#define R600_MPLLLOCKTIME_DFLT 100 +#define R600_MPLLRESETTIME_DFLT 150 +#define R600_VCOSTEPPCT_DFLT 20 +#define R600_ENDINGVCOSTEPPCT_DFLT 5 +#define R600_REFERENCEDIVIDER_DFLT 4 + +#define R600_PM_NUMBER_OF_TC 15 +#define R600_PM_NUMBER_OF_SCLKS 20 +#define R600_PM_NUMBER_OF_MCLKS 4 +#define R600_PM_NUMBER_OF_VOLTAGE_LEVELS 4 +#define R600_PM_NUMBER_OF_ACTIVITY_LEVELS 3 + +/* XXX are these ok? */ +#define R600_TEMP_RANGE_MIN (90 * 1000) +#define R600_TEMP_RANGE_MAX (120 * 1000) + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + +enum r600_power_level { + R600_POWER_LEVEL_LOW = 0, + R600_POWER_LEVEL_MEDIUM = 1, + R600_POWER_LEVEL_HIGH = 2, + R600_POWER_LEVEL_CTXSW = 3, +}; + +enum r600_td { + R600_TD_AUTO, + R600_TD_UP, + R600_TD_DOWN, +}; + +enum r600_display_watermark { + R600_DISPLAY_WATERMARK_LOW = 0, + R600_DISPLAY_WATERMARK_HIGH = 1, +}; + +enum r600_display_gap +{ + R600_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, + R600_PM_DISPLAY_GAP_VBLANK = 1, + R600_PM_DISPLAY_GAP_WATERMARK = 2, + R600_PM_DISPLAY_GAP_IGNORE = 3, +}; +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c new file mode 100644 index 0000000..2ef4cc1 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -0,0 +1,7986 @@ +/* + * Copyright 2013 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "drmP.h" +#include "amdgpu.h" +#include "amdgpu_pm.h" +#include "amdgpu_dpm.h" +#include "amdgpu_atombios.h" +#include "si/sid.h" +#include "r600_dpm.h" +#include "si_dpm.h" +#include "atom.h" +#include "../include/pptable.h" +#include +#include +#include + +#define MC_CG_ARB_FREQ_F0 0x0a +#define MC_CG_ARB_FREQ_F1 0x0b +#define MC_CG_ARB_FREQ_F2 0x0c +#define MC_CG_ARB_FREQ_F3 0x0d + +#define SMC_RAM_END 0x20000 + +#define SCLK_MIN_DEEPSLEEP_FREQ 1350 + + +/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 + +#define BIOS_SCRATCH_4 0x5cd + +MODULE_FIRMWARE("radeon/tahiti_smc.bin"); +MODULE_FIRMWARE("radeon/pitcairn_smc.bin"); +MODULE_FIRMWARE("radeon/verde_smc.bin"); +MODULE_FIRMWARE("radeon/oland_smc.bin"); +MODULE_FIRMWARE("radeon/hainan_smc.bin"); + +union power_info { + struct _ATOM_POWERPLAY_INFO info; + struct _ATOM_POWERPLAY_INFO_V2 info_2; + struct _ATOM_POWERPLAY_INFO_V3 info_3; + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; + struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; + struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; +}; + +union fan_info { + struct _ATOM_PPLIB_FANTABLE fan; + struct _ATOM_PPLIB_FANTABLE2 fan2; + struct _ATOM_PPLIB_FANTABLE3 fan3; +}; + +union pplib_clock_info { + struct _ATOM_PPLIB_R600_CLOCK_INFO r600; + struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; + struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; + struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; + struct _ATOM_PPLIB_SI_CLOCK_INFO si; +}; + +const u32 r600_utc[R600_PM_NUMBER_OF_TC] = +{ + R600_UTC_DFLT_00, + R600_UTC_DFLT_01, + R600_UTC_DFLT_02, + R600_UTC_DFLT_03, + R600_UTC_DFLT_04, + R600_UTC_DFLT_05, + R600_UTC_DFLT_06, + R600_UTC_DFLT_07, + R600_UTC_DFLT_08, + R600_UTC_DFLT_09, + R600_UTC_DFLT_10, + R600_UTC_DFLT_11, + R600_UTC_DFLT_12, + R600_UTC_DFLT_13, + R600_UTC_DFLT_14, +}; + +const u32 r600_dtc[R600_PM_NUMBER_OF_TC] = +{ + R600_DTC_DFLT_00, + R600_DTC_DFLT_01, + R600_DTC_DFLT_02, + R600_DTC_DFLT_03, + R600_DTC_DFLT_04, + R600_DTC_DFLT_05, + R600_DTC_DFLT_06, + R600_DTC_DFLT_07, + R600_DTC_DFLT_08, + R600_DTC_DFLT_09, + R600_DTC_DFLT_10, + R600_DTC_DFLT_11, + R600_DTC_DFLT_12, + R600_DTC_DFLT_13, + R600_DTC_DFLT_14, +}; + +static const struct si_cac_config_reg cac_weights_tahiti[] = +{ + { 0x0, 0x0000ffff, 0, 0xc, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x101, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0xc, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x8fc, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x95, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x34e, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x1a1, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0xda, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x46, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x208, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0xe7, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x948, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x167, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x31, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x18e, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_tahiti[] = +{ + { 0x143, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x149, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14c, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x92, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x95, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x155, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x158, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x116, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x119, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } + +}; + +static const struct si_cac_config_reg cac_override_tahiti[] = +{ + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_tahiti = +{ + ((1 << 16) | 27027), + 6, + 0, + 4, + 95, + { + 0UL, + 0UL, + 4521550UL, + 309631529UL, + -1270850L, + 4513710L, + 40 + }, + 595000000UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_dte_data dte_data_tahiti = +{ + { 1159409, 0, 0, 0, 0 }, + { 777, 0, 0, 0, 0 }, + 2, + 54000, + 127000, + 25, + 2, + 10, + 13, + { 27, 31, 35, 39, 43, 47, 54, 61, 67, 74, 81, 88, 95, 0, 0, 0 }, + { 240888759, 221057860, 235370597, 162287531, 158510299, 131423027, 116673180, 103067515, 87941937, 76209048, 68209175, 64090048, 58301890, 0, 0, 0 }, + { 12024, 11189, 11451, 8411, 7939, 6666, 5681, 4905, 4241, 3720, 3354, 3122, 2890, 0, 0, 0 }, + 85, + false +}; + +static const struct si_dte_data dte_data_tahiti_le = +{ + { 0x1E8480, 0x7A1200, 0x2160EC0, 0x3938700, 0 }, + { 0x7D, 0x7D, 0x4E4, 0xB00, 0 }, + 0x5, + 0xAFC8, + 0x64, + 0x32, + 1, + 0, + 0x10, + { 0x78, 0x7C, 0x82, 0x88, 0x8E, 0x94, 0x9A, 0xA0, 0xA6, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC, 0xC0, 0xC4 }, + { 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700, 0x3938700 }, + { 0x2AF8, 0x2AF8, 0x29BB, 0x27F9, 0x2637, 0x2475, 0x22B3, 0x20F1, 0x1F2F, 0x1D6D, 0x1734, 0x1414, 0x10F4, 0xDD4, 0xAB4, 0x794 }, + 85, + true +}; + +static const struct si_dte_data dte_data_tahiti_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x7D0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_new_zealand = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0 }, + { 0x29B, 0x3E9, 0x537, 0x7D2, 0 }, + 0x5, + 0xAFC8, + 0x69, + 0x32, + 1, + 0, + 0x10, + { 0x82, 0xA0, 0xB4, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0xDAC, 0x1388, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685 }, + 85, + true +}; + +static const struct si_dte_data dte_data_aruba_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_malta = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +struct si_cac_config_reg cac_weights_pitcairn[] = +{ + { 0x0, 0x0000ffff, 0, 0x8a, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x24d, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x19, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0xc11, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x7f3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x403, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x367, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x4c9, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x45d, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x36d, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x534, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x5da, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x880, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0x201, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x1f, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5de, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x7b, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x13, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0xf9, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x66, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x13, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x186, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_pitcairn[] = +{ + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x116, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x155, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x92, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x149, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x119, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x158, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x95, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_override_pitcairn[] = +{ + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_pitcairn = +{ + ((1 << 16) | 27027), + 5, + 0, + 6, + 100, + { + 51600000UL, + 1800000UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_dte_data dte_data_pitcairn = +{ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0, + false +}; + +static const struct si_dte_data dte_data_curacao_xt = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_curacao_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_neptune_xt = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x3A2F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_cac_config_reg cac_weights_chelsea_pro[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x2BD, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_chelsea_xt[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x30A, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_heathrow[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x362, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_cape_verde_pro[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x315, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_cape_verde[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_cape_verde[] = +{ + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_override_cape_verde[] = +{ + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_cape_verde = +{ + ((1 << 16) | 0x6993), + 5, + 0, + 7, + 105, + { + 0UL, + 0UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_dte_data dte_data_cape_verde = +{ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0, + false +}; + +static const struct si_dte_data dte_data_venus_xtx = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x71C, 0xAAB, 0xE39, 0x11C7, 0x0 }, + 5, + 55000, + 0x69, + 0xA, + 1, + 0, + 0x3, + { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0xD6D8, 0x88B8, 0x1555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_venus_xt = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0xBDA, 0x11C7, 0x17B4, 0x1DA1, 0x0 }, + 5, + 55000, + 0x69, + 0xA, + 1, + 0, + 0x3, + { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0xAFC8, 0x88B8, 0x238E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_venus_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x11C7, 0x1AAB, 0x238E, 0x2C72, 0x0 }, + 5, + 55000, + 0x69, + 0xA, + 1, + 0, + 0x3, + { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0x88B8, 0x88B8, 0x3555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +struct si_cac_config_reg cac_weights_oland[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_mars_pro[] = +{ + { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_mars_xt[] = +{ + { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x60, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_oland_pro[] = +{ + { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x90, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_oland_xt[] = +{ + { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x120, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_oland[] = +{ + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_mars_pro[] = +{ + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_override_oland[] = +{ + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_oland = +{ + ((1 << 16) | 0x6993), + 5, + 0, + 7, + 105, + { + 0UL, + 0UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_powertune_data powertune_data_mars_pro = +{ + ((1 << 16) | 0x6993), + 5, + 0, + 7, + 105, + { + 0UL, + 0UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_dte_data dte_data_oland = +{ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0, + false +}; + +static const struct si_dte_data dte_data_mars_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 55000, + 105, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0xF627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_sun_xt = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 55000, + 105, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0xD555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + + +static const struct si_cac_config_reg cac_weights_hainan[] = +{ + { 0x0, 0x0000ffff, 0, 0x2d9, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x22b, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x21c, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x1dc, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x24e, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x35e, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1143, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0xe17, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x441, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x28b, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0xabe, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xf11, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x907, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0xb45, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0xd1e, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xa2c, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x62, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x1f3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x42, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x709, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x3a, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x357, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x314, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x6d, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x1b9, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_hainan = +{ + ((1 << 16) | 0x6993), + 5, + 0, + 9, + 105, + { + 0UL, + 0UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev); +struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev); +struct ni_power_info *ni_get_pi(struct amdgpu_device *adev); +struct si_ps *si_get_ps(struct amdgpu_ps *rps); + +static int si_populate_voltage_value(struct amdgpu_device *adev, + const struct atom_voltage_table *table, + u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage); +static int si_get_std_voltage_value(struct amdgpu_device *adev, + SISLANDS_SMC_VOLTAGE_VALUE *voltage, + u16 *std_voltage); +static int si_write_smc_soft_register(struct amdgpu_device *adev, + u16 reg_offset, u32 value); +static int si_convert_power_level_to_smc(struct amdgpu_device *adev, + struct rv7xx_pl *pl, + SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level); +static int si_calculate_sclk_params(struct amdgpu_device *adev, + u32 engine_clock, + SISLANDS_SMC_SCLK_VALUE *sclk); + +static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev); +static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev); +static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev); +static void si_dpm_set_irq_funcs(struct amdgpu_device *adev); + +extern u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg); + +static struct si_power_info *si_get_pi(struct amdgpu_device *adev) +{ + struct si_power_info *pi = adev->pm.dpm.priv; + return pi; +} + +static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff, + u16 v, s32 t, u32 ileakage, u32 *leakage) +{ + s64 kt, kv, leakage_w, i_leakage, vddc; + s64 temperature, t_slope, t_intercept, av, bv, t_ref; + s64 tmp; + + i_leakage = div64_s64(drm_int2fixp(ileakage), 100); + vddc = div64_s64(drm_int2fixp(v), 1000); + temperature = div64_s64(drm_int2fixp(t), 1000); + + t_slope = div64_s64(drm_int2fixp(coeff->t_slope), 100000000); + t_intercept = div64_s64(drm_int2fixp(coeff->t_intercept), 100000000); + av = div64_s64(drm_int2fixp(coeff->av), 100000000); + bv = div64_s64(drm_int2fixp(coeff->bv), 100000000); + t_ref = drm_int2fixp(coeff->t_ref); + + tmp = drm_fixp_mul(t_slope, vddc) + t_intercept; + kt = drm_fixp_exp(drm_fixp_mul(tmp, temperature)); + kt = drm_fixp_div(kt, drm_fixp_exp(drm_fixp_mul(tmp, t_ref))); + kv = drm_fixp_mul(av, drm_fixp_exp(drm_fixp_mul(bv, vddc))); + + leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc); + + *leakage = drm_fixp2int(leakage_w * 1000); +} + +static void si_calculate_leakage_for_v_and_t(struct amdgpu_device *adev, + const struct ni_leakage_coeffients *coeff, + u16 v, + s32 t, + u32 i_leakage, + u32 *leakage) +{ + si_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage); +} + +static void si_calculate_leakage_for_v_formula(const struct ni_leakage_coeffients *coeff, + const u32 fixed_kt, u16 v, + u32 ileakage, u32 *leakage) +{ + s64 kt, kv, leakage_w, i_leakage, vddc; + + i_leakage = div64_s64(drm_int2fixp(ileakage), 100); + vddc = div64_s64(drm_int2fixp(v), 1000); + + kt = div64_s64(drm_int2fixp(fixed_kt), 100000000); + kv = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->av), 100000000), + drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bv), 100000000), vddc))); + + leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc); + + *leakage = drm_fixp2int(leakage_w * 1000); +} + +static void si_calculate_leakage_for_v(struct amdgpu_device *adev, + const struct ni_leakage_coeffients *coeff, + const u32 fixed_kt, + u16 v, + u32 i_leakage, + u32 *leakage) +{ + si_calculate_leakage_for_v_formula(coeff, fixed_kt, v, i_leakage, leakage); +} + + +static void si_update_dte_from_pl2(struct amdgpu_device *adev, + struct si_dte_data *dte_data) +{ + u32 p_limit1 = adev->pm.dpm.tdp_limit; + u32 p_limit2 = adev->pm.dpm.near_tdp_limit; + u32 k = dte_data->k; + u32 t_max = dte_data->max_t; + u32 t_split[5] = { 10, 15, 20, 25, 30 }; + u32 t_0 = dte_data->t0; + u32 i; + + if (p_limit2 != 0 && p_limit2 <= p_limit1) { + dte_data->tdep_count = 3; + + for (i = 0; i < k; i++) { + dte_data->r[i] = + (t_split[i] * (t_max - t_0/(u32)1000) * (1 << 14)) / + (p_limit2 * (u32)100); + } + + dte_data->tdep_r[1] = dte_data->r[4] * 2; + + for (i = 2; i < SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; i++) { + dte_data->tdep_r[i] = dte_data->r[4]; + } + } else { + DRM_ERROR("Invalid PL2! DTE will not be updated.\n"); + } +} + +struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = adev->pm.dpm.priv; + + return pi; +} + +struct ni_power_info *ni_get_pi(struct amdgpu_device *adev) +{ + struct ni_power_info *pi = adev->pm.dpm.priv; + + return pi; +} + +struct si_ps *si_get_ps(struct amdgpu_ps *aps) +{ + struct si_ps *ps = aps->ps_priv; + + return ps; +} + +static void si_initialize_powertune_defaults(struct amdgpu_device *adev) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + bool update_dte_from_pl2 = false; + + if (adev->asic_type == CHIP_TAHITI) { + si_pi->cac_weights = cac_weights_tahiti; + si_pi->lcac_config = lcac_tahiti; + si_pi->cac_override = cac_override_tahiti; + si_pi->powertune_data = &powertune_data_tahiti; + si_pi->dte_data = dte_data_tahiti; + + switch (adev->pdev->device) { + case 0x6798: + si_pi->dte_data.enable_dte_by_default = true; + break; + case 0x6799: + si_pi->dte_data = dte_data_new_zealand; + break; + case 0x6790: + case 0x6791: + case 0x6792: + case 0x679E: + si_pi->dte_data = dte_data_aruba_pro; + update_dte_from_pl2 = true; + break; + case 0x679B: + si_pi->dte_data = dte_data_malta; + update_dte_from_pl2 = true; + break; + case 0x679A: + si_pi->dte_data = dte_data_tahiti_pro; + update_dte_from_pl2 = true; + break; + default: + if (si_pi->dte_data.enable_dte_by_default == true) + DRM_ERROR("DTE is not enabled!\n"); + break; + } + } else if (adev->asic_type == CHIP_PITCAIRN) { + switch (adev->pdev->device) { + case 0x6810: + case 0x6818: + si_pi->cac_weights = cac_weights_pitcairn; + si_pi->lcac_config = lcac_pitcairn; + si_pi->cac_override = cac_override_pitcairn; + si_pi->powertune_data = &powertune_data_pitcairn; + si_pi->dte_data = dte_data_curacao_xt; + update_dte_from_pl2 = true; + break; + case 0x6819: + case 0x6811: + si_pi->cac_weights = cac_weights_pitcairn; + si_pi->lcac_config = lcac_pitcairn; + si_pi->cac_override = cac_override_pitcairn; + si_pi->powertune_data = &powertune_data_pitcairn; + si_pi->dte_data = dte_data_curacao_pro; + update_dte_from_pl2 = true; + break; + case 0x6800: + case 0x6806: + si_pi->cac_weights = cac_weights_pitcairn; + si_pi->lcac_config = lcac_pitcairn; + si_pi->cac_override = cac_override_pitcairn; + si_pi->powertune_data = &powertune_data_pitcairn; + si_pi->dte_data = dte_data_neptune_xt; + update_dte_from_pl2 = true; + break; + default: + si_pi->cac_weights = cac_weights_pitcairn; + si_pi->lcac_config = lcac_pitcairn; + si_pi->cac_override = cac_override_pitcairn; + si_pi->powertune_data = &powertune_data_pitcairn; + si_pi->dte_data = dte_data_pitcairn; + break; + } + } else if (adev->asic_type == CHIP_VERDE) { + si_pi->lcac_config = lcac_cape_verde; + si_pi->cac_override = cac_override_cape_verde; + si_pi->powertune_data = &powertune_data_cape_verde; + + switch (adev->pdev->device) { + case 0x683B: + case 0x683F: + case 0x6829: + case 0x6835: + si_pi->cac_weights = cac_weights_cape_verde_pro; + si_pi->dte_data = dte_data_cape_verde; + break; + case 0x682C: + si_pi->cac_weights = cac_weights_cape_verde_pro; + si_pi->dte_data = dte_data_sun_xt; + break; + case 0x6825: + case 0x6827: + si_pi->cac_weights = cac_weights_heathrow; + si_pi->dte_data = dte_data_cape_verde; + break; + case 0x6824: + case 0x682D: + si_pi->cac_weights = cac_weights_chelsea_xt; + si_pi->dte_data = dte_data_cape_verde; + break; + case 0x682F: + si_pi->cac_weights = cac_weights_chelsea_pro; + si_pi->dte_data = dte_data_cape_verde; + break; + case 0x6820: + si_pi->cac_weights = cac_weights_heathrow; + si_pi->dte_data = dte_data_venus_xtx; + break; + case 0x6821: + si_pi->cac_weights = cac_weights_heathrow; + si_pi->dte_data = dte_data_venus_xt; + break; + case 0x6823: + case 0x682B: + case 0x6822: + case 0x682A: + si_pi->cac_weights = cac_weights_chelsea_pro; + si_pi->dte_data = dte_data_venus_pro; + break; + default: + si_pi->cac_weights = cac_weights_cape_verde; + si_pi->dte_data = dte_data_cape_verde; + break; + } + } else if (adev->asic_type == CHIP_OLAND) { + switch (adev->pdev->device) { + case 0x6601: + case 0x6621: + case 0x6603: + case 0x6605: + si_pi->cac_weights = cac_weights_mars_pro; + si_pi->lcac_config = lcac_mars_pro; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_mars_pro; + si_pi->dte_data = dte_data_mars_pro; + update_dte_from_pl2 = true; + break; + case 0x6600: + case 0x6606: + case 0x6620: + case 0x6604: + si_pi->cac_weights = cac_weights_mars_xt; + si_pi->lcac_config = lcac_mars_pro; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_mars_pro; + si_pi->dte_data = dte_data_mars_pro; + update_dte_from_pl2 = true; + break; + case 0x6611: + case 0x6613: + case 0x6608: + si_pi->cac_weights = cac_weights_oland_pro; + si_pi->lcac_config = lcac_mars_pro; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_mars_pro; + si_pi->dte_data = dte_data_mars_pro; + update_dte_from_pl2 = true; + break; + case 0x6610: + si_pi->cac_weights = cac_weights_oland_xt; + si_pi->lcac_config = lcac_mars_pro; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_mars_pro; + si_pi->dte_data = dte_data_mars_pro; + update_dte_from_pl2 = true; + break; + default: + si_pi->cac_weights = cac_weights_oland; + si_pi->lcac_config = lcac_oland; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_oland; + si_pi->dte_data = dte_data_oland; + break; + } + } else if (adev->asic_type == CHIP_HAINAN) { + si_pi->cac_weights = cac_weights_hainan; + si_pi->lcac_config = lcac_oland; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_hainan; + si_pi->dte_data = dte_data_sun_xt; + update_dte_from_pl2 = true; + } else { + DRM_ERROR("Unknown SI asic revision, failed to initialize PowerTune!\n"); + return; + } + + ni_pi->enable_power_containment = false; + ni_pi->enable_cac = false; + ni_pi->enable_sq_ramping = false; + si_pi->enable_dte = false; + + if (si_pi->powertune_data->enable_powertune_by_default) { + ni_pi->enable_power_containment= true; + ni_pi->enable_cac = true; + if (si_pi->dte_data.enable_dte_by_default) { + si_pi->enable_dte = true; + if (update_dte_from_pl2) + si_update_dte_from_pl2(adev, &si_pi->dte_data); + + } + ni_pi->enable_sq_ramping = true; + } + + ni_pi->driver_calculate_cac_leakage = true; + ni_pi->cac_configuration_required = true; + + if (ni_pi->cac_configuration_required) { + ni_pi->support_cac_long_term_average = true; + si_pi->dyn_powertune_data.l2_lta_window_size = + si_pi->powertune_data->l2_lta_window_size_default; + si_pi->dyn_powertune_data.lts_truncate = + si_pi->powertune_data->lts_truncate_default; + } else { + ni_pi->support_cac_long_term_average = false; + si_pi->dyn_powertune_data.l2_lta_window_size = 0; + si_pi->dyn_powertune_data.lts_truncate = 0; + } + + si_pi->dyn_powertune_data.disable_uvd_powertune = false; +} + +static u32 si_get_smc_power_scaling_factor(struct amdgpu_device *adev) +{ + return 1; +} + +static u32 si_calculate_cac_wintime(struct amdgpu_device *adev) +{ + u32 xclk; + u32 wintime; + u32 cac_window; + u32 cac_window_size; + + xclk = amdgpu_asic_get_xclk(adev); + + if (xclk == 0) + return 0; + + cac_window = RREG32(CG_CAC_CTRL) & CAC_WINDOW_MASK; + cac_window_size = ((cac_window & 0xFFFF0000) >> 16) * (cac_window & 0x0000FFFF); + + wintime = (cac_window_size * 100) / xclk; + + return wintime; +} + +static u32 si_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor) +{ + return power_in_watts; +} + +static int si_calculate_adjusted_tdp_limits(struct amdgpu_device *adev, + bool adjust_polarity, + u32 tdp_adjustment, + u32 *tdp_limit, + u32 *near_tdp_limit) +{ + u32 adjustment_delta, max_tdp_limit; + + if (tdp_adjustment > (u32)adev->pm.dpm.tdp_od_limit) + return -EINVAL; + + max_tdp_limit = ((100 + 100) * adev->pm.dpm.tdp_limit) / 100; + + if (adjust_polarity) { + *tdp_limit = ((100 + tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100; + *near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted + (*tdp_limit - adev->pm.dpm.tdp_limit); + } else { + *tdp_limit = ((100 - tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100; + adjustment_delta = adev->pm.dpm.tdp_limit - *tdp_limit; + if (adjustment_delta < adev->pm.dpm.near_tdp_limit_adjusted) + *near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted - adjustment_delta; + else + *near_tdp_limit = 0; + } + + if ((*tdp_limit <= 0) || (*tdp_limit > max_tdp_limit)) + return -EINVAL; + if ((*near_tdp_limit <= 0) || (*near_tdp_limit > *tdp_limit)) + return -EINVAL; + + return 0; +} + +static int si_populate_smc_tdp_limits(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + + if (ni_pi->enable_power_containment) { + SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable; + PP_SIslands_PAPMParameters *papm_parm; + struct amdgpu_ppm_table *ppm = adev->pm.dpm.dyn_state.ppm_table; + u32 scaling_factor = si_get_smc_power_scaling_factor(adev); + u32 tdp_limit; + u32 near_tdp_limit; + int ret; + + if (scaling_factor == 0) + return -EINVAL; + + memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE)); + + ret = si_calculate_adjusted_tdp_limits(adev, + false, /* ??? */ + adev->pm.dpm.tdp_adjustment, + &tdp_limit, + &near_tdp_limit); + if (ret) + return ret; + + smc_table->dpm2Params.TDPLimit = + cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000); + smc_table->dpm2Params.NearTDPLimit = + cpu_to_be32(si_scale_power_for_smc(near_tdp_limit, scaling_factor) * 1000); + smc_table->dpm2Params.SafePowerLimit = + cpu_to_be32(si_scale_power_for_smc((near_tdp_limit * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000); + + ret = si_copy_bytes_to_smc(adev, + (si_pi->state_table_start + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + + offsetof(PP_SIslands_DPM2Parameters, TDPLimit)), + (u8 *)(&(smc_table->dpm2Params.TDPLimit)), + sizeof(u32) * 3, + si_pi->sram_end); + if (ret) + return ret; + + if (si_pi->enable_ppm) { + papm_parm = &si_pi->papm_parm; + memset(papm_parm, 0, sizeof(PP_SIslands_PAPMParameters)); + papm_parm->NearTDPLimitTherm = cpu_to_be32(ppm->dgpu_tdp); + papm_parm->dGPU_T_Limit = cpu_to_be32(ppm->tj_max); + papm_parm->dGPU_T_Warning = cpu_to_be32(95); + papm_parm->dGPU_T_Hysteresis = cpu_to_be32(5); + papm_parm->PlatformPowerLimit = 0xffffffff; + papm_parm->NearTDPLimitPAPM = 0xffffffff; + + ret = si_copy_bytes_to_smc(adev, si_pi->papm_cfg_table_start, + (u8 *)papm_parm, + sizeof(PP_SIslands_PAPMParameters), + si_pi->sram_end); + if (ret) + return ret; + } + } + return 0; +} + +static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + + if (ni_pi->enable_power_containment) { + SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable; + u32 scaling_factor = si_get_smc_power_scaling_factor(adev); + int ret; + + memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE)); + + smc_table->dpm2Params.NearTDPLimit = + cpu_to_be32(si_scale_power_for_smc(adev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000); + smc_table->dpm2Params.SafePowerLimit = + cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000); + + ret = si_copy_bytes_to_smc(adev, + (si_pi->state_table_start + + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + + offsetof(PP_SIslands_DPM2Parameters, NearTDPLimit)), + (u8 *)(&(smc_table->dpm2Params.NearTDPLimit)), + sizeof(u32) * 2, + si_pi->sram_end); + if (ret) + return ret; + } + + return 0; +} + +static u16 si_calculate_power_efficiency_ratio(struct amdgpu_device *adev, + const u16 prev_std_vddc, + const u16 curr_std_vddc) +{ + u64 margin = (u64)SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN; + u64 prev_vddc = (u64)prev_std_vddc; + u64 curr_vddc = (u64)curr_std_vddc; + u64 pwr_efficiency_ratio, n, d; + + if ((prev_vddc == 0) || (curr_vddc == 0)) + return 0; + + n = div64_u64((u64)1024 * curr_vddc * curr_vddc * ((u64)1000 + margin), (u64)1000); + d = prev_vddc * prev_vddc; + pwr_efficiency_ratio = div64_u64(n, d); + + if (pwr_efficiency_ratio > (u64)0xFFFF) + return 0; + + return (u16)pwr_efficiency_ratio; +} + +static bool si_should_disable_uvd_powertune(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + if (si_pi->dyn_powertune_data.disable_uvd_powertune && + amdgpu_state->vclk && amdgpu_state->dclk) + return true; + + return false; +} + +struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev) +{ + struct evergreen_power_info *pi = adev->pm.dpm.priv; + + return pi; +} + +static int si_populate_power_containment_values(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + SISLANDS_SMC_VOLTAGE_VALUE vddc; + u32 prev_sclk; + u32 max_sclk; + u32 min_sclk; + u16 prev_std_vddc; + u16 curr_std_vddc; + int i; + u16 pwr_efficiency_ratio; + u8 max_ps_percent; + bool disable_uvd_power_tune; + int ret; + + if (ni_pi->enable_power_containment == false) + return 0; + + if (state->performance_level_count == 0) + return -EINVAL; + + if (smc_state->levelCount != state->performance_level_count) + return -EINVAL; + + disable_uvd_power_tune = si_should_disable_uvd_powertune(adev, amdgpu_state); + + smc_state->levels[0].dpm2.MaxPS = 0; + smc_state->levels[0].dpm2.NearTDPDec = 0; + smc_state->levels[0].dpm2.AboveSafeInc = 0; + smc_state->levels[0].dpm2.BelowSafeInc = 0; + smc_state->levels[0].dpm2.PwrEfficiencyRatio = 0; + + for (i = 1; i < state->performance_level_count; i++) { + prev_sclk = state->performance_levels[i-1].sclk; + max_sclk = state->performance_levels[i].sclk; + if (i == 1) + max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_M; + else + max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_H; + + if (prev_sclk > max_sclk) + return -EINVAL; + + if ((max_ps_percent == 0) || + (prev_sclk == max_sclk) || + disable_uvd_power_tune) { + min_sclk = max_sclk; + } else if (i == 1) { + min_sclk = prev_sclk; + } else { + min_sclk = (prev_sclk * (u32)max_ps_percent) / 100; + } + + if (min_sclk < state->performance_levels[0].sclk) + min_sclk = state->performance_levels[0].sclk; + + if (min_sclk == 0) + return -EINVAL; + + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + state->performance_levels[i-1].vddc, &vddc); + if (ret) + return ret; + + ret = si_get_std_voltage_value(adev, &vddc, &prev_std_vddc); + if (ret) + return ret; + + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + state->performance_levels[i].vddc, &vddc); + if (ret) + return ret; + + ret = si_get_std_voltage_value(adev, &vddc, &curr_std_vddc); + if (ret) + return ret; + + pwr_efficiency_ratio = si_calculate_power_efficiency_ratio(adev, + prev_std_vddc, curr_std_vddc); + + smc_state->levels[i].dpm2.MaxPS = (u8)((SISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk); + smc_state->levels[i].dpm2.NearTDPDec = SISLANDS_DPM2_NEAR_TDP_DEC; + smc_state->levels[i].dpm2.AboveSafeInc = SISLANDS_DPM2_ABOVE_SAFE_INC; + smc_state->levels[i].dpm2.BelowSafeInc = SISLANDS_DPM2_BELOW_SAFE_INC; + smc_state->levels[i].dpm2.PwrEfficiencyRatio = cpu_to_be16(pwr_efficiency_ratio); + } + + return 0; +} + +static int si_populate_sq_ramping_values(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + u32 sq_power_throttle, sq_power_throttle2; + bool enable_sq_ramping = ni_pi->enable_sq_ramping; + int i; + + if (state->performance_level_count == 0) + return -EINVAL; + + if (smc_state->levelCount != state->performance_level_count) + return -EINVAL; + + if (adev->pm.dpm.sq_ramping_threshold == 0) + return -EINVAL; + + if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER > (MAX_POWER_MASK >> MAX_POWER_SHIFT)) + enable_sq_ramping = false; + + if (SISLANDS_DPM2_SQ_RAMP_MIN_POWER > (MIN_POWER_MASK >> MIN_POWER_SHIFT)) + enable_sq_ramping = false; + + if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (MAX_POWER_DELTA_MASK >> MAX_POWER_DELTA_SHIFT)) + enable_sq_ramping = false; + + if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT)) + enable_sq_ramping = false; + + if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) + enable_sq_ramping = false; + + for (i = 0; i < state->performance_level_count; i++) { + sq_power_throttle = 0; + sq_power_throttle2 = 0; + + if ((state->performance_levels[i].sclk >= adev->pm.dpm.sq_ramping_threshold) && + enable_sq_ramping) { + sq_power_throttle |= MAX_POWER(SISLANDS_DPM2_SQ_RAMP_MAX_POWER); + sq_power_throttle |= MIN_POWER(SISLANDS_DPM2_SQ_RAMP_MIN_POWER); + sq_power_throttle2 |= MAX_POWER_DELTA(SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA); + sq_power_throttle2 |= STI_SIZE(SISLANDS_DPM2_SQ_RAMP_STI_SIZE); + sq_power_throttle2 |= LTI_RATIO(SISLANDS_DPM2_SQ_RAMP_LTI_RATIO); + } else { + sq_power_throttle |= MAX_POWER_MASK | MIN_POWER_MASK; + sq_power_throttle2 |= MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; + } + + smc_state->levels[i].SQPowerThrottle = cpu_to_be32(sq_power_throttle); + smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2); + } + + return 0; +} + +static int si_enable_power_containment(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + bool enable) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + PPSMC_Result smc_result; + int ret = 0; + + if (ni_pi->enable_power_containment) { + if (enable) { + if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) { + smc_result = si_send_msg_to_smc(adev, PPSMC_TDPClampingActive); + if (smc_result != PPSMC_Result_OK) { + ret = -EINVAL; + ni_pi->pc_enabled = false; + } else { + ni_pi->pc_enabled = true; + } + } + } else { + smc_result = si_send_msg_to_smc(adev, PPSMC_TDPClampingInactive); + if (smc_result != PPSMC_Result_OK) + ret = -EINVAL; + ni_pi->pc_enabled = false; + } + } + + return ret; +} + +static int si_initialize_smc_dte_tables(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + int ret = 0; + struct si_dte_data *dte_data = &si_pi->dte_data; + Smc_SIslands_DTE_Configuration *dte_tables = NULL; + u32 table_size; + u8 tdep_count; + u32 i; + + if (dte_data == NULL) + si_pi->enable_dte = false; + + if (si_pi->enable_dte == false) + return 0; + + if (dte_data->k <= 0) + return -EINVAL; + + dte_tables = kzalloc(sizeof(Smc_SIslands_DTE_Configuration), GFP_KERNEL); + if (dte_tables == NULL) { + si_pi->enable_dte = false; + return -ENOMEM; + } + + table_size = dte_data->k; + + if (table_size > SMC_SISLANDS_DTE_MAX_FILTER_STAGES) + table_size = SMC_SISLANDS_DTE_MAX_FILTER_STAGES; + + tdep_count = dte_data->tdep_count; + if (tdep_count > SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE) + tdep_count = SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; + + dte_tables->K = cpu_to_be32(table_size); + dte_tables->T0 = cpu_to_be32(dte_data->t0); + dte_tables->MaxT = cpu_to_be32(dte_data->max_t); + dte_tables->WindowSize = dte_data->window_size; + dte_tables->temp_select = dte_data->temp_select; + dte_tables->DTE_mode = dte_data->dte_mode; + dte_tables->Tthreshold = cpu_to_be32(dte_data->t_threshold); + + if (tdep_count > 0) + table_size--; + + for (i = 0; i < table_size; i++) { + dte_tables->tau[i] = cpu_to_be32(dte_data->tau[i]); + dte_tables->R[i] = cpu_to_be32(dte_data->r[i]); + } + + dte_tables->Tdep_count = tdep_count; + + for (i = 0; i < (u32)tdep_count; i++) { + dte_tables->T_limits[i] = dte_data->t_limits[i]; + dte_tables->Tdep_tau[i] = cpu_to_be32(dte_data->tdep_tau[i]); + dte_tables->Tdep_R[i] = cpu_to_be32(dte_data->tdep_r[i]); + } + + ret = si_copy_bytes_to_smc(adev, si_pi->dte_table_start, (u8 *)dte_tables, + sizeof(Smc_SIslands_DTE_Configuration), si_pi->sram_end); + kfree(dte_tables); + + return ret; +} + +static int si_get_cac_std_voltage_max_min(struct amdgpu_device *adev, + u16 *max, u16 *min) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct amdgpu_cac_leakage_table *table = + &adev->pm.dpm.dyn_state.cac_leakage_table; + u32 i; + u32 v0_loadline; + + + if (table == NULL) + return -EINVAL; + + *max = 0; + *min = 0xFFFF; + + for (i = 0; i < table->count; i++) { + if (table->entries[i].vddc > *max) + *max = table->entries[i].vddc; + if (table->entries[i].vddc < *min) + *min = table->entries[i].vddc; + } + + if (si_pi->powertune_data->lkge_lut_v0_percent > 100) + return -EINVAL; + + v0_loadline = (*min) * (100 - si_pi->powertune_data->lkge_lut_v0_percent) / 100; + + if (v0_loadline > 0xFFFFUL) + return -EINVAL; + + *min = (u16)v0_loadline; + + if ((*min > *max) || (*max == 0) || (*min == 0)) + return -EINVAL; + + return 0; +} + +static u16 si_get_cac_std_voltage_step(u16 max, u16 min) +{ + return ((max - min) + (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)) / + SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; +} + +static int si_init_dte_leakage_table(struct amdgpu_device *adev, + PP_SIslands_CacConfig *cac_tables, + u16 vddc_max, u16 vddc_min, u16 vddc_step, + u16 t0, u16 t_step) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 leakage; + unsigned int i, j; + s32 t; + u32 smc_leakage; + u32 scaling_factor; + u16 voltage; + + scaling_factor = si_get_smc_power_scaling_factor(adev); + + for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) { + t = (1000 * (i * t_step + t0)); + + for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) { + voltage = vddc_max - (vddc_step * j); + + si_calculate_leakage_for_v_and_t(adev, + &si_pi->powertune_data->leakage_coefficients, + voltage, + t, + si_pi->dyn_powertune_data.cac_leakage, + &leakage); + + smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4; + + if (smc_leakage > 0xFFFF) + smc_leakage = 0xFFFF; + + cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] = + cpu_to_be16((u16)smc_leakage); + } + } + return 0; +} + +static int si_init_simplified_leakage_table(struct amdgpu_device *adev, + PP_SIslands_CacConfig *cac_tables, + u16 vddc_max, u16 vddc_min, u16 vddc_step) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 leakage; + unsigned int i, j; + u32 smc_leakage; + u32 scaling_factor; + u16 voltage; + + scaling_factor = si_get_smc_power_scaling_factor(adev); + + for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) { + voltage = vddc_max - (vddc_step * j); + + si_calculate_leakage_for_v(adev, + &si_pi->powertune_data->leakage_coefficients, + si_pi->powertune_data->fixed_kt, + voltage, + si_pi->dyn_powertune_data.cac_leakage, + &leakage); + + smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4; + + if (smc_leakage > 0xFFFF) + smc_leakage = 0xFFFF; + + for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) + cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] = + cpu_to_be16((u16)smc_leakage); + } + return 0; +} + +static int si_initialize_smc_cac_tables(struct amdgpu_device *adev) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + PP_SIslands_CacConfig *cac_tables = NULL; + u16 vddc_max, vddc_min, vddc_step; + u16 t0, t_step; + u32 load_line_slope, reg; + int ret = 0; + u32 ticks_per_us = amdgpu_asic_get_xclk(adev) / 100; + + if (ni_pi->enable_cac == false) + return 0; + + cac_tables = kzalloc(sizeof(PP_SIslands_CacConfig), GFP_KERNEL); + if (!cac_tables) + return -ENOMEM; + + reg = RREG32(CG_CAC_CTRL) & ~CAC_WINDOW_MASK; + reg |= CAC_WINDOW(si_pi->powertune_data->cac_window); + WREG32(CG_CAC_CTRL, reg); + + si_pi->dyn_powertune_data.cac_leakage = adev->pm.dpm.cac_leakage; + si_pi->dyn_powertune_data.dc_pwr_value = + si_pi->powertune_data->dc_cac[NISLANDS_DCCAC_LEVEL_0]; + si_pi->dyn_powertune_data.wintime = si_calculate_cac_wintime(adev); + si_pi->dyn_powertune_data.shift_n = si_pi->powertune_data->shift_n_default; + + si_pi->dyn_powertune_data.leakage_minimum_temperature = 80 * 1000; + + ret = si_get_cac_std_voltage_max_min(adev, &vddc_max, &vddc_min); + if (ret) + goto done_free; + + vddc_step = si_get_cac_std_voltage_step(vddc_max, vddc_min); + vddc_min = vddc_max - (vddc_step * (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)); + t_step = 4; + t0 = 60; + + if (si_pi->enable_dte || ni_pi->driver_calculate_cac_leakage) + ret = si_init_dte_leakage_table(adev, cac_tables, + vddc_max, vddc_min, vddc_step, + t0, t_step); + else + ret = si_init_simplified_leakage_table(adev, cac_tables, + vddc_max, vddc_min, vddc_step); + if (ret) + goto done_free; + + load_line_slope = ((u32)adev->pm.dpm.load_line_slope << SMC_SISLANDS_SCALE_R) / 100; + + cac_tables->l2numWin_TDP = cpu_to_be32(si_pi->dyn_powertune_data.l2_lta_window_size); + cac_tables->lts_truncate_n = si_pi->dyn_powertune_data.lts_truncate; + cac_tables->SHIFT_N = si_pi->dyn_powertune_data.shift_n; + cac_tables->lkge_lut_V0 = cpu_to_be32((u32)vddc_min); + cac_tables->lkge_lut_Vstep = cpu_to_be32((u32)vddc_step); + cac_tables->R_LL = cpu_to_be32(load_line_slope); + cac_tables->WinTime = cpu_to_be32(si_pi->dyn_powertune_data.wintime); + cac_tables->calculation_repeats = cpu_to_be32(2); + cac_tables->dc_cac = cpu_to_be32(0); + cac_tables->log2_PG_LKG_SCALE = 12; + cac_tables->cac_temp = si_pi->powertune_data->operating_temp; + cac_tables->lkge_lut_T0 = cpu_to_be32((u32)t0); + cac_tables->lkge_lut_Tstep = cpu_to_be32((u32)t_step); + + ret = si_copy_bytes_to_smc(adev, si_pi->cac_table_start, (u8 *)cac_tables, + sizeof(PP_SIslands_CacConfig), si_pi->sram_end); + + if (ret) + goto done_free; + + ret = si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ticks_per_us, ticks_per_us); + +done_free: + if (ret) { + ni_pi->enable_cac = false; + ni_pi->enable_power_containment = false; + } + + kfree(cac_tables); + + return 0; +} + +static int si_program_cac_config_registers(struct amdgpu_device *adev, + const struct si_cac_config_reg *cac_config_regs) +{ + const struct si_cac_config_reg *config_regs = cac_config_regs; + u32 data = 0, offset; + + if (!config_regs) + return -EINVAL; + + while (config_regs->offset != 0xFFFFFFFF) { + switch (config_regs->type) { + case SISLANDS_CACCONFIG_CGIND: + offset = SMC_CG_IND_START + config_regs->offset; + if (offset < SMC_CG_IND_END) + data = RREG32_SMC(offset); + break; + default: + data = RREG32(config_regs->offset); + break; + } + + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + + switch (config_regs->type) { + case SISLANDS_CACCONFIG_CGIND: + offset = SMC_CG_IND_START + config_regs->offset; + if (offset < SMC_CG_IND_END) + WREG32_SMC(offset, data); + break; + default: + WREG32(config_regs->offset, data); + break; + } + config_regs++; + } + return 0; +} + +static int si_initialize_hardware_cac_manager(struct amdgpu_device *adev) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + int ret; + + if ((ni_pi->enable_cac == false) || + (ni_pi->cac_configuration_required == false)) + return 0; + + ret = si_program_cac_config_registers(adev, si_pi->lcac_config); + if (ret) + return ret; + ret = si_program_cac_config_registers(adev, si_pi->cac_override); + if (ret) + return ret; + ret = si_program_cac_config_registers(adev, si_pi->cac_weights); + if (ret) + return ret; + + return 0; +} + +static int si_enable_smc_cac(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + bool enable) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + PPSMC_Result smc_result; + int ret = 0; + + if (ni_pi->enable_cac) { + if (enable) { + if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) { + if (ni_pi->support_cac_long_term_average) { + smc_result = si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgEnable); + if (smc_result != PPSMC_Result_OK) + ni_pi->support_cac_long_term_average = false; + } + + smc_result = si_send_msg_to_smc(adev, PPSMC_MSG_EnableCac); + if (smc_result != PPSMC_Result_OK) { + ret = -EINVAL; + ni_pi->cac_enabled = false; + } else { + ni_pi->cac_enabled = true; + } + + if (si_pi->enable_dte) { + smc_result = si_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE); + if (smc_result != PPSMC_Result_OK) + ret = -EINVAL; + } + } + } else if (ni_pi->cac_enabled) { + if (si_pi->enable_dte) + smc_result = si_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE); + + smc_result = si_send_msg_to_smc(adev, PPSMC_MSG_DisableCac); + + ni_pi->cac_enabled = false; + + if (ni_pi->support_cac_long_term_average) + smc_result = si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgDisable); + } + } + return ret; +} + +static int si_init_smc_spll_table(struct amdgpu_device *adev) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + SMC_SISLANDS_SPLL_DIV_TABLE *spll_table; + SISLANDS_SMC_SCLK_VALUE sclk_params; + u32 fb_div, p_div; + u32 clk_s, clk_v; + u32 sclk = 0; + int ret = 0; + u32 tmp; + int i; + + if (si_pi->spll_table_start == 0) + return -EINVAL; + + spll_table = kzalloc(sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), GFP_KERNEL); + if (spll_table == NULL) + return -ENOMEM; + + for (i = 0; i < 256; i++) { + ret = si_calculate_sclk_params(adev, sclk, &sclk_params); + if (ret) + break; + p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & SPLL_PDIV_A_MASK) >> SPLL_PDIV_A_SHIFT; + fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT; + clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CLK_S_MASK) >> CLK_S_SHIFT; + clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CLK_V_MASK) >> CLK_V_SHIFT; + + fb_div &= ~0x00001FFF; + fb_div >>= 1; + clk_v >>= 6; + + if (p_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT)) + ret = -EINVAL; + if (fb_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT)) + ret = -EINVAL; + if (clk_s & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT)) + ret = -EINVAL; + if (clk_v & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT)) + ret = -EINVAL; + + if (ret) + break; + + tmp = ((fb_div << SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) | + ((p_div << SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK); + spll_table->freq[i] = cpu_to_be32(tmp); + + tmp = ((clk_v << SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK) | + ((clk_s << SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK); + spll_table->ss[i] = cpu_to_be32(tmp); + + sclk += 512; + } + + + if (!ret) + ret = si_copy_bytes_to_smc(adev, si_pi->spll_table_start, + (u8 *)spll_table, sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), + si_pi->sram_end); + + if (ret) + ni_pi->enable_power_containment = false; + + kfree(spll_table); + + return ret; +} + +struct si_dpm_quirk { + u32 chip_vendor; + u32 chip_device; + u32 subsys_vendor; + u32 subsys_device; + u32 max_sclk; + u32 max_mclk; +}; + +/* cards with dpm stability problems */ +static struct si_dpm_quirk si_dpm_quirk_list[] = { + /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ + { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 }, + { PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 }, + { 0, 0, 0, 0 }, +}; + +static u16 si_get_lower_of_leakage_and_vce_voltage(struct amdgpu_device *adev, + u16 vce_voltage) +{ + u16 highest_leakage = 0; + struct si_power_info *si_pi = si_get_pi(adev); + int i; + + for (i = 0; i < si_pi->leakage_voltage.count; i++){ + if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage) + highest_leakage = si_pi->leakage_voltage.entries[i].voltage; + } + + if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage)) + return highest_leakage; + + return vce_voltage; +} + +static int si_get_vce_clock_voltage(struct amdgpu_device *adev, + u32 evclk, u32 ecclk, u16 *voltage) +{ + u32 i; + int ret = -EINVAL; + struct amdgpu_vce_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + + if (((evclk == 0) && (ecclk == 0)) || + (table && (table->count == 0))) { + *voltage = 0; + return 0; + } + + for (i = 0; i < table->count; i++) { + if ((evclk <= table->entries[i].evclk) && + (ecclk <= table->entries[i].ecclk)) { + *voltage = table->entries[i].v; + ret = 0; + break; + } + } + + /* if no match return the highest voltage */ + if (ret) + *voltage = table->entries[table->count - 1].v; + + *voltage = si_get_lower_of_leakage_and_vce_voltage(adev, *voltage); + + return ret; +} + +static bool si_dpm_vblank_too_short(struct amdgpu_device *adev) +{ + + u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); + /* we never hit the non-gddr5 limit so disable it */ + u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0; + + if (vblank_time < switch_limit) + return true; + else + return false; + +} + +static int ni_copy_and_switch_arb_sets(struct amdgpu_device *adev, + u32 arb_freq_src, u32 arb_freq_dest) +{ + u32 mc_arb_dram_timing; + u32 mc_arb_dram_timing2; + u32 burst_time; + u32 mc_cg_config; + + switch (arb_freq_src) { + case MC_CG_ARB_FREQ_F0: + mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING); + mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); + burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT; + break; + case MC_CG_ARB_FREQ_F1: + mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_1); + mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1); + burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT; + break; + case MC_CG_ARB_FREQ_F2: + mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_2); + mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2); + burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT; + break; + case MC_CG_ARB_FREQ_F3: + mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_3); + mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3); + burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT; + break; + default: + return -EINVAL; + } + + switch (arb_freq_dest) { + case MC_CG_ARB_FREQ_F0: + WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing); + WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); + WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK); + break; + case MC_CG_ARB_FREQ_F1: + WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); + WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); + WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK); + break; + case MC_CG_ARB_FREQ_F2: + WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing); + WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2); + WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK); + break; + case MC_CG_ARB_FREQ_F3: + WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing); + WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2); + WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK); + break; + default: + return -EINVAL; + } + + mc_cg_config = RREG32(MC_CG_CONFIG) | 0x0000000F; + WREG32(MC_CG_CONFIG, mc_cg_config); + WREG32_P(MC_ARB_CG, CG_ARB_REQ(arb_freq_dest), ~CG_ARB_REQ_MASK); + + return 0; +} + +static void ni_update_current_ps(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct si_ps *new_ps = si_get_ps(rps); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); + + eg_pi->current_rps = *rps; + ni_pi->current_ps = *new_ps; + eg_pi->current_rps.ps_priv = &ni_pi->current_ps; +} + +static void ni_update_requested_ps(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct si_ps *new_ps = si_get_ps(rps); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); + + eg_pi->requested_rps = *rps; + ni_pi->requested_ps = *new_ps; + eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps; +} + +static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev, + struct amdgpu_ps *new_ps, + struct amdgpu_ps *old_ps) +{ + struct si_ps *new_state = si_get_ps(new_ps); + struct si_ps *current_state = si_get_ps(old_ps); + + if ((new_ps->vclk == old_ps->vclk) && + (new_ps->dclk == old_ps->dclk)) + return; + + if (new_state->performance_levels[new_state->performance_level_count - 1].sclk >= + current_state->performance_levels[current_state->performance_level_count - 1].sclk) + return; + + amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk); +} + +static void ni_set_uvd_clock_after_set_eng_clock(struct amdgpu_device *adev, + struct amdgpu_ps *new_ps, + struct amdgpu_ps *old_ps) +{ + struct si_ps *new_state = si_get_ps(new_ps); + struct si_ps *current_state = si_get_ps(old_ps); + + if ((new_ps->vclk == old_ps->vclk) && + (new_ps->dclk == old_ps->dclk)) + return; + + if (new_state->performance_levels[new_state->performance_level_count - 1].sclk < + current_state->performance_levels[current_state->performance_level_count - 1].sclk) + return; + + amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk); +} + +static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage) +{ + unsigned int i; + + for (i = 0; i < table->count; i++) { + if (voltage <= table->entries[i].value) + return table->entries[i].value; + } + + return table->entries[table->count - 1].value; +} + +static u32 btc_find_valid_clock(struct amdgpu_clock_array *clocks, + u32 max_clock, u32 requested_clock) +{ + unsigned int i; + + if ((clocks == NULL) || (clocks->count == 0)) + return (requested_clock < max_clock) ? requested_clock : max_clock; + + for (i = 0; i < clocks->count; i++) { + if (clocks->values[i] >= requested_clock) + return (clocks->values[i] < max_clock) ? clocks->values[i] : max_clock; + } + + return (clocks->values[clocks->count - 1] < max_clock) ? + clocks->values[clocks->count - 1] : max_clock; +} + +static u32 btc_get_valid_mclk(struct amdgpu_device *adev, + u32 max_mclk, u32 requested_mclk) +{ + return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_mclk_values, + max_mclk, requested_mclk); +} + +static u32 btc_get_valid_sclk(struct amdgpu_device *adev, + u32 max_sclk, u32 requested_sclk) +{ + return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_sclk_values, + max_sclk, requested_sclk); +} + +void btc_get_max_clock_from_voltage_dependency_table(struct amdgpu_clock_voltage_dependency_table *table, + u32 *max_clock) +{ + u32 i, clock = 0; + + if ((table == NULL) || (table->count == 0)) { + *max_clock = clock; + return; + } + + for (i = 0; i < table->count; i++) { + if (clock < table->entries[i].clk) + clock = table->entries[i].clk; + } + *max_clock = clock; +} + +static void btc_apply_voltage_dependency_rules(struct amdgpu_clock_voltage_dependency_table *table, + u32 clock, u16 max_voltage, u16 *voltage) +{ + u32 i; + + if ((table == NULL) || (table->count == 0)) + return; + + for (i= 0; i < table->count; i++) { + if (clock <= table->entries[i].clk) { + if (*voltage < table->entries[i].v) + *voltage = (u16)((table->entries[i].v < max_voltage) ? + table->entries[i].v : max_voltage); + return; + } + } + + *voltage = (*voltage > max_voltage) ? *voltage : max_voltage; +} + +static void btc_adjust_clock_combinations(struct amdgpu_device *adev, + const struct amdgpu_clock_and_voltage_limits *max_limits, + struct rv7xx_pl *pl) +{ + + if ((pl->mclk == 0) || (pl->sclk == 0)) + return; + + if (pl->mclk == pl->sclk) + return; + + if (pl->mclk > pl->sclk) { + if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > adev->pm.dpm.dyn_state.mclk_sclk_ratio) + pl->sclk = btc_get_valid_sclk(adev, + max_limits->sclk, + (pl->mclk + + (adev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) / + adev->pm.dpm.dyn_state.mclk_sclk_ratio); + } else { + if ((pl->sclk - pl->mclk) > adev->pm.dpm.dyn_state.sclk_mclk_delta) + pl->mclk = btc_get_valid_mclk(adev, + max_limits->mclk, + pl->sclk - + adev->pm.dpm.dyn_state.sclk_mclk_delta); + } +} + +static void btc_apply_voltage_delta_rules(struct amdgpu_device *adev, + u16 max_vddc, u16 max_vddci, + u16 *vddc, u16 *vddci) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + u16 new_voltage; + + if ((0 == *vddc) || (0 == *vddci)) + return; + + if (*vddc > *vddci) { + if ((*vddc - *vddci) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { + new_voltage = btc_find_voltage(&eg_pi->vddci_voltage_table, + (*vddc - adev->pm.dpm.dyn_state.vddc_vddci_delta)); + *vddci = (new_voltage < max_vddci) ? new_voltage : max_vddci; + } + } else { + if ((*vddci - *vddc) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { + new_voltage = btc_find_voltage(&eg_pi->vddc_voltage_table, + (*vddci - adev->pm.dpm.dyn_state.vddc_vddci_delta)); + *vddc = (new_voltage < max_vddc) ? new_voltage : max_vddc; + } + } +} + +static enum amdgpu_pcie_gen r600_get_pcie_gen_support(struct amdgpu_device *adev, + u32 sys_mask, + enum amdgpu_pcie_gen asic_gen, + enum amdgpu_pcie_gen default_gen) +{ + switch (asic_gen) { + case AMDGPU_PCIE_GEN1: + return AMDGPU_PCIE_GEN1; + case AMDGPU_PCIE_GEN2: + return AMDGPU_PCIE_GEN2; + case AMDGPU_PCIE_GEN3: + return AMDGPU_PCIE_GEN3; + default: + if ((sys_mask & DRM_PCIE_SPEED_80) && (default_gen == AMDGPU_PCIE_GEN3)) + return AMDGPU_PCIE_GEN3; + else if ((sys_mask & DRM_PCIE_SPEED_50) && (default_gen == AMDGPU_PCIE_GEN2)) + return AMDGPU_PCIE_GEN2; + else + return AMDGPU_PCIE_GEN1; + } + return AMDGPU_PCIE_GEN1; +} + +static void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, + u32 *p, u32 *u) +{ + u32 b_c = 0; + u32 i_c; + u32 tmp; + + i_c = (i * r_c) / 100; + tmp = i_c >> p_b; + + while (tmp) { + b_c++; + tmp >>= 1; + } + + *u = (b_c + 1) / 2; + *p = i_c / (1 << (2 * (*u))); +} + +static int r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th) +{ + u32 k, a, ah, al; + u32 t1; + + if ((fl == 0) || (fh == 0) || (fl > fh)) + return -EINVAL; + + k = (100 * fh) / fl; + t1 = (t * (k - 100)); + a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100)); + a = (a + 5) / 10; + ah = ((a * t) + 5000) / 10000; + al = a - ah; + + *th = t - ah; + *tl = t + al; + + return 0; +} + +static bool r600_is_uvd_state(u32 class, u32 class2) +{ + if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + return true; + if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + return true; + if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + return true; + if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + return true; + if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + return true; + return false; +} + +static u8 rv770_get_memory_module_index(struct amdgpu_device *adev) +{ + return (u8) ((RREG32(BIOS_SCRATCH_4) >> 16) & 0xff); +} + +static void rv770_get_max_vddc(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + u16 vddc; + + if (amdgpu_atombios_get_max_vddc(adev, 0, 0, &vddc)) + pi->max_vddc = 0; + else + pi->max_vddc = vddc; +} + +static void rv770_get_engine_memory_ss(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct amdgpu_atom_ss ss; + + pi->sclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss, + ASIC_INTERNAL_ENGINE_SS, 0); + pi->mclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss, + ASIC_INTERNAL_MEMORY_SS, 0); + + if (pi->sclk_ss || pi->mclk_ss) + pi->dynamic_ss = true; + else + pi->dynamic_ss = false; +} + + +static void si_apply_state_adjust_rules(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct si_ps *ps = si_get_ps(rps); + struct amdgpu_clock_and_voltage_limits *max_limits; + bool disable_mclk_switching = false; + bool disable_sclk_switching = false; + u32 mclk, sclk; + u16 vddc, vddci, min_vce_voltage = 0; + u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; + u32 max_sclk = 0, max_mclk = 0; + int i; + struct si_dpm_quirk *p = si_dpm_quirk_list; + + /* Apply dpm quirks */ + while (p && p->chip_device != 0) { + if (adev->pdev->vendor == p->chip_vendor && + adev->pdev->device == p->chip_device && + adev->pdev->subsystem_vendor == p->subsys_vendor && + adev->pdev->subsystem_device == p->subsys_device) { + max_sclk = p->max_sclk; + max_mclk = p->max_mclk; + break; + } + ++p; + } + + if (rps->vce_active) { + rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; + rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk; + si_get_vce_clock_voltage(adev, rps->evclk, rps->ecclk, + &min_vce_voltage); + } else { + rps->evclk = 0; + rps->ecclk = 0; + } + + if ((adev->pm.dpm.new_active_crtc_count > 1) || + si_dpm_vblank_too_short(adev)) + disable_mclk_switching = true; + + if (rps->vclk || rps->dclk) { + disable_mclk_switching = true; + disable_sclk_switching = true; + } + + if (adev->pm.dpm.ac_power) + max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; + else + max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc; + + for (i = ps->performance_level_count - 2; i >= 0; i--) { + if (ps->performance_levels[i].vddc > ps->performance_levels[i+1].vddc) + ps->performance_levels[i].vddc = ps->performance_levels[i+1].vddc; + } + if (adev->pm.dpm.ac_power == false) { + for (i = 0; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].mclk > max_limits->mclk) + ps->performance_levels[i].mclk = max_limits->mclk; + if (ps->performance_levels[i].sclk > max_limits->sclk) + ps->performance_levels[i].sclk = max_limits->sclk; + if (ps->performance_levels[i].vddc > max_limits->vddc) + ps->performance_levels[i].vddc = max_limits->vddc; + if (ps->performance_levels[i].vddci > max_limits->vddci) + ps->performance_levels[i].vddci = max_limits->vddci; + } + } + + /* limit clocks to max supported clocks based on voltage dependency tables */ + btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, + &max_sclk_vddc); + btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, + &max_mclk_vddci); + btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, + &max_mclk_vddc); + + for (i = 0; i < ps->performance_level_count; i++) { + if (max_sclk_vddc) { + if (ps->performance_levels[i].sclk > max_sclk_vddc) + ps->performance_levels[i].sclk = max_sclk_vddc; + } + if (max_mclk_vddci) { + if (ps->performance_levels[i].mclk > max_mclk_vddci) + ps->performance_levels[i].mclk = max_mclk_vddci; + } + if (max_mclk_vddc) { + if (ps->performance_levels[i].mclk > max_mclk_vddc) + ps->performance_levels[i].mclk = max_mclk_vddc; + } + if (max_mclk) { + if (ps->performance_levels[i].mclk > max_mclk) + ps->performance_levels[i].mclk = max_mclk; + } + if (max_sclk) { + if (ps->performance_levels[i].sclk > max_sclk) + ps->performance_levels[i].sclk = max_sclk; + } + } + + /* XXX validate the min clocks required for display */ + + if (disable_mclk_switching) { + mclk = ps->performance_levels[ps->performance_level_count - 1].mclk; + vddci = ps->performance_levels[ps->performance_level_count - 1].vddci; + } else { + mclk = ps->performance_levels[0].mclk; + vddci = ps->performance_levels[0].vddci; + } + + if (disable_sclk_switching) { + sclk = ps->performance_levels[ps->performance_level_count - 1].sclk; + vddc = ps->performance_levels[ps->performance_level_count - 1].vddc; + } else { + sclk = ps->performance_levels[0].sclk; + vddc = ps->performance_levels[0].vddc; + } + + if (rps->vce_active) { + if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk) + sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk; + if (mclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk) + mclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk; + } + + /* adjusted low state */ + ps->performance_levels[0].sclk = sclk; + ps->performance_levels[0].mclk = mclk; + ps->performance_levels[0].vddc = vddc; + ps->performance_levels[0].vddci = vddci; + + if (disable_sclk_switching) { + sclk = ps->performance_levels[0].sclk; + for (i = 1; i < ps->performance_level_count; i++) { + if (sclk < ps->performance_levels[i].sclk) + sclk = ps->performance_levels[i].sclk; + } + for (i = 0; i < ps->performance_level_count; i++) { + ps->performance_levels[i].sclk = sclk; + ps->performance_levels[i].vddc = vddc; + } + } else { + for (i = 1; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk) + ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk; + if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc) + ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc; + } + } + + if (disable_mclk_switching) { + mclk = ps->performance_levels[0].mclk; + for (i = 1; i < ps->performance_level_count; i++) { + if (mclk < ps->performance_levels[i].mclk) + mclk = ps->performance_levels[i].mclk; + } + for (i = 0; i < ps->performance_level_count; i++) { + ps->performance_levels[i].mclk = mclk; + ps->performance_levels[i].vddci = vddci; + } + } else { + for (i = 1; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk) + ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk; + if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci) + ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci; + } + } + + for (i = 0; i < ps->performance_level_count; i++) + btc_adjust_clock_combinations(adev, max_limits, + &ps->performance_levels[i]); + + for (i = 0; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].vddc < min_vce_voltage) + ps->performance_levels[i].vddc = min_vce_voltage; + btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, + ps->performance_levels[i].sclk, + max_limits->vddc, &ps->performance_levels[i].vddc); + btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, + ps->performance_levels[i].mclk, + max_limits->vddci, &ps->performance_levels[i].vddci); + btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, + ps->performance_levels[i].mclk, + max_limits->vddc, &ps->performance_levels[i].vddc); + btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk, + adev->clock.current_dispclk, + max_limits->vddc, &ps->performance_levels[i].vddc); + } + + for (i = 0; i < ps->performance_level_count; i++) { + btc_apply_voltage_delta_rules(adev, + max_limits->vddc, max_limits->vddci, + &ps->performance_levels[i].vddc, + &ps->performance_levels[i].vddci); + } + + ps->dc_compatible = true; + for (i = 0; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].vddc > adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc) + ps->dc_compatible = false; + } +} + +#if 0 +static int si_read_smc_soft_register(struct amdgpu_device *adev, + u16 reg_offset, u32 *value) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + return si_read_smc_sram_dword(adev, + si_pi->soft_regs_start + reg_offset, value, + si_pi->sram_end); +} +#endif + +static int si_write_smc_soft_register(struct amdgpu_device *adev, + u16 reg_offset, u32 value) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + return si_write_smc_sram_dword(adev, + si_pi->soft_regs_start + reg_offset, + value, si_pi->sram_end); +} + +static bool si_is_special_1gb_platform(struct amdgpu_device *adev) +{ + bool ret = false; + u32 tmp, width, row, column, bank, density; + bool is_memory_gddr5, is_special; + + tmp = RREG32(MC_SEQ_MISC0); + is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE == ((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT)); + is_special = (MC_SEQ_MISC0_REV_ID_VALUE == ((tmp & MC_SEQ_MISC0_REV_ID_MASK) >> MC_SEQ_MISC0_REV_ID_SHIFT)) + & (MC_SEQ_MISC0_VEN_ID_VALUE == ((tmp & MC_SEQ_MISC0_VEN_ID_MASK) >> MC_SEQ_MISC0_VEN_ID_SHIFT)); + + WREG32(MC_SEQ_IO_DEBUG_INDEX, 0xb); + width = ((RREG32(MC_SEQ_IO_DEBUG_DATA) >> 1) & 1) ? 16 : 32; + + tmp = RREG32(MC_ARB_RAMCFG); + row = ((tmp & NOOFROWS_MASK) >> NOOFROWS_SHIFT) + 10; + column = ((tmp & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT) + 8; + bank = ((tmp & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + 2; + + density = (1 << (row + column - 20 + bank)) * width; + + if ((adev->pdev->device == 0x6819) && + is_memory_gddr5 && is_special && (density == 0x400)) + ret = true; + + return ret; +} + +static void si_get_leakage_vddc(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u16 vddc, count = 0; + int i, ret; + + for (i = 0; i < SISLANDS_MAX_LEAKAGE_COUNT; i++) { + ret = amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(adev, &vddc, SISLANDS_LEAKAGE_INDEX0 + i); + + if (!ret && (vddc > 0) && (vddc != (SISLANDS_LEAKAGE_INDEX0 + i))) { + si_pi->leakage_voltage.entries[count].voltage = vddc; + si_pi->leakage_voltage.entries[count].leakage_index = + SISLANDS_LEAKAGE_INDEX0 + i; + count++; + } + } + si_pi->leakage_voltage.count = count; +} + +static int si_get_leakage_voltage_from_leakage_index(struct amdgpu_device *adev, + u32 index, u16 *leakage_voltage) +{ + struct si_power_info *si_pi = si_get_pi(adev); + int i; + + if (leakage_voltage == NULL) + return -EINVAL; + + if ((index & 0xff00) != 0xff00) + return -EINVAL; + + if ((index & 0xff) > SISLANDS_MAX_LEAKAGE_COUNT + 1) + return -EINVAL; + + if (index < SISLANDS_LEAKAGE_INDEX0) + return -EINVAL; + + for (i = 0; i < si_pi->leakage_voltage.count; i++) { + if (si_pi->leakage_voltage.entries[i].leakage_index == index) { + *leakage_voltage = si_pi->leakage_voltage.entries[i].voltage; + return 0; + } + } + return -EAGAIN; +} + +static void si_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + bool want_thermal_protection; + enum amdgpu_dpm_event_src dpm_event_src; + + switch (sources) { + case 0: + default: + want_thermal_protection = false; + break; + case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL): + want_thermal_protection = true; + dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGITAL; + break; + case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL): + want_thermal_protection = true; + dpm_event_src = AMDGPU_DPM_EVENT_SRC_EXTERNAL; + break; + case ((1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL) | + (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL)): + want_thermal_protection = true; + dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL; + break; + } + + if (want_thermal_protection) { + WREG32_P(CG_THERMAL_CTRL, DPM_EVENT_SRC(dpm_event_src), ~DPM_EVENT_SRC_MASK); + if (pi->thermal_protection) + WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); + } else { + WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); + } +} + +static void si_enable_auto_throttle_source(struct amdgpu_device *adev, + enum amdgpu_dpm_auto_throttle_src source, + bool enable) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + + if (enable) { + if (!(pi->active_auto_throttle_sources & (1 << source))) { + pi->active_auto_throttle_sources |= 1 << source; + si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources); + } + } else { + if (pi->active_auto_throttle_sources & (1 << source)) { + pi->active_auto_throttle_sources &= ~(1 << source); + si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources); + } + } +} + +static void si_start_dpm(struct amdgpu_device *adev) +{ + WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); +} + +static void si_stop_dpm(struct amdgpu_device *adev) +{ + WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); +} + +static void si_enable_sclk_control(struct amdgpu_device *adev, bool enable) +{ + if (enable) + WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); + else + WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); + +} + +#if 0 +static int si_notify_hardware_of_thermal_state(struct amdgpu_device *adev, + u32 thermal_level) +{ + PPSMC_Result ret; + + if (thermal_level == 0) { + ret = si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); + if (ret == PPSMC_Result_OK) + return 0; + else + return -EINVAL; + } + return 0; +} + +static void si_notify_hardware_vpu_recovery_event(struct amdgpu_device *adev) +{ + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen, true); +} +#endif + +#if 0 +static int si_notify_hw_of_powersource(struct amdgpu_device *adev, bool ac_power) +{ + if (ac_power) + return (si_send_msg_to_smc(adev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ? + 0 : -EINVAL; + + return 0; +} +#endif + +static PPSMC_Result si_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, + PPSMC_Msg msg, u32 parameter) +{ + WREG32(SMC_SCRATCH0, parameter); + return si_send_msg_to_smc(adev, msg); +} + +static int si_restrict_performance_levels_before_switch(struct amdgpu_device *adev) +{ + if (si_send_msg_to_smc(adev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK) + return -EINVAL; + + return (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static int si_dpm_force_performance_level(struct amdgpu_device *adev, + enum amdgpu_dpm_forced_level level) +{ + struct amdgpu_ps *rps = adev->pm.dpm.current_ps; + struct si_ps *ps = si_get_ps(rps); + u32 levels = ps->performance_level_count; + + if (level == AMDGPU_DPM_FORCED_LEVEL_HIGH) { + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK) + return -EINVAL; + + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK) + return -EINVAL; + } else if (level == AMDGPU_DPM_FORCED_LEVEL_LOW) { + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK) + return -EINVAL; + + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK) + return -EINVAL; + } else if (level == AMDGPU_DPM_FORCED_LEVEL_AUTO) { + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK) + return -EINVAL; + + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK) + return -EINVAL; + } + + adev->pm.dpm.forced_level = level; + + return 0; +} + +#if 0 +static int si_set_boot_state(struct amdgpu_device *adev) +{ + return (si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} +#endif + +static int si_set_sw_state(struct amdgpu_device *adev) +{ + return (si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static int si_halt_smc(struct amdgpu_device *adev) +{ + if (si_send_msg_to_smc(adev, PPSMC_MSG_Halt) != PPSMC_Result_OK) + return -EINVAL; + + return (si_wait_for_smc_inactive(adev) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static int si_resume_smc(struct amdgpu_device *adev) +{ + if (si_send_msg_to_smc(adev, PPSMC_FlushDataCache) != PPSMC_Result_OK) + return -EINVAL; + + return (si_send_msg_to_smc(adev, PPSMC_MSG_Resume) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static void si_dpm_start_smc(struct amdgpu_device *adev) +{ + si_program_jump_on_start(adev); + si_start_smc(adev); + si_start_smc_clock(adev); +} + +static void si_dpm_stop_smc(struct amdgpu_device *adev) +{ + si_reset_smc(adev); + si_stop_smc_clock(adev); +} + +static int si_process_firmware_header(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + int ret; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_stateTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->state_table_start = tmp; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_softRegisters, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->soft_regs_start = tmp; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->mc_reg_table_start = tmp; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_fanTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->fan_table_start = tmp; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->arb_table_start = tmp; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->cac_table_start = tmp; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->dte_table_start = tmp; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_spllTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->spll_table_start = tmp; + + ret = si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->papm_cfg_table_start = tmp; + + return ret; +} + +static void si_read_clock_registers(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + si_pi->clock_registers.cg_spll_func_cntl = RREG32(CG_SPLL_FUNC_CNTL); + si_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(CG_SPLL_FUNC_CNTL_2); + si_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(CG_SPLL_FUNC_CNTL_3); + si_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(CG_SPLL_FUNC_CNTL_4); + si_pi->clock_registers.cg_spll_spread_spectrum = RREG32(CG_SPLL_SPREAD_SPECTRUM); + si_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(CG_SPLL_SPREAD_SPECTRUM_2); + si_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL); + si_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL); + si_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL); + si_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL); + si_pi->clock_registers.mpll_func_cntl = RREG32(MPLL_FUNC_CNTL); + si_pi->clock_registers.mpll_func_cntl_1 = RREG32(MPLL_FUNC_CNTL_1); + si_pi->clock_registers.mpll_func_cntl_2 = RREG32(MPLL_FUNC_CNTL_2); + si_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1); + si_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2); +} + +static void si_enable_thermal_protection(struct amdgpu_device *adev, + bool enable) +{ + if (enable) + WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); + else + WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); +} + +static void si_enable_acpi_power_management(struct amdgpu_device *adev) +{ + WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN); +} + +#if 0 +static int si_enter_ulp_state(struct amdgpu_device *adev) +{ + WREG32(SMC_MESSAGE_0, PPSMC_MSG_SwitchToMinimumPower); + + udelay(25000); + + return 0; +} + +static int si_exit_ulp_state(struct amdgpu_device *adev) +{ + int i; + + WREG32(SMC_MESSAGE_0, PPSMC_MSG_ResumeFromMinimumPower); + + udelay(7000); + + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(SMC_RESP_0) == 1) + break; + udelay(1000); + } + + return 0; +} +#endif + +static int si_notify_smc_display_change(struct amdgpu_device *adev, + bool has_display) +{ + PPSMC_Msg msg = has_display ? + PPSMC_MSG_HasDisplay : PPSMC_MSG_NoDisplay; + + return (si_send_msg_to_smc(adev, msg) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static void si_program_response_times(struct amdgpu_device *adev) +{ + u32 voltage_response_time, backbias_response_time, acpi_delay_time, vbi_time_out; + u32 vddc_dly, acpi_dly, vbi_dly; + u32 reference_clock; + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mvdd_chg_time, 1); + + voltage_response_time = (u32)adev->pm.dpm.voltage_response_time; + backbias_response_time = (u32)adev->pm.dpm.backbias_response_time; + + if (voltage_response_time == 0) + voltage_response_time = 1000; + + acpi_delay_time = 15000; + vbi_time_out = 100000; + + reference_clock = amdgpu_asic_get_xclk(adev); + + vddc_dly = (voltage_response_time * reference_clock) / 100; + acpi_dly = (acpi_delay_time * reference_clock) / 100; + vbi_dly = (vbi_time_out * reference_clock) / 100; + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_vreg, vddc_dly); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_acpi, acpi_dly); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA); +} + +static void si_program_ds_registers(struct amdgpu_device *adev) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + u32 tmp; + + /* DEEP_SLEEP_CLK_SEL field should be 0x10 on tahiti A0 */ + if (adev->asic_type == CHIP_TAHITI && adev->rev_id == 0x0) + tmp = 0x10; + else + tmp = 0x1; + + if (eg_pi->sclk_deep_sleep) { + WREG32_P(MISC_CLK_CNTL, DEEP_SLEEP_CLK_SEL(tmp), ~DEEP_SLEEP_CLK_SEL_MASK); + WREG32_P(CG_SPLL_AUTOSCALE_CNTL, AUTOSCALE_ON_SS_CLEAR, + ~AUTOSCALE_ON_SS_CLEAR); + } +} + +static void si_program_display_gap(struct amdgpu_device *adev) +{ + u32 tmp, pipe; + int i; + + tmp = RREG32(CG_DISPLAY_GAP_CNTL) & ~(DISP1_GAP_MASK | DISP2_GAP_MASK); + if (adev->pm.dpm.new_active_crtc_count > 0) + tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM); + else + tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE); + + if (adev->pm.dpm.new_active_crtc_count > 1) + tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM); + else + tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE); + + WREG32(CG_DISPLAY_GAP_CNTL, tmp); + + tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG); + pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> DCCG_DISP1_SLOW_SELECT_SHIFT; + + if ((adev->pm.dpm.new_active_crtc_count > 0) && + (!(adev->pm.dpm.new_active_crtcs & (1 << pipe)))) { + /* find the first active crtc */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (adev->pm.dpm.new_active_crtcs & (1 << i)) + break; + } + if (i == adev->mode_info.num_crtc) + pipe = 0; + else + pipe = i; + + tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK; + tmp |= DCCG_DISP1_SLOW_SELECT(pipe); + WREG32(DCCG_DISP_SLOW_SELECT_REG, tmp); + } + + /* Setting this to false forces the performance state to low if the crtcs are disabled. + * This can be a problem on PowerXpress systems or if you want to use the card + * for offscreen rendering or compute if there are no crtcs enabled. + */ + si_notify_smc_display_change(adev, adev->pm.dpm.new_active_crtc_count > 0); +} + +static void si_enable_spread_spectrum(struct amdgpu_device *adev, bool enable) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + + if (enable) { + if (pi->sclk_ss) + WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN); + } else { + WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN); + WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN); + } +} + +static void si_setup_bsp(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + u32 xclk = amdgpu_asic_get_xclk(adev); + + r600_calculate_u_and_p(pi->asi, + xclk, + 16, + &pi->bsp, + &pi->bsu); + + r600_calculate_u_and_p(pi->pasi, + xclk, + 16, + &pi->pbsp, + &pi->pbsu); + + + pi->dsp = BSP(pi->bsp) | BSU(pi->bsu); + pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu); + + WREG32(CG_BSP, pi->dsp); +} + +static void si_program_git(struct amdgpu_device *adev) +{ + WREG32_P(CG_GIT, CG_GICST(R600_GICST_DFLT), ~CG_GICST_MASK); +} + +static void si_program_tp(struct amdgpu_device *adev) +{ + int i; + enum r600_td td = R600_TD_DFLT; + + for (i = 0; i < R600_PM_NUMBER_OF_TC; i++) + WREG32(CG_FFCT_0 + i, (UTC_0(r600_utc[i]) | DTC_0(r600_dtc[i]))); + + if (td == R600_TD_AUTO) + WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL); + else + WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL); + + if (td == R600_TD_UP) + WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE); + + if (td == R600_TD_DOWN) + WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE); +} + +static void si_program_tpp(struct amdgpu_device *adev) +{ + WREG32(CG_TPC, R600_TPC_DFLT); +} + +static void si_program_sstp(struct amdgpu_device *adev) +{ + WREG32(CG_SSP, (SSTU(R600_SSTU_DFLT) | SST(R600_SST_DFLT))); +} + +static void si_enable_display_gap(struct amdgpu_device *adev) +{ + u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL); + + tmp &= ~(DISP1_GAP_MASK | DISP2_GAP_MASK); + tmp |= (DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE) | + DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE)); + + tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK); + tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK) | + DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE)); + WREG32(CG_DISPLAY_GAP_CNTL, tmp); +} + +static void si_program_vc(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + + WREG32(CG_FTV, pi->vrc); +} + +static void si_clear_vc(struct amdgpu_device *adev) +{ + WREG32(CG_FTV, 0); +} + +u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock) +{ + u8 mc_para_index; + + if (memory_clock < 10000) + mc_para_index = 0; + else if (memory_clock >= 80000) + mc_para_index = 0x0f; + else + mc_para_index = (u8)((memory_clock - 10000) / 5000 + 1); + return mc_para_index; +} + +u8 si_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode) +{ + u8 mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) + mc_para_index = 0x00; + else if (memory_clock > 47500) + mc_para_index = 0x0f; + else + mc_para_index = (u8)((memory_clock - 10000) / 2500); + } else { + if (memory_clock < 65000) + mc_para_index = 0x00; + else if (memory_clock > 135000) + mc_para_index = 0x0f; + else + mc_para_index = (u8)((memory_clock - 60000) / 5000); + } + return mc_para_index; +} + +static u8 si_get_strobe_mode_settings(struct amdgpu_device *adev, u32 mclk) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + bool strobe_mode = false; + u8 result = 0; + + if (mclk <= pi->mclk_strobe_mode_threshold) + strobe_mode = true; + + if (adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) + result = si_get_mclk_frequency_ratio(mclk, strobe_mode); + else + result = si_get_ddr3_mclk_frequency_ratio(mclk); + + if (strobe_mode) + result |= SISLANDS_SMC_STROBE_ENABLE; + + return result; +} + +static int si_upload_firmware(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + int ret; + + si_reset_smc(adev); + si_stop_smc_clock(adev); + + ret = si_load_smc_ucode(adev, si_pi->sram_end); + + return ret; +} + +static bool si_validate_phase_shedding_tables(struct amdgpu_device *adev, + const struct atom_voltage_table *table, + const struct amdgpu_phase_shedding_limits_table *limits) +{ + u32 data, num_bits, num_levels; + + if ((table == NULL) || (limits == NULL)) + return false; + + data = table->mask_low; + + num_bits = hweight32(data); + + if (num_bits == 0) + return false; + + num_levels = (1 << num_bits); + + if (table->count != num_levels) + return false; + + if (limits->count != (num_levels - 1)) + return false; + + return true; +} + +static void si_trim_voltage_table_to_fit_state_table(struct amdgpu_device *adev, + u32 max_voltage_steps, + struct atom_voltage_table *voltage_table) +{ + unsigned int i, diff; + + if (voltage_table->count <= max_voltage_steps) + return; + + diff = voltage_table->count - max_voltage_steps; + + for (i= 0; i < max_voltage_steps; i++) + voltage_table->entries[i] = voltage_table->entries[i + diff]; + + voltage_table->count = max_voltage_steps; +} + +static int si_get_svi2_voltage_table(struct amdgpu_device *adev, + struct amdgpu_clock_voltage_dependency_table *voltage_dependency_table, + struct atom_voltage_table *voltage_table) +{ + u32 i; + + if (voltage_dependency_table == NULL) + return -EINVAL; + + voltage_table->mask_low = 0; + voltage_table->phase_delay = 0; + + voltage_table->count = voltage_dependency_table->count; + for (i = 0; i < voltage_table->count; i++) { + voltage_table->entries[i].value = voltage_dependency_table->entries[i].v; + voltage_table->entries[i].smio_low = 0; + } + + return 0; +} + +static int si_construct_voltage_tables(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + int ret; + + if (pi->voltage_control) { + ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC, + VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table); + if (ret) + return ret; + + if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) + si_trim_voltage_table_to_fit_state_table(adev, + SISLANDS_MAX_NO_VREG_STEPS, + &eg_pi->vddc_voltage_table); + } else if (si_pi->voltage_control_svi2) { + ret = si_get_svi2_voltage_table(adev, + &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, + &eg_pi->vddc_voltage_table); + if (ret) + return ret; + } else { + return -EINVAL; + } + + if (eg_pi->vddci_control) { + ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDCI, + VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddci_voltage_table); + if (ret) + return ret; + + if (eg_pi->vddci_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) + si_trim_voltage_table_to_fit_state_table(adev, + SISLANDS_MAX_NO_VREG_STEPS, + &eg_pi->vddci_voltage_table); + } + if (si_pi->vddci_control_svi2) { + ret = si_get_svi2_voltage_table(adev, + &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, + &eg_pi->vddci_voltage_table); + if (ret) + return ret; + } + + if (pi->mvdd_control) { + ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_MVDDC, + VOLTAGE_OBJ_GPIO_LUT, &si_pi->mvdd_voltage_table); + + if (ret) { + pi->mvdd_control = false; + return ret; + } + + if (si_pi->mvdd_voltage_table.count == 0) { + pi->mvdd_control = false; + return -EINVAL; + } + + if (si_pi->mvdd_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) + si_trim_voltage_table_to_fit_state_table(adev, + SISLANDS_MAX_NO_VREG_STEPS, + &si_pi->mvdd_voltage_table); + } + + if (si_pi->vddc_phase_shed_control) { + ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC, + VOLTAGE_OBJ_PHASE_LUT, &si_pi->vddc_phase_shed_table); + if (ret) + si_pi->vddc_phase_shed_control = false; + + if ((si_pi->vddc_phase_shed_table.count == 0) || + (si_pi->vddc_phase_shed_table.count > SISLANDS_MAX_NO_VREG_STEPS)) + si_pi->vddc_phase_shed_control = false; + } + + return 0; +} + +static void si_populate_smc_voltage_table(struct amdgpu_device *adev, + const struct atom_voltage_table *voltage_table, + SISLANDS_SMC_STATETABLE *table) +{ + unsigned int i; + + for (i = 0; i < voltage_table->count; i++) + table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low); +} + +static int si_populate_smc_voltage_tables(struct amdgpu_device *adev, + SISLANDS_SMC_STATETABLE *table) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + u8 i; + + if (si_pi->voltage_control_svi2) { + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc, + si_pi->svc_gpio_id); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd, + si_pi->svd_gpio_id); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type, + 2); + } else { + if (eg_pi->vddc_voltage_table.count) { + si_populate_smc_voltage_table(adev, &eg_pi->vddc_voltage_table, table); + table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] = + cpu_to_be32(eg_pi->vddc_voltage_table.mask_low); + + for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) { + if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) { + table->maxVDDCIndexInPPTable = i; + break; + } + } + } + + if (eg_pi->vddci_voltage_table.count) { + si_populate_smc_voltage_table(adev, &eg_pi->vddci_voltage_table, table); + + table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] = + cpu_to_be32(eg_pi->vddci_voltage_table.mask_low); + } + + + if (si_pi->mvdd_voltage_table.count) { + si_populate_smc_voltage_table(adev, &si_pi->mvdd_voltage_table, table); + + table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] = + cpu_to_be32(si_pi->mvdd_voltage_table.mask_low); + } + + if (si_pi->vddc_phase_shed_control) { + if (si_validate_phase_shedding_tables(adev, &si_pi->vddc_phase_shed_table, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table)) { + si_populate_smc_voltage_table(adev, &si_pi->vddc_phase_shed_table, table); + + table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] = + cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low); + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_phase_shedding_delay, + (u32)si_pi->vddc_phase_shed_table.phase_delay); + } else { + si_pi->vddc_phase_shed_control = false; + } + } + } + + return 0; +} + +static int si_populate_voltage_value(struct amdgpu_device *adev, + const struct atom_voltage_table *table, + u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage) +{ + unsigned int i; + + for (i = 0; i < table->count; i++) { + if (value <= table->entries[i].value) { + voltage->index = (u8)i; + voltage->value = cpu_to_be16(table->entries[i].value); + break; + } + } + + if (i >= table->count) + return -EINVAL; + + return 0; +} + +static int si_populate_mvdd_value(struct amdgpu_device *adev, u32 mclk, + SISLANDS_SMC_VOLTAGE_VALUE *voltage) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + + if (pi->mvdd_control) { + if (mclk <= pi->mvdd_split_frequency) + voltage->index = 0; + else + voltage->index = (u8)(si_pi->mvdd_voltage_table.count) - 1; + + voltage->value = cpu_to_be16(si_pi->mvdd_voltage_table.entries[voltage->index].value); + } + return 0; +} + +static int si_get_std_voltage_value(struct amdgpu_device *adev, + SISLANDS_SMC_VOLTAGE_VALUE *voltage, + u16 *std_voltage) +{ + u16 v_index; + bool voltage_found = false; + *std_voltage = be16_to_cpu(voltage->value); + + if (adev->pm.dpm.dyn_state.cac_leakage_table.entries) { + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE) { + if (adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries == NULL) + return -EINVAL; + + for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) { + if (be16_to_cpu(voltage->value) == + (u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) { + voltage_found = true; + if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count) + *std_voltage = + adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc; + else + *std_voltage = + adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc; + break; + } + } + + if (!voltage_found) { + for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) { + if (be16_to_cpu(voltage->value) <= + (u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) { + voltage_found = true; + if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count) + *std_voltage = + adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc; + else + *std_voltage = + adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc; + break; + } + } + } + } else { + if ((u32)voltage->index < adev->pm.dpm.dyn_state.cac_leakage_table.count) + *std_voltage = adev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc; + } + } + + return 0; +} + +static int si_populate_std_voltage_value(struct amdgpu_device *adev, + u16 value, u8 index, + SISLANDS_SMC_VOLTAGE_VALUE *voltage) +{ + voltage->index = index; + voltage->value = cpu_to_be16(value); + + return 0; +} + +static int si_populate_phase_shedding_value(struct amdgpu_device *adev, + const struct amdgpu_phase_shedding_limits_table *limits, + u16 voltage, u32 sclk, u32 mclk, + SISLANDS_SMC_VOLTAGE_VALUE *smc_voltage) +{ + unsigned int i; + + for (i = 0; i < limits->count; i++) { + if ((voltage <= limits->entries[i].voltage) && + (sclk <= limits->entries[i].sclk) && + (mclk <= limits->entries[i].mclk)) + break; + } + + smc_voltage->phase_settings = (u8)i; + + return 0; +} + +static int si_init_arb_table_index(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + int ret; + + ret = si_read_smc_sram_dword(adev, si_pi->arb_table_start, &tmp, si_pi->sram_end); + if (ret) + return ret; + + tmp &= 0x00FFFFFF; + tmp |= MC_CG_ARB_FREQ_F1 << 24; + + return si_write_smc_sram_dword(adev, si_pi->arb_table_start, tmp, si_pi->sram_end); +} + +static int si_initial_switch_from_arb_f0_to_f1(struct amdgpu_device *adev) +{ + return ni_copy_and_switch_arb_sets(adev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); +} + +static int si_reset_to_default(struct amdgpu_device *adev) +{ + return (si_send_msg_to_smc(adev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static int si_force_switch_to_arb_f0(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + int ret; + + ret = si_read_smc_sram_dword(adev, si_pi->arb_table_start, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + tmp = (tmp >> 24) & 0xff; + + if (tmp == MC_CG_ARB_FREQ_F0) + return 0; + + return ni_copy_and_switch_arb_sets(adev, tmp, MC_CG_ARB_FREQ_F0); +} + +static u32 si_calculate_memory_refresh_rate(struct amdgpu_device *adev, + u32 engine_clock) +{ + u32 dram_rows; + u32 dram_refresh_rate; + u32 mc_arb_rfsh_rate; + u32 tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT; + + if (tmp >= 4) + dram_rows = 16384; + else + dram_rows = 1 << (tmp + 10); + + dram_refresh_rate = 1 << ((RREG32(MC_SEQ_MISC0) & 0x3) + 3); + mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64; + + return mc_arb_rfsh_rate; +} + +static int si_populate_memory_timing_parameters(struct amdgpu_device *adev, + struct rv7xx_pl *pl, + SMC_SIslands_MCArbDramTimingRegisterSet *arb_regs) +{ + u32 dram_timing; + u32 dram_timing2; + u32 burst_time; + + arb_regs->mc_arb_rfsh_rate = + (u8)si_calculate_memory_refresh_rate(adev, pl->sclk); + + amdgpu_atombios_set_engine_dram_timings(adev, + pl->sclk, + pl->mclk); + + dram_timing = RREG32(MC_ARB_DRAM_TIMING); + dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); + burst_time = RREG32(MC_ARB_BURST_TIME) & STATE0_MASK; + + arb_regs->mc_arb_dram_timing = cpu_to_be32(dram_timing); + arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2); + arb_regs->mc_arb_burst_time = (u8)burst_time; + + return 0; +} + +static int si_do_program_memory_timing_parameters(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + unsigned int first_arb_set) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 }; + int i, ret = 0; + + for (i = 0; i < state->performance_level_count; i++) { + ret = si_populate_memory_timing_parameters(adev, &state->performance_levels[i], &arb_regs); + if (ret) + break; + ret = si_copy_bytes_to_smc(adev, + si_pi->arb_table_start + + offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i), + (u8 *)&arb_regs, + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), + si_pi->sram_end); + if (ret) + break; + } + + return ret; +} + +static int si_program_memory_timing_parameters(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state) +{ + return si_do_program_memory_timing_parameters(adev, amdgpu_new_state, + SISLANDS_DRIVER_STATE_ARB_INDEX); +} + +static int si_populate_initial_mvdd_value(struct amdgpu_device *adev, + struct SISLANDS_SMC_VOLTAGE_VALUE *voltage) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + + if (pi->mvdd_control) + return si_populate_voltage_value(adev, &si_pi->mvdd_voltage_table, + si_pi->mvdd_bootup_value, voltage); + + return 0; +} + +static int si_populate_smc_initial_state(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_initial_state, + SISLANDS_SMC_STATETABLE *table) +{ + struct si_ps *initial_state = si_get_ps(amdgpu_initial_state); + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + u32 reg; + int ret; + + table->initialState.levels[0].mclk.vDLL_CNTL = + cpu_to_be32(si_pi->clock_registers.dll_cntl); + table->initialState.levels[0].mclk.vMCLK_PWRMGT_CNTL = + cpu_to_be32(si_pi->clock_registers.mclk_pwrmgt_cntl); + table->initialState.levels[0].mclk.vMPLL_AD_FUNC_CNTL = + cpu_to_be32(si_pi->clock_registers.mpll_ad_func_cntl); + table->initialState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL = + cpu_to_be32(si_pi->clock_registers.mpll_dq_func_cntl); + table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL = + cpu_to_be32(si_pi->clock_registers.mpll_func_cntl); + table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL_1 = + cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_1); + table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL_2 = + cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_2); + table->initialState.levels[0].mclk.vMPLL_SS = + cpu_to_be32(si_pi->clock_registers.mpll_ss1); + table->initialState.levels[0].mclk.vMPLL_SS2 = + cpu_to_be32(si_pi->clock_registers.mpll_ss2); + + table->initialState.levels[0].mclk.mclk_value = + cpu_to_be32(initial_state->performance_levels[0].mclk); + + table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = + cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl); + table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = + cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_2); + table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = + cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_3); + table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 = + cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_4); + table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM = + cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum); + table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 = + cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum_2); + + table->initialState.levels[0].sclk.sclk_value = + cpu_to_be32(initial_state->performance_levels[0].sclk); + + table->initialState.levels[0].arbRefreshState = + SISLANDS_INITIAL_STATE_ARB_INDEX; + + table->initialState.levels[0].ACIndex = 0; + + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + initial_state->performance_levels[0].vddc, + &table->initialState.levels[0].vddc); + + if (!ret) { + u16 std_vddc; + + ret = si_get_std_voltage_value(adev, + &table->initialState.levels[0].vddc, + &std_vddc); + if (!ret) + si_populate_std_voltage_value(adev, std_vddc, + table->initialState.levels[0].vddc.index, + &table->initialState.levels[0].std_vddc); + } + + if (eg_pi->vddci_control) + si_populate_voltage_value(adev, + &eg_pi->vddci_voltage_table, + initial_state->performance_levels[0].vddci, + &table->initialState.levels[0].vddci); + + if (si_pi->vddc_phase_shed_control) + si_populate_phase_shedding_value(adev, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table, + initial_state->performance_levels[0].vddc, + initial_state->performance_levels[0].sclk, + initial_state->performance_levels[0].mclk, + &table->initialState.levels[0].vddc); + + si_populate_initial_mvdd_value(adev, &table->initialState.levels[0].mvdd); + + reg = CG_R(0xffff) | CG_L(0); + table->initialState.levels[0].aT = cpu_to_be32(reg); + + table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp); + + table->initialState.levels[0].gen2PCIE = (u8)si_pi->boot_pcie_gen; + + if (adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { + table->initialState.levels[0].strobeMode = + si_get_strobe_mode_settings(adev, + initial_state->performance_levels[0].mclk); + + if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold) + table->initialState.levels[0].mcFlags = SISLANDS_SMC_MC_EDC_RD_FLAG | SISLANDS_SMC_MC_EDC_WR_FLAG; + else + table->initialState.levels[0].mcFlags = 0; + } + + table->initialState.levelCount = 1; + + table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC; + + table->initialState.levels[0].dpm2.MaxPS = 0; + table->initialState.levels[0].dpm2.NearTDPDec = 0; + table->initialState.levels[0].dpm2.AboveSafeInc = 0; + table->initialState.levels[0].dpm2.BelowSafeInc = 0; + table->initialState.levels[0].dpm2.PwrEfficiencyRatio = 0; + + reg = MIN_POWER_MASK | MAX_POWER_MASK; + table->initialState.levels[0].SQPowerThrottle = cpu_to_be32(reg); + + reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; + table->initialState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg); + + return 0; +} + +static int si_populate_smc_acpi_state(struct amdgpu_device *adev, + SISLANDS_SMC_STATETABLE *table) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl; + u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2; + u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3; + u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4; + u32 dll_cntl = si_pi->clock_registers.dll_cntl; + u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl; + u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl; + u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl; + u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl; + u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1; + u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2; + u32 reg; + int ret; + + table->ACPIState = table->initialState; + + table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (pi->acpi_vddc) { + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + pi->acpi_vddc, &table->ACPIState.levels[0].vddc); + if (!ret) { + u16 std_vddc; + + ret = si_get_std_voltage_value(adev, + &table->ACPIState.levels[0].vddc, &std_vddc); + if (!ret) + si_populate_std_voltage_value(adev, std_vddc, + table->ACPIState.levels[0].vddc.index, + &table->ACPIState.levels[0].std_vddc); + } + table->ACPIState.levels[0].gen2PCIE = si_pi->acpi_pcie_gen; + + if (si_pi->vddc_phase_shed_control) { + si_populate_phase_shedding_value(adev, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table, + pi->acpi_vddc, + 0, + 0, + &table->ACPIState.levels[0].vddc); + } + } else { + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + pi->min_vddc_in_table, &table->ACPIState.levels[0].vddc); + if (!ret) { + u16 std_vddc; + + ret = si_get_std_voltage_value(adev, + &table->ACPIState.levels[0].vddc, &std_vddc); + + if (!ret) + si_populate_std_voltage_value(adev, std_vddc, + table->ACPIState.levels[0].vddc.index, + &table->ACPIState.levels[0].std_vddc); + } + table->ACPIState.levels[0].gen2PCIE = (u8)r600_get_pcie_gen_support(adev, + si_pi->sys_pcie_mask, + si_pi->boot_pcie_gen, + AMDGPU_PCIE_GEN1); + + if (si_pi->vddc_phase_shed_control) + si_populate_phase_shedding_value(adev, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table, + pi->min_vddc_in_table, + 0, + 0, + &table->ACPIState.levels[0].vddc); + } + + if (pi->acpi_vddc) { + if (eg_pi->acpi_vddci) + si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table, + eg_pi->acpi_vddci, + &table->ACPIState.levels[0].vddci); + } + + mclk_pwrmgt_cntl |= MRDCK0_RESET | MRDCK1_RESET; + mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB); + + dll_cntl &= ~(MRDCK0_BYPASS | MRDCK1_BYPASS); + + spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; + spll_func_cntl_2 |= SCLK_MUX_SEL(4); + + table->ACPIState.levels[0].mclk.vDLL_CNTL = + cpu_to_be32(dll_cntl); + table->ACPIState.levels[0].mclk.vMCLK_PWRMGT_CNTL = + cpu_to_be32(mclk_pwrmgt_cntl); + table->ACPIState.levels[0].mclk.vMPLL_AD_FUNC_CNTL = + cpu_to_be32(mpll_ad_func_cntl); + table->ACPIState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL = + cpu_to_be32(mpll_dq_func_cntl); + table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL = + cpu_to_be32(mpll_func_cntl); + table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL_1 = + cpu_to_be32(mpll_func_cntl_1); + table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL_2 = + cpu_to_be32(mpll_func_cntl_2); + table->ACPIState.levels[0].mclk.vMPLL_SS = + cpu_to_be32(si_pi->clock_registers.mpll_ss1); + table->ACPIState.levels[0].mclk.vMPLL_SS2 = + cpu_to_be32(si_pi->clock_registers.mpll_ss2); + + table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = + cpu_to_be32(spll_func_cntl); + table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = + cpu_to_be32(spll_func_cntl_2); + table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = + cpu_to_be32(spll_func_cntl_3); + table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 = + cpu_to_be32(spll_func_cntl_4); + + table->ACPIState.levels[0].mclk.mclk_value = 0; + table->ACPIState.levels[0].sclk.sclk_value = 0; + + si_populate_mvdd_value(adev, 0, &table->ACPIState.levels[0].mvdd); + + if (eg_pi->dynamic_ac_timing) + table->ACPIState.levels[0].ACIndex = 0; + + table->ACPIState.levels[0].dpm2.MaxPS = 0; + table->ACPIState.levels[0].dpm2.NearTDPDec = 0; + table->ACPIState.levels[0].dpm2.AboveSafeInc = 0; + table->ACPIState.levels[0].dpm2.BelowSafeInc = 0; + table->ACPIState.levels[0].dpm2.PwrEfficiencyRatio = 0; + + reg = MIN_POWER_MASK | MAX_POWER_MASK; + table->ACPIState.levels[0].SQPowerThrottle = cpu_to_be32(reg); + + reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; + table->ACPIState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg); + + return 0; +} + +static int si_populate_ulv_state(struct amdgpu_device *adev, + SISLANDS_SMC_SWSTATE *state) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + u32 sclk_in_sr = 1350; /* ??? */ + int ret; + + ret = si_convert_power_level_to_smc(adev, &ulv->pl, + &state->levels[0]); + if (!ret) { + if (eg_pi->sclk_deep_sleep) { + if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ) + state->levels[0].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS; + else + state->levels[0].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE; + } + if (ulv->one_pcie_lane_in_ulv) + state->flags |= PPSMC_SWSTATE_FLAG_PCIE_X1; + state->levels[0].arbRefreshState = (u8)(SISLANDS_ULV_STATE_ARB_INDEX); + state->levels[0].ACIndex = 1; + state->levels[0].std_vddc = state->levels[0].vddc; + state->levelCount = 1; + + state->flags |= PPSMC_SWSTATE_FLAG_DC; + } + + return ret; +} + +static int si_program_ulv_memory_timing_parameters(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 }; + int ret; + + ret = si_populate_memory_timing_parameters(adev, &ulv->pl, + &arb_regs); + if (ret) + return ret; + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ulv_volt_change_delay, + ulv->volt_change_delay); + + ret = si_copy_bytes_to_smc(adev, + si_pi->arb_table_start + + offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * SISLANDS_ULV_STATE_ARB_INDEX, + (u8 *)&arb_regs, + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), + si_pi->sram_end); + + return ret; +} + +static void si_get_mvdd_configuration(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + + pi->mvdd_split_frequency = 30000; +} + +static int si_init_smc_table(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct amdgpu_ps *amdgpu_boot_state = adev->pm.dpm.boot_ps; + const struct si_ulv_param *ulv = &si_pi->ulv; + SISLANDS_SMC_STATETABLE *table = &si_pi->smc_statetable; + int ret; + u32 lane_width; + u32 vr_hot_gpio; + + si_populate_smc_voltage_tables(adev, table); + + switch (adev->pm.int_thermal_type) { + case THERMAL_TYPE_SI: + case THERMAL_TYPE_EMC2103_WITH_INTERNAL: + table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL; + break; + case THERMAL_TYPE_NONE: + table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE; + break; + default: + table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL; + break; + } + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC) + table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT) { + if ((adev->pdev->device != 0x6818) && (adev->pdev->device != 0x6819)) + table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT; + } + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC) + table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) + table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY) + table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH; + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE) { + table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO; + vr_hot_gpio = adev->pm.dpm.backbias_response_time; + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_vr_hot_gpio, + vr_hot_gpio); + } + + ret = si_populate_smc_initial_state(adev, amdgpu_boot_state, table); + if (ret) + return ret; + + ret = si_populate_smc_acpi_state(adev, table); + if (ret) + return ret; + + table->driverState = table->initialState; + + ret = si_do_program_memory_timing_parameters(adev, amdgpu_boot_state, + SISLANDS_INITIAL_STATE_ARB_INDEX); + if (ret) + return ret; + + if (ulv->supported && ulv->pl.vddc) { + ret = si_populate_ulv_state(adev, &table->ULVState); + if (ret) + return ret; + + ret = si_program_ulv_memory_timing_parameters(adev); + if (ret) + return ret; + + WREG32(CG_ULV_CONTROL, ulv->cg_ulv_control); + WREG32(CG_ULV_PARAMETER, ulv->cg_ulv_parameter); + + lane_width = amdgpu_get_pcie_lanes(adev); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width); + } else { + table->ULVState = table->initialState; + } + + return si_copy_bytes_to_smc(adev, si_pi->state_table_start, + (u8 *)table, sizeof(SISLANDS_SMC_STATETABLE), + si_pi->sram_end); +} + +static int si_calculate_sclk_params(struct amdgpu_device *adev, + u32 engine_clock, + SISLANDS_SMC_SCLK_VALUE *sclk) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct atom_clock_dividers dividers; + u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl; + u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2; + u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3; + u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4; + u32 cg_spll_spread_spectrum = si_pi->clock_registers.cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2 = si_pi->clock_registers.cg_spll_spread_spectrum_2; + u64 tmp; + u32 reference_clock = adev->clock.spll.reference_freq; + u32 reference_divider; + u32 fbdiv; + int ret; + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + engine_clock, false, ÷rs); + if (ret) + return ret; + + reference_divider = 1 + dividers.ref_div; + + tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384; + do_div(tmp, reference_clock); + fbdiv = (u32) tmp; + + spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK); + spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div); + spll_func_cntl |= SPLL_PDIV_A(dividers.post_div); + + spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; + spll_func_cntl_2 |= SCLK_MUX_SEL(2); + + spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; + spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); + spll_func_cntl_3 |= SPLL_DITHEN; + + if (pi->sclk_ss) { + struct amdgpu_atom_ss ss; + u32 vco_freq = engine_clock * dividers.post_div; + + if (amdgpu_atombios_get_asic_ss_info(adev, &ss, + ASIC_INTERNAL_ENGINE_SS, vco_freq)) { + u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); + u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000); + + cg_spll_spread_spectrum &= ~CLK_S_MASK; + cg_spll_spread_spectrum |= CLK_S(clk_s); + cg_spll_spread_spectrum |= SSEN; + + cg_spll_spread_spectrum_2 &= ~CLK_V_MASK; + cg_spll_spread_spectrum_2 |= CLK_V(clk_v); + } + } + + sclk->sclk_value = engine_clock; + sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl; + sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2; + sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3; + sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4; + sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum; + sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2; + + return 0; +} + +static int si_populate_sclk_value(struct amdgpu_device *adev, + u32 engine_clock, + SISLANDS_SMC_SCLK_VALUE *sclk) +{ + SISLANDS_SMC_SCLK_VALUE sclk_tmp; + int ret; + + ret = si_calculate_sclk_params(adev, engine_clock, &sclk_tmp); + if (!ret) { + sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value); + sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL); + sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2); + sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3); + sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4); + sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM); + sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2); + } + + return ret; +} + +static int si_populate_mclk_value(struct amdgpu_device *adev, + u32 engine_clock, + u32 memory_clock, + SISLANDS_SMC_MCLK_VALUE *mclk, + bool strobe_mode, + bool dll_state_on) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + u32 dll_cntl = si_pi->clock_registers.dll_cntl; + u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl; + u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl; + u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl; + u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl; + u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1; + u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2; + u32 mpll_ss1 = si_pi->clock_registers.mpll_ss1; + u32 mpll_ss2 = si_pi->clock_registers.mpll_ss2; + struct atom_mpll_param mpll_param; + int ret; + + ret = amdgpu_atombios_get_memory_pll_dividers(adev, memory_clock, strobe_mode, &mpll_param); + if (ret) + return ret; + + mpll_func_cntl &= ~BWCTRL_MASK; + mpll_func_cntl |= BWCTRL(mpll_param.bwcntl); + + mpll_func_cntl_1 &= ~(CLKF_MASK | CLKFRAC_MASK | VCO_MODE_MASK); + mpll_func_cntl_1 |= CLKF(mpll_param.clkf) | + CLKFRAC(mpll_param.clkfrac) | VCO_MODE(mpll_param.vco_mode); + + mpll_ad_func_cntl &= ~YCLK_POST_DIV_MASK; + mpll_ad_func_cntl |= YCLK_POST_DIV(mpll_param.post_div); + + if (adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { + mpll_dq_func_cntl &= ~(YCLK_SEL_MASK | YCLK_POST_DIV_MASK); + mpll_dq_func_cntl |= YCLK_SEL(mpll_param.yclk_sel) | + YCLK_POST_DIV(mpll_param.post_div); + } + + if (pi->mclk_ss) { + struct amdgpu_atom_ss ss; + u32 freq_nom; + u32 tmp; + u32 reference_clock = adev->clock.mpll.reference_freq; + + if (adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) + freq_nom = memory_clock * 4; + else + freq_nom = memory_clock * 2; + + tmp = freq_nom / reference_clock; + tmp = tmp * tmp; + if (amdgpu_atombios_get_asic_ss_info(adev, &ss, + ASIC_INTERNAL_MEMORY_SS, freq_nom)) { + u32 clks = reference_clock * 5 / ss.rate; + u32 clkv = (u32)((((131 * ss.percentage * ss.rate) / 100) * tmp) / freq_nom); + + mpll_ss1 &= ~CLKV_MASK; + mpll_ss1 |= CLKV(clkv); + + mpll_ss2 &= ~CLKS_MASK; + mpll_ss2 |= CLKS(clks); + } + } + + mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK; + mclk_pwrmgt_cntl |= DLL_SPEED(mpll_param.dll_speed); + + if (dll_state_on) + mclk_pwrmgt_cntl |= MRDCK0_PDNB | MRDCK1_PDNB; + else + mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB); + + mclk->mclk_value = cpu_to_be32(memory_clock); + mclk->vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); + mclk->vMPLL_FUNC_CNTL_1 = cpu_to_be32(mpll_func_cntl_1); + mclk->vMPLL_FUNC_CNTL_2 = cpu_to_be32(mpll_func_cntl_2); + mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl); + mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl); + mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); + mclk->vDLL_CNTL = cpu_to_be32(dll_cntl); + mclk->vMPLL_SS = cpu_to_be32(mpll_ss1); + mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2); + + return 0; +} + +static void si_populate_smc_sp(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct si_ps *ps = si_get_ps(amdgpu_state); + struct rv7xx_power_info *pi = rv770_get_pi(adev); + int i; + + for (i = 0; i < ps->performance_level_count - 1; i++) + smc_state->levels[i].bSP = cpu_to_be32(pi->dsp); + + smc_state->levels[ps->performance_level_count - 1].bSP = + cpu_to_be32(pi->psp); +} + +static int si_convert_power_level_to_smc(struct amdgpu_device *adev, + struct rv7xx_pl *pl, + SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + int ret; + bool dll_state_on; + u16 std_vddc; + bool gmc_pg = false; + + if (eg_pi->pcie_performance_request && + (si_pi->force_pcie_gen != AMDGPU_PCIE_GEN_INVALID)) + level->gen2PCIE = (u8)si_pi->force_pcie_gen; + else + level->gen2PCIE = (u8)pl->pcie_gen; + + ret = si_populate_sclk_value(adev, pl->sclk, &level->sclk); + if (ret) + return ret; + + level->mcFlags = 0; + + if (pi->mclk_stutter_mode_threshold && + (pl->mclk <= pi->mclk_stutter_mode_threshold) && + !eg_pi->uvd_enabled && + (RREG32(DPG_PIPE_STUTTER_CONTROL) & STUTTER_ENABLE) && + (adev->pm.dpm.new_active_crtc_count <= 2)) { + level->mcFlags |= SISLANDS_SMC_MC_STUTTER_EN; + + if (gmc_pg) + level->mcFlags |= SISLANDS_SMC_MC_PG_EN; + } + + if (adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { + if (pl->mclk > pi->mclk_edc_enable_threshold) + level->mcFlags |= SISLANDS_SMC_MC_EDC_RD_FLAG; + + if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold) + level->mcFlags |= SISLANDS_SMC_MC_EDC_WR_FLAG; + + level->strobeMode = si_get_strobe_mode_settings(adev, pl->mclk); + + if (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) { + if (si_get_mclk_frequency_ratio(pl->mclk, true) >= + ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf)) + dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false; + else + dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false; + } else { + dll_state_on = false; + } + } else { + level->strobeMode = si_get_strobe_mode_settings(adev, + pl->mclk); + + dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false; + } + + ret = si_populate_mclk_value(adev, + pl->sclk, + pl->mclk, + &level->mclk, + (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) != 0, dll_state_on); + if (ret) + return ret; + + ret = si_populate_voltage_value(adev, + &eg_pi->vddc_voltage_table, + pl->vddc, &level->vddc); + if (ret) + return ret; + + + ret = si_get_std_voltage_value(adev, &level->vddc, &std_vddc); + if (ret) + return ret; + + ret = si_populate_std_voltage_value(adev, std_vddc, + level->vddc.index, &level->std_vddc); + if (ret) + return ret; + + if (eg_pi->vddci_control) { + ret = si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table, + pl->vddci, &level->vddci); + if (ret) + return ret; + } + + if (si_pi->vddc_phase_shed_control) { + ret = si_populate_phase_shedding_value(adev, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table, + pl->vddc, + pl->sclk, + pl->mclk, + &level->vddc); + if (ret) + return ret; + } + + level->MaxPoweredUpCU = si_pi->max_cu; + + ret = si_populate_mvdd_value(adev, pl->mclk, &level->mvdd); + + return ret; +} + +static int si_populate_smc_t(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + u32 a_t; + u32 t_l, t_h; + u32 high_bsp; + int i, ret; + + if (state->performance_level_count >= 9) + return -EINVAL; + + if (state->performance_level_count < 2) { + a_t = CG_R(0xffff) | CG_L(0); + smc_state->levels[0].aT = cpu_to_be32(a_t); + return 0; + } + + smc_state->levels[0].aT = cpu_to_be32(0); + + for (i = 0; i <= state->performance_level_count - 2; i++) { + ret = r600_calculate_at( + (50 / SISLANDS_MAX_HARDWARE_POWERLEVELS) * 100 * (i + 1), + 100 * R600_AH_DFLT, + state->performance_levels[i + 1].sclk, + state->performance_levels[i].sclk, + &t_l, + &t_h); + + if (ret) { + t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT; + t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT; + } + + a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_R_MASK; + a_t |= CG_R(t_l * pi->bsp / 20000); + smc_state->levels[i].aT = cpu_to_be32(a_t); + + high_bsp = (i == state->performance_level_count - 2) ? + pi->pbsp : pi->bsp; + a_t = CG_R(0xffff) | CG_L(t_h * high_bsp / 20000); + smc_state->levels[i + 1].aT = cpu_to_be32(a_t); + } + + return 0; +} + +static int si_disable_ulv(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + + if (ulv->supported) + return (si_send_msg_to_smc(adev, PPSMC_MSG_DisableULV) == PPSMC_Result_OK) ? + 0 : -EINVAL; + + return 0; +} + +static bool si_is_state_ulv_compatible(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + const struct si_power_info *si_pi = si_get_pi(adev); + const struct si_ulv_param *ulv = &si_pi->ulv; + const struct si_ps *state = si_get_ps(amdgpu_state); + int i; + + if (state->performance_levels[0].mclk != ulv->pl.mclk) + return false; + + /* XXX validate against display requirements! */ + + for (i = 0; i < adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count; i++) { + if (adev->clock.current_dispclk <= + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].clk) { + if (ulv->pl.vddc < + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].v) + return false; + } + } + + if ((amdgpu_state->vclk != 0) || (amdgpu_state->dclk != 0)) + return false; + + return true; +} + +static int si_set_power_state_conditionally_enable_ulv(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state) +{ + const struct si_power_info *si_pi = si_get_pi(adev); + const struct si_ulv_param *ulv = &si_pi->ulv; + + if (ulv->supported) { + if (si_is_state_ulv_compatible(adev, amdgpu_new_state)) + return (si_send_msg_to_smc(adev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ? + 0 : -EINVAL; + } + return 0; +} + +static int si_convert_power_state_to_smc(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + int i, ret; + u32 threshold; + u32 sclk_in_sr = 1350; /* ??? */ + + if (state->performance_level_count > SISLANDS_MAX_HARDWARE_POWERLEVELS) + return -EINVAL; + + threshold = state->performance_levels[state->performance_level_count-1].sclk * 100 / 100; + + if (amdgpu_state->vclk && amdgpu_state->dclk) { + eg_pi->uvd_enabled = true; + if (eg_pi->smu_uvd_hs) + smc_state->flags |= PPSMC_SWSTATE_FLAG_UVD; + } else { + eg_pi->uvd_enabled = false; + } + + if (state->dc_compatible) + smc_state->flags |= PPSMC_SWSTATE_FLAG_DC; + + smc_state->levelCount = 0; + for (i = 0; i < state->performance_level_count; i++) { + if (eg_pi->sclk_deep_sleep) { + if ((i == 0) || si_pi->sclk_deep_sleep_above_low) { + if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ) + smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS; + else + smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE; + } + } + + ret = si_convert_power_level_to_smc(adev, &state->performance_levels[i], + &smc_state->levels[i]); + smc_state->levels[i].arbRefreshState = + (u8)(SISLANDS_DRIVER_STATE_ARB_INDEX + i); + + if (ret) + return ret; + + if (ni_pi->enable_power_containment) + smc_state->levels[i].displayWatermark = + (state->performance_levels[i].sclk < threshold) ? + PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH; + else + smc_state->levels[i].displayWatermark = (i < 2) ? + PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH; + + if (eg_pi->dynamic_ac_timing) + smc_state->levels[i].ACIndex = SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i; + else + smc_state->levels[i].ACIndex = 0; + + smc_state->levelCount++; + } + + si_write_smc_soft_register(adev, + SI_SMC_SOFT_REGISTER_watermark_threshold, + threshold / 512); + + si_populate_smc_sp(adev, amdgpu_state, smc_state); + + ret = si_populate_power_containment_values(adev, amdgpu_state, smc_state); + if (ret) + ni_pi->enable_power_containment = false; + + ret = si_populate_sq_ramping_values(adev, amdgpu_state, smc_state); + if (ret) + ni_pi->enable_sq_ramping = false; + + return si_populate_smc_t(adev, amdgpu_state, smc_state); +} + +static int si_upload_sw_state(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ps *new_state = si_get_ps(amdgpu_new_state); + int ret; + u32 address = si_pi->state_table_start + + offsetof(SISLANDS_SMC_STATETABLE, driverState); + u32 state_size = sizeof(SISLANDS_SMC_SWSTATE) + + ((new_state->performance_level_count - 1) * + sizeof(SISLANDS_SMC_HW_PERFORMANCE_LEVEL)); + SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.driverState; + + memset(smc_state, 0, state_size); + + ret = si_convert_power_state_to_smc(adev, amdgpu_new_state, smc_state); + if (ret) + return ret; + + ret = si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, + state_size, si_pi->sram_end); + + return ret; +} + +static int si_upload_ulv_state(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + int ret = 0; + + if (ulv->supported && ulv->pl.vddc) { + u32 address = si_pi->state_table_start + + offsetof(SISLANDS_SMC_STATETABLE, ULVState); + SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.ULVState; + u32 state_size = sizeof(SISLANDS_SMC_SWSTATE); + + memset(smc_state, 0, state_size); + + ret = si_populate_ulv_state(adev, smc_state); + if (!ret) + ret = si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, + state_size, si_pi->sram_end); + } + + return ret; +} + +static int si_upload_smc_data(struct amdgpu_device *adev) +{ + struct amdgpu_crtc *amdgpu_crtc = NULL; + int i; + + if (adev->pm.dpm.new_active_crtc_count == 0) + return 0; + + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (adev->pm.dpm.new_active_crtcs & (1 << i)) { + amdgpu_crtc = adev->mode_info.crtcs[i]; + break; + } + } + + if (amdgpu_crtc == NULL) + return 0; + + if (amdgpu_crtc->line_time <= 0) + return 0; + + if (si_write_smc_soft_register(adev, + SI_SMC_SOFT_REGISTER_crtc_index, + amdgpu_crtc->crtc_id) != PPSMC_Result_OK) + return 0; + + if (si_write_smc_soft_register(adev, + SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min, + amdgpu_crtc->wm_high / amdgpu_crtc->line_time) != PPSMC_Result_OK) + return 0; + + if (si_write_smc_soft_register(adev, + SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max, + amdgpu_crtc->wm_low / amdgpu_crtc->line_time) != PPSMC_Result_OK) + return 0; + + return 0; +} + +static int si_set_mc_special_registers(struct amdgpu_device *adev, + struct si_mc_reg_table *table) +{ + u8 i, j, k; + u32 temp_reg; + + for (i = 0, j = table->last; i < table->last; i++) { + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + switch (table->mc_reg_address[i].s1) { + case MC_SEQ_MISC1: + temp_reg = RREG32(MC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + j++; + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + + temp_reg = RREG32(MC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + if (adev->mc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + j++; + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + + if (adev->mc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) { + table->mc_reg_address[j].s1 = MC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = MC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + j++; + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + } + break; + case MC_SEQ_RESERVE_M: + temp_reg = RREG32(MC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP; + for(k = 0; k < table->num_entries; k++) + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + j++; + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + break; + default: + break; + } + } + + table->last = j; + + return 0; +} + +static bool si_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg) +{ + bool result = true; + switch (in_reg) { + case MC_SEQ_RAS_TIMING: + *out_reg = MC_SEQ_RAS_TIMING_LP; + break; + case MC_SEQ_CAS_TIMING: + *out_reg = MC_SEQ_CAS_TIMING_LP; + break; + case MC_SEQ_MISC_TIMING: + *out_reg = MC_SEQ_MISC_TIMING_LP; + break; + case MC_SEQ_MISC_TIMING2: + *out_reg = MC_SEQ_MISC_TIMING2_LP; + break; + case MC_SEQ_RD_CTL_D0: + *out_reg = MC_SEQ_RD_CTL_D0_LP; + break; + case MC_SEQ_RD_CTL_D1: + *out_reg = MC_SEQ_RD_CTL_D1_LP; + break; + case MC_SEQ_WR_CTL_D0: + *out_reg = MC_SEQ_WR_CTL_D0_LP; + break; + case MC_SEQ_WR_CTL_D1: + *out_reg = MC_SEQ_WR_CTL_D1_LP; + break; + case MC_PMG_CMD_EMRS: + *out_reg = MC_SEQ_PMG_CMD_EMRS_LP; + break; + case MC_PMG_CMD_MRS: + *out_reg = MC_SEQ_PMG_CMD_MRS_LP; + break; + case MC_PMG_CMD_MRS1: + *out_reg = MC_SEQ_PMG_CMD_MRS1_LP; + break; + case MC_SEQ_PMG_TIMING: + *out_reg = MC_SEQ_PMG_TIMING_LP; + break; + case MC_PMG_CMD_MRS2: + *out_reg = MC_SEQ_PMG_CMD_MRS2_LP; + break; + case MC_SEQ_WR_CTL_2: + *out_reg = MC_SEQ_WR_CTL_2_LP; + break; + default: + result = false; + break; + } + + return result; +} + +static void si_set_valid_flag(struct si_mc_reg_table *table) +{ + u8 i, j; + + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != table->mc_reg_table_entry[j].mc_data[i]) { + table->valid_flag |= 1 << i; + break; + } + } + } +} + +static void si_set_s0_mc_reg_index(struct si_mc_reg_table *table) +{ + u32 i; + u16 address; + + for (i = 0; i < table->last; i++) + table->mc_reg_address[i].s0 = si_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ? + address : table->mc_reg_address[i].s1; + +} + +static int si_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table, + struct si_mc_reg_table *si_table) +{ + u8 i, j; + + if (table->last > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + if (table->num_entries > MAX_AC_TIMING_ENTRIES) + return -EINVAL; + + for (i = 0; i < table->last; i++) + si_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + si_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + si_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + si_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + si_table->num_entries = table->num_entries; + + return 0; +} + +static int si_initialize_mc_reg_table(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct atom_mc_reg_table *table; + struct si_mc_reg_table *si_table = &si_pi->mc_reg_table; + u8 module_index = rv770_get_memory_module_index(adev); + int ret; + + table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL); + if (!table) + return -ENOMEM; + + WREG32(MC_SEQ_RAS_TIMING_LP, RREG32(MC_SEQ_RAS_TIMING)); + WREG32(MC_SEQ_CAS_TIMING_LP, RREG32(MC_SEQ_CAS_TIMING)); + WREG32(MC_SEQ_MISC_TIMING_LP, RREG32(MC_SEQ_MISC_TIMING)); + WREG32(MC_SEQ_MISC_TIMING2_LP, RREG32(MC_SEQ_MISC_TIMING2)); + WREG32(MC_SEQ_PMG_CMD_EMRS_LP, RREG32(MC_PMG_CMD_EMRS)); + WREG32(MC_SEQ_PMG_CMD_MRS_LP, RREG32(MC_PMG_CMD_MRS)); + WREG32(MC_SEQ_PMG_CMD_MRS1_LP, RREG32(MC_PMG_CMD_MRS1)); + WREG32(MC_SEQ_WR_CTL_D0_LP, RREG32(MC_SEQ_WR_CTL_D0)); + WREG32(MC_SEQ_WR_CTL_D1_LP, RREG32(MC_SEQ_WR_CTL_D1)); + WREG32(MC_SEQ_RD_CTL_D0_LP, RREG32(MC_SEQ_RD_CTL_D0)); + WREG32(MC_SEQ_RD_CTL_D1_LP, RREG32(MC_SEQ_RD_CTL_D1)); + WREG32(MC_SEQ_PMG_TIMING_LP, RREG32(MC_SEQ_PMG_TIMING)); + WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2)); + WREG32(MC_SEQ_WR_CTL_2_LP, RREG32(MC_SEQ_WR_CTL_2)); + + ret = amdgpu_atombios_init_mc_reg_table(adev, module_index, table); + if (ret) + goto init_mc_done; + + ret = si_copy_vbios_mc_reg_table(table, si_table); + if (ret) + goto init_mc_done; + + si_set_s0_mc_reg_index(si_table); + + ret = si_set_mc_special_registers(adev, si_table); + if (ret) + goto init_mc_done; + + si_set_valid_flag(si_table); + +init_mc_done: + kfree(table); + + return ret; + +} + +static void si_populate_mc_reg_addresses(struct amdgpu_device *adev, + SMC_SIslands_MCRegisters *mc_reg_table) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 i, j; + + for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) { + if (si_pi->mc_reg_table.valid_flag & (1 << j)) { + if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + break; + mc_reg_table->address[i].s0 = + cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + mc_reg_table->last = (u8)i; +} + +static void si_convert_mc_registers(const struct si_mc_reg_entry *entry, + SMC_SIslands_MCRegisterSet *data, + u32 num_entries, u32 valid_flag) +{ + u32 i, j; + + for(i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & (1 << j)) { + data->value[i] = cpu_to_be32(entry->mc_data[j]); + i++; + } + } +} + +static void si_convert_mc_reg_table_entry_to_smc(struct amdgpu_device *adev, + struct rv7xx_pl *pl, + SMC_SIslands_MCRegisterSet *mc_reg_table_data) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 i = 0; + + for (i = 0; i < si_pi->mc_reg_table.num_entries; i++) { + if (pl->mclk <= si_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max) + break; + } + + if ((i == si_pi->mc_reg_table.num_entries) && (i > 0)) + --i; + + si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, si_pi->mc_reg_table.last, + si_pi->mc_reg_table.valid_flag); +} + +static void si_convert_mc_reg_table_to_smc(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SMC_SIslands_MCRegisters *mc_reg_table) +{ + struct si_ps *state = si_get_ps(amdgpu_state); + int i; + + for (i = 0; i < state->performance_level_count; i++) { + si_convert_mc_reg_table_entry_to_smc(adev, + &state->performance_levels[i], + &mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i]); + } +} + +static int si_populate_mc_reg_table(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_boot_state) +{ + struct si_ps *boot_state = si_get_ps(amdgpu_boot_state); + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table; + + memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters)); + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_seq_index, 1); + + si_populate_mc_reg_addresses(adev, smc_mc_reg_table); + + si_convert_mc_reg_table_entry_to_smc(adev, &boot_state->performance_levels[0], + &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_INITIAL_SLOT]); + + si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0], + &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ACPI_SLOT], + si_pi->mc_reg_table.last, + si_pi->mc_reg_table.valid_flag); + + if (ulv->supported && ulv->pl.vddc != 0) + si_convert_mc_reg_table_entry_to_smc(adev, &ulv->pl, + &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT]); + else + si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0], + &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT], + si_pi->mc_reg_table.last, + si_pi->mc_reg_table.valid_flag); + + si_convert_mc_reg_table_to_smc(adev, amdgpu_boot_state, smc_mc_reg_table); + + return si_copy_bytes_to_smc(adev, si_pi->mc_reg_table_start, + (u8 *)smc_mc_reg_table, + sizeof(SMC_SIslands_MCRegisters), si_pi->sram_end); +} + +static int si_upload_mc_reg_table(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state) +{ + struct si_ps *new_state = si_get_ps(amdgpu_new_state); + struct si_power_info *si_pi = si_get_pi(adev); + u32 address = si_pi->mc_reg_table_start + + offsetof(SMC_SIslands_MCRegisters, + data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT]); + SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table; + + memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters)); + + si_convert_mc_reg_table_to_smc(adev, amdgpu_new_state, smc_mc_reg_table); + + + return si_copy_bytes_to_smc(adev, address, + (u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT], + sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count, + si_pi->sram_end); + +} + +static void si_enable_voltage_control(struct amdgpu_device *adev, bool enable) +{ + if (enable) + WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN); + else + WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN); +} + +static enum amdgpu_pcie_gen si_get_maximum_link_speed(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + struct si_ps *state = si_get_ps(amdgpu_state); + int i; + u16 pcie_speed, max_speed = 0; + + for (i = 0; i < state->performance_level_count; i++) { + pcie_speed = state->performance_levels[i].pcie_gen; + if (max_speed < pcie_speed) + max_speed = pcie_speed; + } + return max_speed; +} + +static u16 si_get_current_pcie_speed(struct amdgpu_device *adev) +{ + u32 speed_cntl; + + speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL) & LC_CURRENT_DATA_RATE_MASK; + speed_cntl >>= LC_CURRENT_DATA_RATE_SHIFT; + + return (u16)speed_cntl; +} + +static void si_request_link_speed_change_before_state_change(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + struct amdgpu_ps *amdgpu_current_state) +{ + struct si_power_info *si_pi = si_get_pi(adev); + enum amdgpu_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); + enum amdgpu_pcie_gen current_link_speed; + + if (si_pi->force_pcie_gen == AMDGPU_PCIE_GEN_INVALID) + current_link_speed = si_get_maximum_link_speed(adev, amdgpu_current_state); + else + current_link_speed = si_pi->force_pcie_gen; + + si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; + si_pi->pspp_notify_required = false; + if (target_link_speed > current_link_speed) { + switch (target_link_speed) { +#if defined(CONFIG_ACPI) + case AMDGPU_PCIE_GEN3: + if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN3, false) == 0) + break; + si_pi->force_pcie_gen = AMDGPU_PCIE_GEN2; + if (current_link_speed == AMDGPU_PCIE_GEN2) + break; + case AMDGPU_PCIE_GEN2: + if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0) + break; +#endif + default: + si_pi->force_pcie_gen = si_get_current_pcie_speed(adev); + break; + } + } else { + if (target_link_speed < current_link_speed) + si_pi->pspp_notify_required = true; + } +} + +static void si_notify_link_speed_change_after_state_change(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + struct amdgpu_ps *amdgpu_current_state) +{ + struct si_power_info *si_pi = si_get_pi(adev); + enum amdgpu_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); + u8 request; + + if (si_pi->pspp_notify_required) { + if (target_link_speed == AMDGPU_PCIE_GEN3) + request = PCIE_PERF_REQ_PECI_GEN3; + else if (target_link_speed == AMDGPU_PCIE_GEN2) + request = PCIE_PERF_REQ_PECI_GEN2; + else + request = PCIE_PERF_REQ_PECI_GEN1; + + if ((request == PCIE_PERF_REQ_PECI_GEN1) && + (si_get_current_pcie_speed(adev) > 0)) + return; + +#if defined(CONFIG_ACPI) + amdgpu_acpi_pcie_performance_request(adev, request, false); +#endif + } +} + +#if 0 +static int si_ds_request(struct amdgpu_device *adev, + bool ds_status_on, u32 count_write) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + + if (eg_pi->sclk_deep_sleep) { + if (ds_status_on) + return (si_send_msg_to_smc(adev, PPSMC_MSG_CancelThrottleOVRDSCLKDS) == + PPSMC_Result_OK) ? + 0 : -EINVAL; + else + return (si_send_msg_to_smc(adev, PPSMC_MSG_ThrottleOVRDSCLKDS) == + PPSMC_Result_OK) ? 0 : -EINVAL; + } + return 0; +} +#endif + +static void si_set_max_cu_value(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + if (adev->asic_type == CHIP_VERDE) { + switch (adev->pdev->device) { + case 0x6820: + case 0x6825: + case 0x6821: + case 0x6823: + case 0x6827: + si_pi->max_cu = 10; + break; + case 0x682D: + case 0x6824: + case 0x682F: + case 0x6826: + si_pi->max_cu = 8; + break; + case 0x6828: + case 0x6830: + case 0x6831: + case 0x6838: + case 0x6839: + case 0x683D: + si_pi->max_cu = 10; + break; + case 0x683B: + case 0x683F: + case 0x6829: + si_pi->max_cu = 8; + break; + default: + si_pi->max_cu = 0; + break; + } + } else { + si_pi->max_cu = 0; + } +} + +static int si_patch_single_dependency_table_based_on_leakage(struct amdgpu_device *adev, + struct amdgpu_clock_voltage_dependency_table *table) +{ + u32 i; + int j; + u16 leakage_voltage; + + if (table) { + for (i = 0; i < table->count; i++) { + switch (si_get_leakage_voltage_from_leakage_index(adev, + table->entries[i].v, + &leakage_voltage)) { + case 0: + table->entries[i].v = leakage_voltage; + break; + case -EAGAIN: + return -EINVAL; + case -EINVAL: + default: + break; + } + } + + for (j = (table->count - 2); j >= 0; j--) { + table->entries[j].v = (table->entries[j].v <= table->entries[j + 1].v) ? + table->entries[j].v : table->entries[j + 1].v; + } + } + return 0; +} + +static int si_patch_dependency_tables_based_on_leakage(struct amdgpu_device *adev) +{ + int ret = 0; + + ret = si_patch_single_dependency_table_based_on_leakage(adev, + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk); + ret = si_patch_single_dependency_table_based_on_leakage(adev, + &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk); + ret = si_patch_single_dependency_table_based_on_leakage(adev, + &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk); + return ret; +} + +static void si_set_pcie_lane_width_in_smc(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + struct amdgpu_ps *amdgpu_current_state) +{ + u32 lane_width; + u32 new_lane_width = + (amdgpu_new_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT; + u32 current_lane_width = + (amdgpu_current_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT; + + if (new_lane_width != current_lane_width) { + amdgpu_set_pcie_lanes(adev, new_lane_width); + lane_width = amdgpu_get_pcie_lanes(adev); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width); + } +} + +static void si_dpm_setup_asic(struct amdgpu_device *adev) +{ + si_read_clock_registers(adev); + si_enable_acpi_power_management(adev); +} + +static int si_thermal_enable_alert(struct amdgpu_device *adev, + bool enable) +{ + u32 thermal_int = RREG32(CG_THERMAL_INT); + + if (enable) { + PPSMC_Result result; + + thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); + WREG32(CG_THERMAL_INT, thermal_int); + result = si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); + if (result != PPSMC_Result_OK) { + DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); + return -EINVAL; + } + } else { + thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; + WREG32(CG_THERMAL_INT, thermal_int); + } + + return 0; +} + +static int si_thermal_set_temperature_range(struct amdgpu_device *adev, + int min_temp, int max_temp) +{ + int low_temp = 0 * 1000; + int high_temp = 255 * 1000; + + if (low_temp < min_temp) + low_temp = min_temp; + if (high_temp > max_temp) + high_temp = max_temp; + if (high_temp < low_temp) { + DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); + return -EINVAL; + } + + WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK); + WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK); + WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK); + + adev->pm.dpm.thermal.min_temp = low_temp; + adev->pm.dpm.thermal.max_temp = high_temp; + + return 0; +} + +static void si_fan_ctrl_set_static_mode(struct amdgpu_device *adev, u32 mode) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + + if (si_pi->fan_ctrl_is_in_default_mode) { + tmp = (RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK) >> FDO_PWM_MODE_SHIFT; + si_pi->fan_ctrl_default_mode = tmp; + tmp = (RREG32(CG_FDO_CTRL2) & TMIN_MASK) >> TMIN_SHIFT; + si_pi->t_min = tmp; + si_pi->fan_ctrl_is_in_default_mode = false; + } + + tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK; + tmp |= TMIN(0); + WREG32(CG_FDO_CTRL2, tmp); + + tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK; + tmp |= FDO_PWM_MODE(mode); + WREG32(CG_FDO_CTRL2, tmp); +} + +static int si_thermal_setup_fan_table(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + PP_SIslands_FanTable fan_table = { FDO_MODE_HARDWARE }; + u32 duty100; + u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2; + u16 fdo_min, slope1, slope2; + u32 reference_clock, tmp; + int ret; + u64 tmp64; + + if (!si_pi->fan_table_start) { + adev->pm.dpm.fan.ucode_fan_control = false; + return 0; + } + + duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; + + if (duty100 == 0) { + adev->pm.dpm.fan.ucode_fan_control = false; + return 0; + } + + tmp64 = (u64)adev->pm.dpm.fan.pwm_min * duty100; + do_div(tmp64, 10000); + fdo_min = (u16)tmp64; + + t_diff1 = adev->pm.dpm.fan.t_med - adev->pm.dpm.fan.t_min; + t_diff2 = adev->pm.dpm.fan.t_high - adev->pm.dpm.fan.t_med; + + pwm_diff1 = adev->pm.dpm.fan.pwm_med - adev->pm.dpm.fan.pwm_min; + pwm_diff2 = adev->pm.dpm.fan.pwm_high - adev->pm.dpm.fan.pwm_med; + + slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.temp_min = cpu_to_be16((50 + adev->pm.dpm.fan.t_min) / 100); + fan_table.temp_med = cpu_to_be16((50 + adev->pm.dpm.fan.t_med) / 100); + fan_table.temp_max = cpu_to_be16((50 + adev->pm.dpm.fan.t_max) / 100); + + fan_table.slope1 = cpu_to_be16(slope1); + fan_table.slope2 = cpu_to_be16(slope2); + + fan_table.fdo_min = cpu_to_be16(fdo_min); + + fan_table.hys_down = cpu_to_be16(adev->pm.dpm.fan.t_hyst); + + fan_table.hys_up = cpu_to_be16(1); + + fan_table.hys_slope = cpu_to_be16(1); + + fan_table.temp_resp_lim = cpu_to_be16(5); + + reference_clock = amdgpu_asic_get_xclk(adev); + + fan_table.refresh_period = cpu_to_be32((adev->pm.dpm.fan.cycle_delay * + reference_clock) / 1600); + + fan_table.fdo_max = cpu_to_be16((u16)duty100); + + tmp = (RREG32(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT; + fan_table.temp_src = (uint8_t)tmp; + + ret = si_copy_bytes_to_smc(adev, + si_pi->fan_table_start, + (u8 *)(&fan_table), + sizeof(fan_table), + si_pi->sram_end); + + if (ret) { + DRM_ERROR("Failed to load fan table to the SMC."); + adev->pm.dpm.fan.ucode_fan_control = false; + } + + return 0; +} + +static int si_fan_ctrl_start_smc_fan_control(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + PPSMC_Result ret; + + ret = si_send_msg_to_smc(adev, PPSMC_StartFanControl); + if (ret == PPSMC_Result_OK) { + si_pi->fan_is_controlled_by_smc = true; + return 0; + } else { + return -EINVAL; + } +} + +static int si_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + PPSMC_Result ret; + + ret = si_send_msg_to_smc(adev, PPSMC_StopFanControl); + + if (ret == PPSMC_Result_OK) { + si_pi->fan_is_controlled_by_smc = false; + return 0; + } else { + return -EINVAL; + } +} + +static int si_dpm_get_fan_speed_percent(struct amdgpu_device *adev, + u32 *speed) +{ + u32 duty, duty100; + u64 tmp64; + + if (adev->pm.no_fan) + return -ENOENT; + + duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; + duty = (RREG32(CG_THERMAL_STATUS) & FDO_PWM_DUTY_MASK) >> FDO_PWM_DUTY_SHIFT; + + if (duty100 == 0) + return -EINVAL; + + tmp64 = (u64)duty * 100; + do_div(tmp64, duty100); + *speed = (u32)tmp64; + + if (*speed > 100) + *speed = 100; + + return 0; +} + +static int si_dpm_set_fan_speed_percent(struct amdgpu_device *adev, + u32 speed) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + u32 duty, duty100; + u64 tmp64; + + if (adev->pm.no_fan) + return -ENOENT; + + if (si_pi->fan_is_controlled_by_smc) + return -EINVAL; + + if (speed > 100) + return -EINVAL; + + duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; + + if (duty100 == 0) + return -EINVAL; + + tmp64 = (u64)speed * duty100; + do_div(tmp64, 100); + duty = (u32)tmp64; + + tmp = RREG32(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK; + tmp |= FDO_STATIC_DUTY(duty); + WREG32(CG_FDO_CTRL0, tmp); + + return 0; +} + +static void si_dpm_set_fan_control_mode(struct amdgpu_device *adev, u32 mode) +{ + if (mode) { + /* stop auto-manage */ + if (adev->pm.dpm.fan.ucode_fan_control) + si_fan_ctrl_stop_smc_fan_control(adev); + si_fan_ctrl_set_static_mode(adev, mode); + } else { + /* restart auto-manage */ + if (adev->pm.dpm.fan.ucode_fan_control) + si_thermal_start_smc_fan_control(adev); + else + si_fan_ctrl_set_default_mode(adev); + } +} + +static u32 si_dpm_get_fan_control_mode(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + + if (si_pi->fan_is_controlled_by_smc) + return 0; + + tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; + return (tmp >> FDO_PWM_MODE_SHIFT); +} + +#if 0 +static int si_fan_ctrl_get_fan_speed_rpm(struct amdgpu_device *adev, + u32 *speed) +{ + u32 tach_period; + u32 xclk = amdgpu_asic_get_xclk(adev); + + if (adev->pm.no_fan) + return -ENOENT; + + if (adev->pm.fan_pulses_per_revolution == 0) + return -ENOENT; + + tach_period = (RREG32(CG_TACH_STATUS) & TACH_PERIOD_MASK) >> TACH_PERIOD_SHIFT; + if (tach_period == 0) + return -ENOENT; + + *speed = 60 * xclk * 10000 / tach_period; + + return 0; +} + +static int si_fan_ctrl_set_fan_speed_rpm(struct amdgpu_device *adev, + u32 speed) +{ + u32 tach_period, tmp; + u32 xclk = amdgpu_asic_get_xclk(adev); + + if (adev->pm.no_fan) + return -ENOENT; + + if (adev->pm.fan_pulses_per_revolution == 0) + return -ENOENT; + + if ((speed < adev->pm.fan_min_rpm) || + (speed > adev->pm.fan_max_rpm)) + return -EINVAL; + + if (adev->pm.dpm.fan.ucode_fan_control) + si_fan_ctrl_stop_smc_fan_control(adev); + + tach_period = 60 * xclk * 10000 / (8 * speed); + tmp = RREG32(CG_TACH_CTRL) & ~TARGET_PERIOD_MASK; + tmp |= TARGET_PERIOD(tach_period); + WREG32(CG_TACH_CTRL, tmp); + + si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC_RPM); + + return 0; +} +#endif + +static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + + if (!si_pi->fan_ctrl_is_in_default_mode) { + tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK; + tmp |= FDO_PWM_MODE(si_pi->fan_ctrl_default_mode); + WREG32(CG_FDO_CTRL2, tmp); + + tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK; + tmp |= TMIN(si_pi->t_min); + WREG32(CG_FDO_CTRL2, tmp); + si_pi->fan_ctrl_is_in_default_mode = true; + } +} + +static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev) +{ + if (adev->pm.dpm.fan.ucode_fan_control) { + si_fan_ctrl_start_smc_fan_control(adev); + si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC); + } +} + +static void si_thermal_initialize(struct amdgpu_device *adev) +{ + u32 tmp; + + if (adev->pm.fan_pulses_per_revolution) { + tmp = RREG32(CG_TACH_CTRL) & ~EDGE_PER_REV_MASK; + tmp |= EDGE_PER_REV(adev->pm.fan_pulses_per_revolution -1); + WREG32(CG_TACH_CTRL, tmp); + } + + tmp = RREG32(CG_FDO_CTRL2) & ~TACH_PWM_RESP_RATE_MASK; + tmp |= TACH_PWM_RESP_RATE(0x28); + WREG32(CG_FDO_CTRL2, tmp); +} + +static int si_thermal_start_thermal_controller(struct amdgpu_device *adev) +{ + int ret; + + si_thermal_initialize(adev); + ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); + if (ret) + return ret; + ret = si_thermal_enable_alert(adev, true); + if (ret) + return ret; + if (adev->pm.dpm.fan.ucode_fan_control) { + ret = si_halt_smc(adev); + if (ret) + return ret; + ret = si_thermal_setup_fan_table(adev); + if (ret) + return ret; + ret = si_resume_smc(adev); + if (ret) + return ret; + si_thermal_start_smc_fan_control(adev); + } + + return 0; +} + +static void si_thermal_stop_thermal_controller(struct amdgpu_device *adev) +{ + if (!adev->pm.no_fan) { + si_fan_ctrl_set_default_mode(adev); + si_fan_ctrl_stop_smc_fan_control(adev); + } +} + +static int si_dpm_enable(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; + int ret; + + if (si_is_smc_running(adev)) + return -EINVAL; + if (pi->voltage_control || si_pi->voltage_control_svi2) + si_enable_voltage_control(adev, true); + if (pi->mvdd_control) + si_get_mvdd_configuration(adev); + if (pi->voltage_control || si_pi->voltage_control_svi2) { + ret = si_construct_voltage_tables(adev); + if (ret) { + DRM_ERROR("si_construct_voltage_tables failed\n"); + return ret; + } + } + if (eg_pi->dynamic_ac_timing) { + ret = si_initialize_mc_reg_table(adev); + if (ret) + eg_pi->dynamic_ac_timing = false; + } + if (pi->dynamic_ss) + si_enable_spread_spectrum(adev, true); + if (pi->thermal_protection) + si_enable_thermal_protection(adev, true); + si_setup_bsp(adev); + si_program_git(adev); + si_program_tp(adev); + si_program_tpp(adev); + si_program_sstp(adev); + si_enable_display_gap(adev); + si_program_vc(adev); + ret = si_upload_firmware(adev); + if (ret) { + DRM_ERROR("si_upload_firmware failed\n"); + return ret; + } + ret = si_process_firmware_header(adev); + if (ret) { + DRM_ERROR("si_process_firmware_header failed\n"); + return ret; + } + ret = si_initial_switch_from_arb_f0_to_f1(adev); + if (ret) { + DRM_ERROR("si_initial_switch_from_arb_f0_to_f1 failed\n"); + return ret; + } + ret = si_init_smc_table(adev); + if (ret) { + DRM_ERROR("si_init_smc_table failed\n"); + return ret; + } + ret = si_init_smc_spll_table(adev); + if (ret) { + DRM_ERROR("si_init_smc_spll_table failed\n"); + return ret; + } + ret = si_init_arb_table_index(adev); + if (ret) { + DRM_ERROR("si_init_arb_table_index failed\n"); + return ret; + } + if (eg_pi->dynamic_ac_timing) { + ret = si_populate_mc_reg_table(adev, boot_ps); + if (ret) { + DRM_ERROR("si_populate_mc_reg_table failed\n"); + return ret; + } + } + ret = si_initialize_smc_cac_tables(adev); + if (ret) { + DRM_ERROR("si_initialize_smc_cac_tables failed\n"); + return ret; + } + ret = si_initialize_hardware_cac_manager(adev); + if (ret) { + DRM_ERROR("si_initialize_hardware_cac_manager failed\n"); + return ret; + } + ret = si_initialize_smc_dte_tables(adev); + if (ret) { + DRM_ERROR("si_initialize_smc_dte_tables failed\n"); + return ret; + } + ret = si_populate_smc_tdp_limits(adev, boot_ps); + if (ret) { + DRM_ERROR("si_populate_smc_tdp_limits failed\n"); + return ret; + } + ret = si_populate_smc_tdp_limits_2(adev, boot_ps); + if (ret) { + DRM_ERROR("si_populate_smc_tdp_limits_2 failed\n"); + return ret; + } + si_program_response_times(adev); + si_program_ds_registers(adev); + si_dpm_start_smc(adev); + ret = si_notify_smc_display_change(adev, false); + if (ret) { + DRM_ERROR("si_notify_smc_display_change failed\n"); + return ret; + } + si_enable_sclk_control(adev, true); + si_start_dpm(adev); + + si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true); + + si_thermal_start_thermal_controller(adev); + + ni_update_current_ps(adev, boot_ps); + + return 0; +} + +static int si_set_temperature_range(struct amdgpu_device *adev) +{ + int ret; + + ret = si_thermal_enable_alert(adev, false); + if (ret) + return ret; + ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); + if (ret) + return ret; + ret = si_thermal_enable_alert(adev, true); + if (ret) + return ret; + + return ret; +} + +static void si_dpm_disable(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; + + if (!si_is_smc_running(adev)) + return; + si_thermal_stop_thermal_controller(adev); + si_disable_ulv(adev); + si_clear_vc(adev); + if (pi->thermal_protection) + si_enable_thermal_protection(adev, false); + si_enable_power_containment(adev, boot_ps, false); + si_enable_smc_cac(adev, boot_ps, false); + si_enable_spread_spectrum(adev, false); + si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, false); + si_stop_dpm(adev); + si_reset_to_default(adev); + si_dpm_stop_smc(adev); + si_force_switch_to_arb_f0(adev); + + ni_update_current_ps(adev, boot_ps); +} + +static int si_dpm_pre_set_power_state(struct amdgpu_device *adev) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; + struct amdgpu_ps *new_ps = &requested_ps; + + ni_update_requested_ps(adev, new_ps); + + si_apply_state_adjust_rules(adev, &eg_pi->requested_rps); + + return 0; +} + +static int si_power_control_set_level(struct amdgpu_device *adev) +{ + struct amdgpu_ps *new_ps = adev->pm.dpm.requested_ps; + int ret; + + ret = si_restrict_performance_levels_before_switch(adev); + if (ret) + return ret; + ret = si_halt_smc(adev); + if (ret) + return ret; + ret = si_populate_smc_tdp_limits(adev, new_ps); + if (ret) + return ret; + ret = si_populate_smc_tdp_limits_2(adev, new_ps); + if (ret) + return ret; + ret = si_resume_smc(adev); + if (ret) + return ret; + ret = si_set_sw_state(adev); + if (ret) + return ret; + return 0; +} + +static int si_dpm_set_power_state(struct amdgpu_device *adev) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps *new_ps = &eg_pi->requested_rps; + struct amdgpu_ps *old_ps = &eg_pi->current_rps; + int ret; + + ret = si_disable_ulv(adev); + if (ret) { + DRM_ERROR("si_disable_ulv failed\n"); + return ret; + } + ret = si_restrict_performance_levels_before_switch(adev); + if (ret) { + DRM_ERROR("si_restrict_performance_levels_before_switch failed\n"); + return ret; + } + if (eg_pi->pcie_performance_request) + si_request_link_speed_change_before_state_change(adev, new_ps, old_ps); + ni_set_uvd_clock_before_set_eng_clock(adev, new_ps, old_ps); + ret = si_enable_power_containment(adev, new_ps, false); + if (ret) { + DRM_ERROR("si_enable_power_containment failed\n"); + return ret; + } + ret = si_enable_smc_cac(adev, new_ps, false); + if (ret) { + DRM_ERROR("si_enable_smc_cac failed\n"); + return ret; + } + ret = si_halt_smc(adev); + if (ret) { + DRM_ERROR("si_halt_smc failed\n"); + return ret; + } + ret = si_upload_sw_state(adev, new_ps); + if (ret) { + DRM_ERROR("si_upload_sw_state failed\n"); + return ret; + } + ret = si_upload_smc_data(adev); + if (ret) { + DRM_ERROR("si_upload_smc_data failed\n"); + return ret; + } + ret = si_upload_ulv_state(adev); + if (ret) { + DRM_ERROR("si_upload_ulv_state failed\n"); + return ret; + } + if (eg_pi->dynamic_ac_timing) { + ret = si_upload_mc_reg_table(adev, new_ps); + if (ret) { + DRM_ERROR("si_upload_mc_reg_table failed\n"); + return ret; + } + } + ret = si_program_memory_timing_parameters(adev, new_ps); + if (ret) { + DRM_ERROR("si_program_memory_timing_parameters failed\n"); + return ret; + } + si_set_pcie_lane_width_in_smc(adev, new_ps, old_ps); + + ret = si_resume_smc(adev); + if (ret) { + DRM_ERROR("si_resume_smc failed\n"); + return ret; + } + ret = si_set_sw_state(adev); + if (ret) { + DRM_ERROR("si_set_sw_state failed\n"); + return ret; + } + ni_set_uvd_clock_after_set_eng_clock(adev, new_ps, old_ps); + if (eg_pi->pcie_performance_request) + si_notify_link_speed_change_after_state_change(adev, new_ps, old_ps); + ret = si_set_power_state_conditionally_enable_ulv(adev, new_ps); + if (ret) { + DRM_ERROR("si_set_power_state_conditionally_enable_ulv failed\n"); + return ret; + } + ret = si_enable_smc_cac(adev, new_ps, true); + if (ret) { + DRM_ERROR("si_enable_smc_cac failed\n"); + return ret; + } + ret = si_enable_power_containment(adev, new_ps, true); + if (ret) { + DRM_ERROR("si_enable_power_containment failed\n"); + return ret; + } + + ret = si_power_control_set_level(adev); + if (ret) { + DRM_ERROR("si_power_control_set_level failed\n"); + return ret; + } + + return 0; +} + +static void si_dpm_post_set_power_state(struct amdgpu_device *adev) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps *new_ps = &eg_pi->requested_rps; + + ni_update_current_ps(adev, new_ps); +} + +#if 0 +void si_dpm_reset_asic(struct amdgpu_device *adev) +{ + si_restrict_performance_levels_before_switch(adev); + si_disable_ulv(adev); + si_set_boot_state(adev); +} +#endif + +static void si_dpm_display_configuration_changed(struct amdgpu_device *adev) +{ + si_program_display_gap(adev); +} + + +static void si_parse_pplib_non_clock_info(struct amdgpu_device *adev, + struct amdgpu_ps *rps, + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, + u8 table_rev) +{ + rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); + rps->class = le16_to_cpu(non_clock_info->usClassification); + rps->class2 = le16_to_cpu(non_clock_info->usClassification2); + + if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { + rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); + rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); + } else if (r600_is_uvd_state(rps->class, rps->class2)) { + rps->vclk = RV770_DEFAULT_VCLK_FREQ; + rps->dclk = RV770_DEFAULT_DCLK_FREQ; + } else { + rps->vclk = 0; + rps->dclk = 0; + } + + if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) + adev->pm.dpm.boot_ps = rps; + if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + adev->pm.dpm.uvd_ps = rps; +} + +static void si_parse_pplib_clock_info(struct amdgpu_device *adev, + struct amdgpu_ps *rps, int index, + union pplib_clock_info *clock_info) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ps *ps = si_get_ps(rps); + u16 leakage_voltage; + struct rv7xx_pl *pl = &ps->performance_levels[index]; + int ret; + + ps->performance_level_count = index + 1; + + pl->sclk = le16_to_cpu(clock_info->si.usEngineClockLow); + pl->sclk |= clock_info->si.ucEngineClockHigh << 16; + pl->mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); + pl->mclk |= clock_info->si.ucMemoryClockHigh << 16; + + pl->vddc = le16_to_cpu(clock_info->si.usVDDC); + pl->vddci = le16_to_cpu(clock_info->si.usVDDCI); + pl->flags = le32_to_cpu(clock_info->si.ulFlags); + pl->pcie_gen = r600_get_pcie_gen_support(adev, + si_pi->sys_pcie_mask, + si_pi->boot_pcie_gen, + clock_info->si.ucPCIEGen); + + /* patch up vddc if necessary */ + ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc, + &leakage_voltage); + if (ret == 0) + pl->vddc = leakage_voltage; + + if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) { + pi->acpi_vddc = pl->vddc; + eg_pi->acpi_vddci = pl->vddci; + si_pi->acpi_pcie_gen = pl->pcie_gen; + } + + if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) && + index == 0) { + /* XXX disable for A0 tahiti */ + si_pi->ulv.supported = false; + si_pi->ulv.pl = *pl; + si_pi->ulv.one_pcie_lane_in_ulv = false; + si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT; + si_pi->ulv.cg_ulv_parameter = SISLANDS_CGULVPARAMETER_DFLT; + si_pi->ulv.cg_ulv_control = SISLANDS_CGULVCONTROL_DFLT; + } + + if (pi->min_vddc_in_table > pl->vddc) + pi->min_vddc_in_table = pl->vddc; + + if (pi->max_vddc_in_table < pl->vddc) + pi->max_vddc_in_table = pl->vddc; + + /* patch up boot state */ + if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { + u16 vddc, vddci, mvdd; + amdgpu_atombios_get_default_voltages(adev, &vddc, &vddci, &mvdd); + pl->mclk = adev->clock.default_mclk; + pl->sclk = adev->clock.default_sclk; + pl->vddc = vddc; + pl->vddci = vddci; + si_pi->mvdd_bootup_value = mvdd; + } + + if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == + ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk; + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk; + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc; + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci; + } +} + +union pplib_power_state { + struct _ATOM_PPLIB_STATE v1; + struct _ATOM_PPLIB_STATE_V2 v2; +}; + +static int si_parse_power_table(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; + union pplib_power_state *power_state; + int i, j, k, non_clock_array_index, clock_array_index; + union pplib_clock_info *clock_info; + struct _StateArray *state_array; + struct _ClockInfoArray *clock_info_array; + struct _NonClockInfoArray *non_clock_info_array; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + u8 *power_state_offset; + struct si_ps *ps; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return -EINVAL; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + amdgpu_add_thermal_controller(adev); + + state_array = (struct _StateArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usStateArrayOffset)); + clock_info_array = (struct _ClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); + non_clock_info_array = (struct _NonClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); + + adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) * + state_array->ucNumEntries, GFP_KERNEL); + if (!adev->pm.dpm.ps) + return -ENOMEM; + power_state_offset = (u8 *)state_array->states; + for (i = 0; i < state_array->ucNumEntries; i++) { + u8 *idx; + power_state = (union pplib_power_state *)power_state_offset; + non_clock_array_index = power_state->v2.nonClockInfoIndex; + non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) + &non_clock_info_array->nonClockInfo[non_clock_array_index]; + ps = kzalloc(sizeof(struct si_ps), GFP_KERNEL); + if (ps == NULL) { + kfree(adev->pm.dpm.ps); + return -ENOMEM; + } + adev->pm.dpm.ps[i].ps_priv = ps; + si_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i], + non_clock_info, + non_clock_info_array->ucEntrySize); + k = 0; + idx = (u8 *)&power_state->v2.clockInfoIndex[0]; + for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { + clock_array_index = idx[j]; + if (clock_array_index >= clock_info_array->ucNumEntries) + continue; + if (k >= SISLANDS_MAX_HARDWARE_POWERLEVELS) + break; + clock_info = (union pplib_clock_info *) + ((u8 *)&clock_info_array->clockInfo[0] + + (clock_array_index * clock_info_array->ucEntrySize)); + si_parse_pplib_clock_info(adev, + &adev->pm.dpm.ps[i], k, + clock_info); + k++; + } + power_state_offset += 2 + power_state->v2.ucNumDPMLevels; + } + adev->pm.dpm.num_ps = state_array->ucNumEntries; + + /* fill in the vce power states */ + for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) { + u32 sclk, mclk; + clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; + clock_info = (union pplib_clock_info *) + &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; + sclk = le16_to_cpu(clock_info->si.usEngineClockLow); + sclk |= clock_info->si.ucEngineClockHigh << 16; + mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); + mclk |= clock_info->si.ucMemoryClockHigh << 16; + adev->pm.dpm.vce_states[i].sclk = sclk; + adev->pm.dpm.vce_states[i].mclk = mclk; + } + + return 0; +} + +static int si_dpm_init(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi; + struct evergreen_power_info *eg_pi; + struct ni_power_info *ni_pi; + struct si_power_info *si_pi; + struct atom_clock_dividers dividers; + int ret; + u32 mask; + + si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL); + if (si_pi == NULL) + return -ENOMEM; + adev->pm.dpm.priv = si_pi; + ni_pi = &si_pi->ni; + eg_pi = &ni_pi->eg; + pi = &eg_pi->rv7xx; + + ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); + if (ret) + si_pi->sys_pcie_mask = 0; + else + si_pi->sys_pcie_mask = mask; + si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; + si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev); + + si_set_max_cu_value(adev); + + rv770_get_max_vddc(adev); + si_get_leakage_vddc(adev); + si_patch_dependency_tables_based_on_leakage(adev); + + pi->acpi_vddc = 0; + eg_pi->acpi_vddci = 0; + pi->min_vddc_in_table = 0; + pi->max_vddc_in_table = 0; + + ret = amdgpu_get_platform_caps(adev); + if (ret) + return ret; + + ret = amdgpu_parse_extended_power_table(adev); + if (ret) + return ret; + + ret = si_parse_power_table(adev); + if (ret) + return ret; + + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = + kzalloc(4 * sizeof(struct amdgpu_clock_voltage_dependency_entry), GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900; + + if (adev->pm.dpm.voltage_response_time == 0) + adev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT; + if (adev->pm.dpm.backbias_response_time == 0) + adev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT; + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + 0, false, ÷rs); + if (ret) + pi->ref_div = dividers.ref_div + 1; + else + pi->ref_div = R600_REFERENCEDIVIDER_DFLT; + + eg_pi->smu_uvd_hs = false; + + pi->mclk_strobe_mode_threshold = 40000; + if (si_is_special_1gb_platform(adev)) + pi->mclk_stutter_mode_threshold = 0; + else + pi->mclk_stutter_mode_threshold = pi->mclk_strobe_mode_threshold; + pi->mclk_edc_enable_threshold = 40000; + eg_pi->mclk_edc_wr_enable_threshold = 40000; + + ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold; + + pi->voltage_control = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, + VOLTAGE_OBJ_GPIO_LUT); + if (!pi->voltage_control) { + si_pi->voltage_control_svi2 = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, + VOLTAGE_OBJ_SVID2); + if (si_pi->voltage_control_svi2) + amdgpu_atombios_get_svi2_info(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, + &si_pi->svd_gpio_id, &si_pi->svc_gpio_id); + } + + pi->mvdd_control = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_MVDDC, + VOLTAGE_OBJ_GPIO_LUT); + + eg_pi->vddci_control = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI, + VOLTAGE_OBJ_GPIO_LUT); + if (!eg_pi->vddci_control) + si_pi->vddci_control_svi2 = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI, + VOLTAGE_OBJ_SVID2); + + si_pi->vddc_phase_shed_control = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, + VOLTAGE_OBJ_PHASE_LUT); + + rv770_get_engine_memory_ss(adev); + + pi->asi = RV770_ASI_DFLT; + pi->pasi = CYPRESS_HASI_DFLT; + pi->vrc = SISLANDS_VRC_DFLT; + + pi->gfx_clock_gating = true; + + eg_pi->sclk_deep_sleep = true; + si_pi->sclk_deep_sleep_above_low = false; + + if (adev->pm.int_thermal_type != THERMAL_TYPE_NONE) + pi->thermal_protection = true; + else + pi->thermal_protection = false; + + eg_pi->dynamic_ac_timing = true; + + eg_pi->light_sleep = true; +#if defined(CONFIG_ACPI) + eg_pi->pcie_performance_request = + amdgpu_acpi_is_pcie_performance_request_supported(adev); +#else + eg_pi->pcie_performance_request = false; +#endif + + si_pi->sram_end = SMC_RAM_END; + + adev->pm.dpm.dyn_state.mclk_sclk_ratio = 4; + adev->pm.dpm.dyn_state.sclk_mclk_delta = 15000; + adev->pm.dpm.dyn_state.vddc_vddci_delta = 200; + adev->pm.dpm.dyn_state.valid_sclk_values.count = 0; + adev->pm.dpm.dyn_state.valid_sclk_values.values = NULL; + adev->pm.dpm.dyn_state.valid_mclk_values.count = 0; + adev->pm.dpm.dyn_state.valid_mclk_values.values = NULL; + + si_initialize_powertune_defaults(adev); + + /* make sure dc limits are valid */ + if ((adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) || + (adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0)) + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc = + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; + + si_pi->fan_ctrl_is_in_default_mode = true; + + return 0; +} + +static void si_dpm_fini(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < adev->pm.dpm.num_ps; i++) { + kfree(adev->pm.dpm.ps[i].ps_priv); + } + kfree(adev->pm.dpm.ps); + kfree(adev->pm.dpm.priv); + kfree(adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries); + amdgpu_free_extended_power_table(adev); +} + +static void si_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, + struct seq_file *m) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps *rps = &eg_pi->current_rps; + struct si_ps *ps = si_get_ps(rps); + struct rv7xx_pl *pl; + u32 current_index = + (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >> + CURRENT_STATE_INDEX_SHIFT; + + if (current_index >= ps->performance_level_count) { + seq_printf(m, "invalid dpm profile %d\n", current_index); + } else { + pl = &ps->performance_levels[current_index]; + seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", + current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); + } +} + +static int si_dpm_set_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 cg_thermal_int; + + switch (type) { + case AMDGPU_THERMAL_IRQ_LOW_TO_HIGH: + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); + cg_thermal_int |= THERM_INT_MASK_HIGH; + WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); + cg_thermal_int &= ~THERM_INT_MASK_HIGH; + WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); + break; + default: + break; + } + break; + + case AMDGPU_THERMAL_IRQ_HIGH_TO_LOW: + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); + cg_thermal_int |= THERM_INT_MASK_LOW; + WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); + cg_thermal_int &= ~THERM_INT_MASK_LOW; + WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); + break; + default: + break; + } + break; + + default: + break; + } + return 0; +} + +static int si_dpm_process_interrupt(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + bool queue_thermal = false; + + if (entry == NULL) + return -EINVAL; + + switch (entry->src_id) { + case 230: /* thermal low to high */ + DRM_DEBUG("IH: thermal low to high\n"); + adev->pm.dpm.thermal.high_to_low = false; + queue_thermal = true; + break; + case 231: /* thermal high to low */ + DRM_DEBUG("IH: thermal high to low\n"); + adev->pm.dpm.thermal.high_to_low = true; + queue_thermal = true; + break; + default: + break; + } + + if (queue_thermal) + schedule_work(&adev->pm.dpm.thermal.work); + + return 0; +} + +static int si_dpm_late_init(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (!amdgpu_dpm) + return 0; + + /* init the sysfs and debugfs files late */ + ret = amdgpu_pm_sysfs_init(adev); + if (ret) + return ret; + + ret = si_set_temperature_range(adev); + if (ret) + return ret; +#if 0 //TODO ? + si_dpm_powergate_uvd(adev, true); +#endif + return 0; +} + +/** + * si_dpm_init_microcode - load ucode images from disk + * + * @adev: amdgpu_device pointer + * + * Use the firmware interface to load the ucode images into + * the driver (not loaded into hw). + * Returns 0 on success, error on failure. + */ +static int si_dpm_init_microcode(struct amdgpu_device *adev) +{ + const char *chip_name; + char fw_name[30]; + int err; + + DRM_DEBUG("\n"); + switch (adev->asic_type) { + case CHIP_TAHITI: + chip_name = "tahiti"; + break; + case CHIP_PITCAIRN: + chip_name = "pitcairn"; + break; + case CHIP_VERDE: + chip_name = "verde"; + break; + case CHIP_OLAND: + chip_name = "oland"; + break; + case CHIP_HAINAN: + chip_name = "hainan"; + break; + default: BUG(); + } + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); + err = request_firmware(&adev->pm.fw, fw_name, adev->dev); + if (err) + goto out; + err = amdgpu_ucode_validate(adev->pm.fw); + +out: + if (err) { + printk(KERN_ERR + "si_smc: Failed to load firmware. err = %d\"%s\"\n", + err, fw_name); + release_firmware(adev->pm.fw); + adev->pm.fw = NULL; + } + return err; + +} + +static int si_dpm_sw_init(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + ret = amdgpu_irq_add_id(adev, 230, &adev->pm.dpm.thermal.irq); + if (ret) + return ret; + + ret = amdgpu_irq_add_id(adev, 231, &adev->pm.dpm.thermal.irq); + if (ret) + return ret; + + /* default to balanced state */ + adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED; + adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; + adev->pm.dpm.forced_level = AMDGPU_DPM_FORCED_LEVEL_AUTO; + adev->pm.default_sclk = adev->clock.default_sclk; + adev->pm.default_mclk = adev->clock.default_mclk; + adev->pm.current_sclk = adev->clock.default_sclk; + adev->pm.current_mclk = adev->clock.default_mclk; + adev->pm.int_thermal_type = THERMAL_TYPE_NONE; + + if (amdgpu_dpm == 0) + return 0; + + ret = si_dpm_init_microcode(adev); + if (ret) + return ret; + + INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); + mutex_lock(&adev->pm.mutex); + ret = si_dpm_init(adev); + if (ret) + goto dpm_failed; + adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + if (amdgpu_dpm == 1) + amdgpu_pm_print_power_states(adev); + mutex_unlock(&adev->pm.mutex); + DRM_INFO("amdgpu: dpm initialized\n"); + + return 0; + +dpm_failed: + si_dpm_fini(adev); + mutex_unlock(&adev->pm.mutex); + DRM_ERROR("amdgpu: dpm initialization failed\n"); + return ret; +} + +static int si_dpm_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + mutex_lock(&adev->pm.mutex); + amdgpu_pm_sysfs_fini(adev); + si_dpm_fini(adev); + mutex_unlock(&adev->pm.mutex); + + return 0; +} + +static int si_dpm_hw_init(void *handle) +{ + int ret; + + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (!amdgpu_dpm) + return 0; + + mutex_lock(&adev->pm.mutex); + si_dpm_setup_asic(adev); + ret = si_dpm_enable(adev); + if (ret) + adev->pm.dpm_enabled = false; + else + adev->pm.dpm_enabled = true; + mutex_unlock(&adev->pm.mutex); + + return ret; +} + +static int si_dpm_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + si_dpm_disable(adev); + mutex_unlock(&adev->pm.mutex); + } + + return 0; +} + +static int si_dpm_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + /* disable dpm */ + si_dpm_disable(adev); + /* reset the power state */ + adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + mutex_unlock(&adev->pm.mutex); + } + return 0; +} + +static int si_dpm_resume(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + /* asic init will reset to the boot state */ + mutex_lock(&adev->pm.mutex); + si_dpm_setup_asic(adev); + ret = si_dpm_enable(adev); + if (ret) + adev->pm.dpm_enabled = false; + else + adev->pm.dpm_enabled = true; + mutex_unlock(&adev->pm.mutex); + if (adev->pm.dpm_enabled) + amdgpu_pm_compute_clocks(adev); + } + return 0; +} + +static bool si_dpm_is_idle(void *handle) +{ + /* XXX */ + return true; +} + +static int si_dpm_wait_for_idle(void *handle) +{ + /* XXX */ + return 0; +} + +static int si_dpm_soft_reset(void *handle) +{ + return 0; +} + +static int si_dpm_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int si_dpm_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +/* get temperature in millidegrees */ +static int si_dpm_get_temp(struct amdgpu_device *adev) +{ + u32 temp; + int actual_temp = 0; + + temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >> + CTF_TEMP_SHIFT; + + if (temp & 0x200) + actual_temp = 255; + else + actual_temp = temp & 0x1ff; + + actual_temp = (actual_temp * 1000); + + return actual_temp; +} + +static u32 si_dpm_get_sclk(struct amdgpu_device *adev, bool low) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); + + if (low) + return requested_state->performance_levels[0].sclk; + else + return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk; +} + +static u32 si_dpm_get_mclk(struct amdgpu_device *adev, bool low) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); + + if (low) + return requested_state->performance_levels[0].mclk; + else + return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk; +} + +static void si_dpm_print_power_state(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct si_ps *ps = si_get_ps(rps); + struct rv7xx_pl *pl; + int i; + + amdgpu_dpm_print_class_info(rps->class, rps->class2); + amdgpu_dpm_print_cap_info(rps->caps); + printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + for (i = 0; i < ps->performance_level_count; i++) { + pl = &ps->performance_levels[i]; + if (adev->asic_type >= CHIP_TAHITI) + printk("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", + i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); + else + printk("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u\n", + i, pl->sclk, pl->mclk, pl->vddc, pl->vddci); + } + amdgpu_dpm_print_ps_status(adev, rps); +} + +static int si_dpm_early_init(void *handle) +{ + + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + si_dpm_set_dpm_funcs(adev); + si_dpm_set_irq_funcs(adev); + return 0; +} + + +const struct amd_ip_funcs si_dpm_ip_funcs = { + .name = "si_dpm", + .early_init = si_dpm_early_init, + .late_init = si_dpm_late_init, + .sw_init = si_dpm_sw_init, + .sw_fini = si_dpm_sw_fini, + .hw_init = si_dpm_hw_init, + .hw_fini = si_dpm_hw_fini, + .suspend = si_dpm_suspend, + .resume = si_dpm_resume, + .is_idle = si_dpm_is_idle, + .wait_for_idle = si_dpm_wait_for_idle, + .soft_reset = si_dpm_soft_reset, + .set_clockgating_state = si_dpm_set_clockgating_state, + .set_powergating_state = si_dpm_set_powergating_state, +}; + +static const struct amdgpu_dpm_funcs si_dpm_funcs = { + .get_temperature = &si_dpm_get_temp, + .pre_set_power_state = &si_dpm_pre_set_power_state, + .set_power_state = &si_dpm_set_power_state, + .post_set_power_state = &si_dpm_post_set_power_state, + .display_configuration_changed = &si_dpm_display_configuration_changed, + .get_sclk = &si_dpm_get_sclk, + .get_mclk = &si_dpm_get_mclk, + .print_power_state = &si_dpm_print_power_state, + .debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level, + .force_performance_level = &si_dpm_force_performance_level, + .vblank_too_short = &si_dpm_vblank_too_short, + .set_fan_control_mode = &si_dpm_set_fan_control_mode, + .get_fan_control_mode = &si_dpm_get_fan_control_mode, + .set_fan_speed_percent = &si_dpm_set_fan_speed_percent, + .get_fan_speed_percent = &si_dpm_get_fan_speed_percent, +}; + +static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev) +{ + if (adev->pm.funcs == NULL) + adev->pm.funcs = &si_dpm_funcs; +} + +static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = { + .set = si_dpm_set_interrupt_state, + .process = si_dpm_process_interrupt, +}; + +static void si_dpm_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; + adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs; +} + diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.h b/drivers/gpu/drm/amd/amdgpu/si_dpm.h new file mode 100644 index 0000000..51ce21c --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.h @@ -0,0 +1,1015 @@ +/* + * Copyright 2012 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __SI_DPM_H__ +#define __SI_DPM_H__ + +#include "amdgpu_atombios.h" +#include "sislands_smc.h" + +#define MC_CG_CONFIG 0x96f +#define MC_ARB_CG 0x9fa +#define CG_ARB_REQ(x) ((x) << 0) +#define CG_ARB_REQ_MASK (0xff << 0) + +#define MC_ARB_DRAM_TIMING_1 0x9fc +#define MC_ARB_DRAM_TIMING_2 0x9fd +#define MC_ARB_DRAM_TIMING_3 0x9fe +#define MC_ARB_DRAM_TIMING2_1 0x9ff +#define MC_ARB_DRAM_TIMING2_2 0xa00 +#define MC_ARB_DRAM_TIMING2_3 0xa01 + +#define MAX_NO_OF_MVDD_VALUES 2 +#define MAX_NO_VREG_STEPS 32 +#define NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 +#define SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE 32 +#define SMC_NISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20 +#define RV770_ASI_DFLT 1000 +#define CYPRESS_HASI_DFLT 400000 +#define PCIE_PERF_REQ_PECI_GEN1 2 +#define PCIE_PERF_REQ_PECI_GEN2 3 +#define PCIE_PERF_REQ_PECI_GEN3 4 +#define RV770_DEFAULT_VCLK_FREQ 53300 /* 10 khz */ +#define RV770_DEFAULT_DCLK_FREQ 40000 /* 10 khz */ + +#define SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE 16 + +#define RV770_SMC_TABLE_ADDRESS 0xB000 +#define RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 3 + +#define SMC_STROBE_RATIO 0x0F +#define SMC_STROBE_ENABLE 0x10 + +#define SMC_MC_EDC_RD_FLAG 0x01 +#define SMC_MC_EDC_WR_FLAG 0x02 +#define SMC_MC_RTT_ENABLE 0x04 +#define SMC_MC_STUTTER_EN 0x08 + +#define RV770_SMC_VOLTAGEMASK_VDDC 0 +#define RV770_SMC_VOLTAGEMASK_MVDD 1 +#define RV770_SMC_VOLTAGEMASK_VDDCI 2 +#define RV770_SMC_VOLTAGEMASK_MAX 4 + +#define NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 +#define NISLANDS_SMC_STROBE_RATIO 0x0F +#define NISLANDS_SMC_STROBE_ENABLE 0x10 + +#define NISLANDS_SMC_MC_EDC_RD_FLAG 0x01 +#define NISLANDS_SMC_MC_EDC_WR_FLAG 0x02 +#define NISLANDS_SMC_MC_RTT_ENABLE 0x04 +#define NISLANDS_SMC_MC_STUTTER_EN 0x08 + +#define MAX_NO_VREG_STEPS 32 + +#define NISLANDS_SMC_VOLTAGEMASK_VDDC 0 +#define NISLANDS_SMC_VOLTAGEMASK_MVDD 1 +#define NISLANDS_SMC_VOLTAGEMASK_VDDCI 2 +#define NISLANDS_SMC_VOLTAGEMASK_MAX 4 + +#define SISLANDS_MCREGISTERTABLE_INITIAL_SLOT 0 +#define SISLANDS_MCREGISTERTABLE_ACPI_SLOT 1 +#define SISLANDS_MCREGISTERTABLE_ULV_SLOT 2 +#define SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT 3 + +#define SISLANDS_LEAKAGE_INDEX0 0xff01 +#define SISLANDS_MAX_LEAKAGE_COUNT 4 + +#define SISLANDS_MAX_HARDWARE_POWERLEVELS 5 +#define SISLANDS_INITIAL_STATE_ARB_INDEX 0 +#define SISLANDS_ACPI_STATE_ARB_INDEX 1 +#define SISLANDS_ULV_STATE_ARB_INDEX 2 +#define SISLANDS_DRIVER_STATE_ARB_INDEX 3 + +#define SISLANDS_DPM2_MAX_PULSE_SKIP 256 + +#define SISLANDS_DPM2_NEAR_TDP_DEC 10 +#define SISLANDS_DPM2_ABOVE_SAFE_INC 5 +#define SISLANDS_DPM2_BELOW_SAFE_INC 20 + +#define SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT 80 + +#define SISLANDS_DPM2_MAXPS_PERCENT_H 99 +#define SISLANDS_DPM2_MAXPS_PERCENT_M 99 + +#define SISLANDS_DPM2_SQ_RAMP_MAX_POWER 0x3FFF +#define SISLANDS_DPM2_SQ_RAMP_MIN_POWER 0x12 +#define SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 +#define SISLANDS_DPM2_SQ_RAMP_STI_SIZE 0x1E +#define SISLANDS_DPM2_SQ_RAMP_LTI_RATIO 0xF + +#define SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN 10 + +#define SISLANDS_VRC_DFLT 0xC000B3 +#define SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT 1687 +#define SISLANDS_CGULVPARAMETER_DFLT 0x00040035 +#define SISLANDS_CGULVCONTROL_DFLT 0x1f007550 + +#define SI_ASI_DFLT 10000 +#define SI_BSP_DFLT 0x41EB +#define SI_BSU_DFLT 0x2 +#define SI_AH_DFLT 5 +#define SI_RLP_DFLT 25 +#define SI_RMP_DFLT 65 +#define SI_LHP_DFLT 40 +#define SI_LMP_DFLT 15 +#define SI_TD_DFLT 0 +#define SI_UTC_DFLT_00 0x24 +#define SI_UTC_DFLT_01 0x22 +#define SI_UTC_DFLT_02 0x22 +#define SI_UTC_DFLT_03 0x22 +#define SI_UTC_DFLT_04 0x22 +#define SI_UTC_DFLT_05 0x22 +#define SI_UTC_DFLT_06 0x22 +#define SI_UTC_DFLT_07 0x22 +#define SI_UTC_DFLT_08 0x22 +#define SI_UTC_DFLT_09 0x22 +#define SI_UTC_DFLT_10 0x22 +#define SI_UTC_DFLT_11 0x22 +#define SI_UTC_DFLT_12 0x22 +#define SI_UTC_DFLT_13 0x22 +#define SI_UTC_DFLT_14 0x22 +#define SI_DTC_DFLT_00 0x24 +#define SI_DTC_DFLT_01 0x22 +#define SI_DTC_DFLT_02 0x22 +#define SI_DTC_DFLT_03 0x22 +#define SI_DTC_DFLT_04 0x22 +#define SI_DTC_DFLT_05 0x22 +#define SI_DTC_DFLT_06 0x22 +#define SI_DTC_DFLT_07 0x22 +#define SI_DTC_DFLT_08 0x22 +#define SI_DTC_DFLT_09 0x22 +#define SI_DTC_DFLT_10 0x22 +#define SI_DTC_DFLT_11 0x22 +#define SI_DTC_DFLT_12 0x22 +#define SI_DTC_DFLT_13 0x22 +#define SI_DTC_DFLT_14 0x22 +#define SI_VRC_DFLT 0x0000C003 +#define SI_VOLTAGERESPONSETIME_DFLT 1000 +#define SI_BACKBIASRESPONSETIME_DFLT 1000 +#define SI_VRU_DFLT 0x3 +#define SI_SPLLSTEPTIME_DFLT 0x1000 +#define SI_SPLLSTEPUNIT_DFLT 0x3 +#define SI_TPU_DFLT 0 +#define SI_TPC_DFLT 0x200 +#define SI_SSTU_DFLT 0 +#define SI_SST_DFLT 0x00C8 +#define SI_GICST_DFLT 0x200 +#define SI_FCT_DFLT 0x0400 +#define SI_FCTU_DFLT 0 +#define SI_CTXCGTT3DRPHC_DFLT 0x20 +#define SI_CTXCGTT3DRSDC_DFLT 0x40 +#define SI_VDDC3DOORPHC_DFLT 0x100 +#define SI_VDDC3DOORSDC_DFLT 0x7 +#define SI_VDDC3DOORSU_DFLT 0 +#define SI_MPLLLOCKTIME_DFLT 100 +#define SI_MPLLRESETTIME_DFLT 150 +#define SI_VCOSTEPPCT_DFLT 20 +#define SI_ENDINGVCOSTEPPCT_DFLT 5 +#define SI_REFERENCEDIVIDER_DFLT 4 + +#define SI_PM_NUMBER_OF_TC 15 +#define SI_PM_NUMBER_OF_SCLKS 20 +#define SI_PM_NUMBER_OF_MCLKS 4 +#define SI_PM_NUMBER_OF_VOLTAGE_LEVELS 4 +#define SI_PM_NUMBER_OF_ACTIVITY_LEVELS 3 + +/* XXX are these ok? */ +#define SI_TEMP_RANGE_MIN (90 * 1000) +#define SI_TEMP_RANGE_MAX (120 * 1000) + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + +enum ni_dc_cac_level +{ + NISLANDS_DCCAC_LEVEL_0 = 0, + NISLANDS_DCCAC_LEVEL_1, + NISLANDS_DCCAC_LEVEL_2, + NISLANDS_DCCAC_LEVEL_3, + NISLANDS_DCCAC_LEVEL_4, + NISLANDS_DCCAC_LEVEL_5, + NISLANDS_DCCAC_LEVEL_6, + NISLANDS_DCCAC_LEVEL_7, + NISLANDS_DCCAC_MAX_LEVELS +}; + +enum si_cac_config_reg_type +{ + SISLANDS_CACCONFIG_MMR = 0, + SISLANDS_CACCONFIG_CGIND, + SISLANDS_CACCONFIG_MAX +}; + +enum si_power_level { + SI_POWER_LEVEL_LOW = 0, + SI_POWER_LEVEL_MEDIUM = 1, + SI_POWER_LEVEL_HIGH = 2, + SI_POWER_LEVEL_CTXSW = 3, +}; + +enum si_td { + SI_TD_AUTO, + SI_TD_UP, + SI_TD_DOWN, +}; + +enum si_display_watermark { + SI_DISPLAY_WATERMARK_LOW = 0, + SI_DISPLAY_WATERMARK_HIGH = 1, +}; + +enum si_display_gap +{ + SI_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, + SI_PM_DISPLAY_GAP_VBLANK = 1, + SI_PM_DISPLAY_GAP_WATERMARK = 2, + SI_PM_DISPLAY_GAP_IGNORE = 3, +}; + +extern const struct amd_ip_funcs si_dpm_ip_funcs; + +struct ni_leakage_coeffients +{ + u32 at; + u32 bt; + u32 av; + u32 bv; + s32 t_slope; + s32 t_intercept; + u32 t_ref; +}; + +struct SMC_Evergreen_MCRegisterAddress +{ + uint16_t s0; + uint16_t s1; +}; + +typedef struct SMC_Evergreen_MCRegisterAddress SMC_Evergreen_MCRegisterAddress; + +struct evergreen_mc_reg_entry { + u32 mclk_max; + u32 mc_data[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; +}; + +struct evergreen_mc_reg_table { + u8 last; + u8 num_entries; + u16 valid_flag; + struct evergreen_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMC_Evergreen_MCRegisterAddress mc_reg_address[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; +}; + +struct SMC_Evergreen_MCRegisterSet +{ + uint32_t value[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; +}; + +typedef struct SMC_Evergreen_MCRegisterSet SMC_Evergreen_MCRegisterSet; + +struct SMC_Evergreen_MCRegisters +{ + uint8_t last; + uint8_t reserved[3]; + SMC_Evergreen_MCRegisterAddress address[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; + SMC_Evergreen_MCRegisterSet data[5]; +}; + +typedef struct SMC_Evergreen_MCRegisters SMC_Evergreen_MCRegisters; + +struct SMC_NIslands_MCRegisterSet +{ + uint32_t value[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +typedef struct SMC_NIslands_MCRegisterSet SMC_NIslands_MCRegisterSet; + +struct ni_mc_reg_entry { + u32 mclk_max; + u32 mc_data[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +struct SMC_NIslands_MCRegisterAddress +{ + uint16_t s0; + uint16_t s1; +}; + +typedef struct SMC_NIslands_MCRegisterAddress SMC_NIslands_MCRegisterAddress; + +struct SMC_NIslands_MCRegisters +{ + uint8_t last; + uint8_t reserved[3]; + SMC_NIslands_MCRegisterAddress address[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; + SMC_NIslands_MCRegisterSet data[SMC_NISLANDS_MC_REGISTER_ARRAY_SET_COUNT]; +}; + +typedef struct SMC_NIslands_MCRegisters SMC_NIslands_MCRegisters; + +struct evergreen_ulv_param { + bool supported; + struct rv7xx_pl *pl; +}; + +struct evergreen_arb_registers { + u32 mc_arb_dram_timing; + u32 mc_arb_dram_timing2; + u32 mc_arb_rfsh_rate; + u32 mc_arb_burst_time; +}; + +struct at { + u32 rlp; + u32 rmp; + u32 lhp; + u32 lmp; +}; + +struct ni_clock_registers { + u32 cg_spll_func_cntl; + u32 cg_spll_func_cntl_2; + u32 cg_spll_func_cntl_3; + u32 cg_spll_func_cntl_4; + u32 cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2; + u32 mclk_pwrmgt_cntl; + u32 dll_cntl; + u32 mpll_ad_func_cntl; + u32 mpll_ad_func_cntl_2; + u32 mpll_dq_func_cntl; + u32 mpll_dq_func_cntl_2; + u32 mpll_ss1; + u32 mpll_ss2; +}; + +struct RV770_SMC_SCLK_VALUE +{ + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t sclk_value; +}; + +typedef struct RV770_SMC_SCLK_VALUE RV770_SMC_SCLK_VALUE; + +struct RV770_SMC_MCLK_VALUE +{ + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_AD_FUNC_CNTL_2; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL_2; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vDLL_CNTL; + uint32_t vMPLL_SS; + uint32_t vMPLL_SS2; + uint32_t mclk_value; +}; + +typedef struct RV770_SMC_MCLK_VALUE RV770_SMC_MCLK_VALUE; + + +struct RV730_SMC_MCLK_VALUE +{ + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vDLL_CNTL; + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL2; + uint32_t vMPLL_FUNC_CNTL3; + uint32_t vMPLL_SS; + uint32_t vMPLL_SS2; + uint32_t mclk_value; +}; + +typedef struct RV730_SMC_MCLK_VALUE RV730_SMC_MCLK_VALUE; + +struct RV770_SMC_VOLTAGE_VALUE +{ + uint16_t value; + uint8_t index; + uint8_t padding; +}; + +typedef struct RV770_SMC_VOLTAGE_VALUE RV770_SMC_VOLTAGE_VALUE; + +union RV7XX_SMC_MCLK_VALUE +{ + RV770_SMC_MCLK_VALUE mclk770; + RV730_SMC_MCLK_VALUE mclk730; +}; + +typedef union RV7XX_SMC_MCLK_VALUE RV7XX_SMC_MCLK_VALUE, *LPRV7XX_SMC_MCLK_VALUE; + +struct RV770_SMC_HW_PERFORMANCE_LEVEL +{ + uint8_t arbValue; + union{ + uint8_t seqValue; + uint8_t ACIndex; + }; + uint8_t displayWatermark; + uint8_t gen2PCIE; + uint8_t gen2XSP; + uint8_t backbias; + uint8_t strobeMode; + uint8_t mcFlags; + uint32_t aT; + uint32_t bSP; + RV770_SMC_SCLK_VALUE sclk; + RV7XX_SMC_MCLK_VALUE mclk; + RV770_SMC_VOLTAGE_VALUE vddc; + RV770_SMC_VOLTAGE_VALUE mvdd; + RV770_SMC_VOLTAGE_VALUE vddci; + uint8_t reserved1; + uint8_t reserved2; + uint8_t stateFlags; + uint8_t padding; +}; + +typedef struct RV770_SMC_HW_PERFORMANCE_LEVEL RV770_SMC_HW_PERFORMANCE_LEVEL; + +struct RV770_SMC_SWSTATE +{ + uint8_t flags; + uint8_t padding1; + uint8_t padding2; + uint8_t padding3; + RV770_SMC_HW_PERFORMANCE_LEVEL levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; +}; + +typedef struct RV770_SMC_SWSTATE RV770_SMC_SWSTATE; + +struct RV770_SMC_VOLTAGEMASKTABLE +{ + uint8_t highMask[RV770_SMC_VOLTAGEMASK_MAX]; + uint32_t lowMask[RV770_SMC_VOLTAGEMASK_MAX]; +}; + +typedef struct RV770_SMC_VOLTAGEMASKTABLE RV770_SMC_VOLTAGEMASKTABLE; + +struct RV770_SMC_STATETABLE +{ + uint8_t thermalProtectType; + uint8_t systemFlags; + uint8_t maxVDDCIndexInPPTable; + uint8_t extraFlags; + uint8_t highSMIO[MAX_NO_VREG_STEPS]; + uint32_t lowSMIO[MAX_NO_VREG_STEPS]; + RV770_SMC_VOLTAGEMASKTABLE voltageMaskTable; + RV770_SMC_SWSTATE initialState; + RV770_SMC_SWSTATE ACPIState; + RV770_SMC_SWSTATE driverState; + RV770_SMC_SWSTATE ULVState; +}; + +typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE; + +struct vddc_table_entry { + u16 vddc; + u8 vddc_index; + u8 high_smio; + u32 low_smio; +}; + +struct rv770_clock_registers { + u32 cg_spll_func_cntl; + u32 cg_spll_func_cntl_2; + u32 cg_spll_func_cntl_3; + u32 cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2; + u32 mpll_ad_func_cntl; + u32 mpll_ad_func_cntl_2; + u32 mpll_dq_func_cntl; + u32 mpll_dq_func_cntl_2; + u32 mclk_pwrmgt_cntl; + u32 dll_cntl; + u32 mpll_ss1; + u32 mpll_ss2; +}; + +struct rv730_clock_registers { + u32 cg_spll_func_cntl; + u32 cg_spll_func_cntl_2; + u32 cg_spll_func_cntl_3; + u32 cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2; + u32 mclk_pwrmgt_cntl; + u32 dll_cntl; + u32 mpll_func_cntl; + u32 mpll_func_cntl2; + u32 mpll_func_cntl3; + u32 mpll_ss; + u32 mpll_ss2; +}; + +union r7xx_clock_registers { + struct rv770_clock_registers rv770; + struct rv730_clock_registers rv730; +}; + +struct rv7xx_power_info { + /* flags */ + bool mem_gddr5; + bool pcie_gen2; + bool dynamic_pcie_gen2; + bool acpi_pcie_gen2; + bool boot_in_gen2; + bool voltage_control; /* vddc */ + bool mvdd_control; + bool sclk_ss; + bool mclk_ss; + bool dynamic_ss; + bool gfx_clock_gating; + bool mg_clock_gating; + bool mgcgtssm; + bool power_gating; + bool thermal_protection; + bool display_gap; + bool dcodt; + bool ulps; + /* registers */ + union r7xx_clock_registers clk_regs; + u32 s0_vid_lower_smio_cntl; + /* voltage */ + u32 vddc_mask_low; + u32 mvdd_mask_low; + u32 mvdd_split_frequency; + u32 mvdd_low_smio[MAX_NO_OF_MVDD_VALUES]; + u16 max_vddc; + u16 max_vddc_in_table; + u16 min_vddc_in_table; + struct vddc_table_entry vddc_table[MAX_NO_VREG_STEPS]; + u8 valid_vddc_entries; + /* dc odt */ + u32 mclk_odt_threshold; + u8 odt_value_0[2]; + u8 odt_value_1[2]; + /* stored values */ + u32 boot_sclk; + u16 acpi_vddc; + u32 ref_div; + u32 active_auto_throttle_sources; + u32 mclk_stutter_mode_threshold; + u32 mclk_strobe_mode_threshold; + u32 mclk_edc_enable_threshold; + u32 bsp; + u32 bsu; + u32 pbsp; + u32 pbsu; + u32 dsp; + u32 psp; + u32 asi; + u32 pasi; + u32 vrc; + u32 restricted_levels; + u32 rlp; + u32 rmp; + u32 lhp; + u32 lmp; + /* smc offsets */ + u16 state_table_start; + u16 soft_regs_start; + u16 sram_end; + /* scratch structs */ + RV770_SMC_STATETABLE smc_statetable; +}; + +struct rv7xx_pl { + u32 sclk; + u32 mclk; + u16 vddc; + u16 vddci; /* eg+ only */ + u32 flags; + enum amdgpu_pcie_gen pcie_gen; /* si+ only */ +}; + +struct rv7xx_ps { + struct rv7xx_pl high; + struct rv7xx_pl medium; + struct rv7xx_pl low; + bool dc_compatible; +}; + +struct si_ps { + u16 performance_level_count; + bool dc_compatible; + struct rv7xx_pl performance_levels[NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; +}; + +struct ni_mc_reg_table { + u8 last; + u8 num_entries; + u16 valid_flag; + struct ni_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMC_NIslands_MCRegisterAddress mc_reg_address[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +struct ni_cac_data +{ + struct ni_leakage_coeffients leakage_coefficients; + u32 i_leakage; + s32 leakage_minimum_temperature; + u32 pwr_const; + u32 dc_cac_value; + u32 bif_cac_value; + u32 lkge_pwr; + u8 mc_wr_weight; + u8 mc_rd_weight; + u8 allow_ovrflw; + u8 num_win_tdp; + u8 l2num_win_tdp; + u8 lts_truncate_n; +}; + +struct evergreen_power_info { + /* must be first! */ + struct rv7xx_power_info rv7xx; + /* flags */ + bool vddci_control; + bool dynamic_ac_timing; + bool abm; + bool mcls; + bool light_sleep; + bool memory_transition; + bool pcie_performance_request; + bool pcie_performance_request_registered; + bool sclk_deep_sleep; + bool dll_default_on; + bool ls_clock_gating; + bool smu_uvd_hs; + bool uvd_enabled; + /* stored values */ + u16 acpi_vddci; + u8 mvdd_high_index; + u8 mvdd_low_index; + u32 mclk_edc_wr_enable_threshold; + struct evergreen_mc_reg_table mc_reg_table; + struct atom_voltage_table vddc_voltage_table; + struct atom_voltage_table vddci_voltage_table; + struct evergreen_arb_registers bootup_arb_registers; + struct evergreen_ulv_param ulv; + struct at ats[2]; + /* smc offsets */ + u16 mc_reg_table_start; + struct amdgpu_ps current_rps; + struct rv7xx_ps current_ps; + struct amdgpu_ps requested_rps; + struct rv7xx_ps requested_ps; +}; + +struct PP_NIslands_Dpm2PerfLevel +{ + uint8_t MaxPS; + uint8_t TgtAct; + uint8_t MaxPS_StepInc; + uint8_t MaxPS_StepDec; + uint8_t PSST; + uint8_t NearTDPDec; + uint8_t AboveSafeInc; + uint8_t BelowSafeInc; + uint8_t PSDeltaLimit; + uint8_t PSDeltaWin; + uint8_t Reserved[6]; +}; + +typedef struct PP_NIslands_Dpm2PerfLevel PP_NIslands_Dpm2PerfLevel; + +struct PP_NIslands_DPM2Parameters +{ + uint32_t TDPLimit; + uint32_t NearTDPLimit; + uint32_t SafePowerLimit; + uint32_t PowerBoostLimit; +}; +typedef struct PP_NIslands_DPM2Parameters PP_NIslands_DPM2Parameters; + +struct NISLANDS_SMC_SCLK_VALUE +{ + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_FUNC_CNTL_4; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t sclk_value; +}; + +typedef struct NISLANDS_SMC_SCLK_VALUE NISLANDS_SMC_SCLK_VALUE; + +struct NISLANDS_SMC_MCLK_VALUE +{ + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL_1; + uint32_t vMPLL_FUNC_CNTL_2; + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_AD_FUNC_CNTL_2; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL_2; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vDLL_CNTL; + uint32_t vMPLL_SS; + uint32_t vMPLL_SS2; + uint32_t mclk_value; +}; + +typedef struct NISLANDS_SMC_MCLK_VALUE NISLANDS_SMC_MCLK_VALUE; + +struct NISLANDS_SMC_VOLTAGE_VALUE +{ + uint16_t value; + uint8_t index; + uint8_t padding; +}; + +typedef struct NISLANDS_SMC_VOLTAGE_VALUE NISLANDS_SMC_VOLTAGE_VALUE; + +struct NISLANDS_SMC_HW_PERFORMANCE_LEVEL +{ + uint8_t arbValue; + uint8_t ACIndex; + uint8_t displayWatermark; + uint8_t gen2PCIE; + uint8_t reserved1; + uint8_t reserved2; + uint8_t strobeMode; + uint8_t mcFlags; + uint32_t aT; + uint32_t bSP; + NISLANDS_SMC_SCLK_VALUE sclk; + NISLANDS_SMC_MCLK_VALUE mclk; + NISLANDS_SMC_VOLTAGE_VALUE vddc; + NISLANDS_SMC_VOLTAGE_VALUE mvdd; + NISLANDS_SMC_VOLTAGE_VALUE vddci; + NISLANDS_SMC_VOLTAGE_VALUE std_vddc; + uint32_t powergate_en; + uint8_t hUp; + uint8_t hDown; + uint8_t stateFlags; + uint8_t arbRefreshState; + uint32_t SQPowerThrottle; + uint32_t SQPowerThrottle_2; + uint32_t reserved[2]; + PP_NIslands_Dpm2PerfLevel dpm2; +}; + +typedef struct NISLANDS_SMC_HW_PERFORMANCE_LEVEL NISLANDS_SMC_HW_PERFORMANCE_LEVEL; + +struct NISLANDS_SMC_SWSTATE +{ + uint8_t flags; + uint8_t levelCount; + uint8_t padding2; + uint8_t padding3; + NISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[1]; +}; + +typedef struct NISLANDS_SMC_SWSTATE NISLANDS_SMC_SWSTATE; + +struct NISLANDS_SMC_VOLTAGEMASKTABLE +{ + uint8_t highMask[NISLANDS_SMC_VOLTAGEMASK_MAX]; + uint32_t lowMask[NISLANDS_SMC_VOLTAGEMASK_MAX]; +}; + +typedef struct NISLANDS_SMC_VOLTAGEMASKTABLE NISLANDS_SMC_VOLTAGEMASKTABLE; + +#define NISLANDS_MAX_NO_VREG_STEPS 32 + +struct NISLANDS_SMC_STATETABLE +{ + uint8_t thermalProtectType; + uint8_t systemFlags; + uint8_t maxVDDCIndexInPPTable; + uint8_t extraFlags; + uint8_t highSMIO[NISLANDS_MAX_NO_VREG_STEPS]; + uint32_t lowSMIO[NISLANDS_MAX_NO_VREG_STEPS]; + NISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable; + PP_NIslands_DPM2Parameters dpm2Params; + NISLANDS_SMC_SWSTATE initialState; + NISLANDS_SMC_SWSTATE ACPIState; + NISLANDS_SMC_SWSTATE ULVState; + NISLANDS_SMC_SWSTATE driverState; + NISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1]; +}; + +typedef struct NISLANDS_SMC_STATETABLE NISLANDS_SMC_STATETABLE; + +struct ni_power_info { + /* must be first! */ + struct evergreen_power_info eg; + struct ni_clock_registers clock_registers; + struct ni_mc_reg_table mc_reg_table; + u32 mclk_rtt_mode_threshold; + /* flags */ + bool use_power_boost_limit; + bool support_cac_long_term_average; + bool cac_enabled; + bool cac_configuration_required; + bool driver_calculate_cac_leakage; + bool pc_enabled; + bool enable_power_containment; + bool enable_cac; + bool enable_sq_ramping; + /* smc offsets */ + u16 arb_table_start; + u16 fan_table_start; + u16 cac_table_start; + u16 spll_table_start; + /* CAC stuff */ + struct ni_cac_data cac_data; + u32 dc_cac_table[NISLANDS_DCCAC_MAX_LEVELS]; + const struct ni_cac_weights *cac_weights; + u8 lta_window_size; + u8 lts_truncate; + struct si_ps current_ps; + struct si_ps requested_ps; + /* scratch structs */ + SMC_NIslands_MCRegisters smc_mc_reg_table; + NISLANDS_SMC_STATETABLE smc_statetable; +}; + +struct si_cac_config_reg +{ + u32 offset; + u32 mask; + u32 shift; + u32 value; + enum si_cac_config_reg_type type; +}; + +struct si_powertune_data +{ + u32 cac_window; + u32 l2_lta_window_size_default; + u8 lts_truncate_default; + u8 shift_n_default; + u8 operating_temp; + struct ni_leakage_coeffients leakage_coefficients; + u32 fixed_kt; + u32 lkge_lut_v0_percent; + u8 dc_cac[NISLANDS_DCCAC_MAX_LEVELS]; + bool enable_powertune_by_default; +}; + +struct si_dyn_powertune_data +{ + u32 cac_leakage; + s32 leakage_minimum_temperature; + u32 wintime; + u32 l2_lta_window_size; + u8 lts_truncate; + u8 shift_n; + u8 dc_pwr_value; + bool disable_uvd_powertune; +}; + +struct si_dte_data +{ + u32 tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; + u32 r[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; + u32 k; + u32 t0; + u32 max_t; + u8 window_size; + u8 temp_select; + u8 dte_mode; + u8 tdep_count; + u8 t_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + u32 tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + u32 tdep_r[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + u32 t_threshold; + bool enable_dte_by_default; +}; + +struct si_clock_registers { + u32 cg_spll_func_cntl; + u32 cg_spll_func_cntl_2; + u32 cg_spll_func_cntl_3; + u32 cg_spll_func_cntl_4; + u32 cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2; + u32 dll_cntl; + u32 mclk_pwrmgt_cntl; + u32 mpll_ad_func_cntl; + u32 mpll_dq_func_cntl; + u32 mpll_func_cntl; + u32 mpll_func_cntl_1; + u32 mpll_func_cntl_2; + u32 mpll_ss1; + u32 mpll_ss2; +}; + +struct si_mc_reg_entry { + u32 mclk_max; + u32 mc_data[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +struct si_mc_reg_table { + u8 last; + u8 num_entries; + u16 valid_flag; + struct si_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMC_NIslands_MCRegisterAddress mc_reg_address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +struct si_leakage_voltage_entry +{ + u16 voltage; + u16 leakage_index; +}; + +struct si_leakage_voltage +{ + u16 count; + struct si_leakage_voltage_entry entries[SISLANDS_MAX_LEAKAGE_COUNT]; +}; + + +struct si_ulv_param { + bool supported; + u32 cg_ulv_control; + u32 cg_ulv_parameter; + u32 volt_change_delay; + struct rv7xx_pl pl; + bool one_pcie_lane_in_ulv; +}; + +struct si_power_info { + /* must be first! */ + struct ni_power_info ni; + struct si_clock_registers clock_registers; + struct si_mc_reg_table mc_reg_table; + struct atom_voltage_table mvdd_voltage_table; + struct atom_voltage_table vddc_phase_shed_table; + struct si_leakage_voltage leakage_voltage; + u16 mvdd_bootup_value; + struct si_ulv_param ulv; + u32 max_cu; + /* pcie gen */ + enum amdgpu_pcie_gen force_pcie_gen; + enum amdgpu_pcie_gen boot_pcie_gen; + enum amdgpu_pcie_gen acpi_pcie_gen; + u32 sys_pcie_mask; + /* flags */ + bool enable_dte; + bool enable_ppm; + bool vddc_phase_shed_control; + bool pspp_notify_required; + bool sclk_deep_sleep_above_low; + bool voltage_control_svi2; + bool vddci_control_svi2; + /* smc offsets */ + u32 sram_end; + u32 state_table_start; + u32 soft_regs_start; + u32 mc_reg_table_start; + u32 arb_table_start; + u32 cac_table_start; + u32 dte_table_start; + u32 spll_table_start; + u32 papm_cfg_table_start; + u32 fan_table_start; + /* CAC stuff */ + const struct si_cac_config_reg *cac_weights; + const struct si_cac_config_reg *lcac_config; + const struct si_cac_config_reg *cac_override; + const struct si_powertune_data *powertune_data; + struct si_dyn_powertune_data dyn_powertune_data; + /* DTE stuff */ + struct si_dte_data dte_data; + /* scratch structs */ + SMC_SIslands_MCRegisters smc_mc_reg_table; + SISLANDS_SMC_STATETABLE smc_statetable; + PP_SIslands_PAPMParameters papm_parm; + /* SVI2 */ + u8 svd_gpio_id; + u8 svc_gpio_id; + /* fan control */ + bool fan_ctrl_is_in_default_mode; + u32 t_min; + u32 fan_ctrl_default_mode; + bool fan_is_controlled_by_smc; +}; + +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/si_smc.c b/drivers/gpu/drm/amd/amdgpu/si_smc.c index 214f37c..c1c2594 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/si_smc.c @@ -224,6 +224,7 @@ int si_load_smc_ucode(struct amdgpu_device *adev, u32 limit) amdgpu_ucode_print_smc_hdr(&hdr->header); + adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version); ucode_start_address = le32_to_cpu(hdr->ucode_start_addr); ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); src = (const u8 *) -- cgit v1.1 From 84b77336eea3690b4261c05707a7aba23b61fbad Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 31 Aug 2016 13:23:18 +0800 Subject: drm/amdgpu: use DRM print instead of printk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 2ef4cc1..5dd53af 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -7687,9 +7687,8 @@ static int si_dpm_init_microcode(struct amdgpu_device *adev) out: if (err) { - printk(KERN_ERR - "si_smc: Failed to load firmware. err = %d\"%s\"\n", - err, fw_name); + DRM_ERROR("si_smc: Failed to load firmware. err = %d\"%s\"\n", + err, fw_name); release_firmware(adev->pm.fw); adev->pm.fw = NULL; } @@ -7908,15 +7907,15 @@ static void si_dpm_print_power_state(struct amdgpu_device *adev, amdgpu_dpm_print_class_info(rps->class, rps->class2); amdgpu_dpm_print_cap_info(rps->caps); - printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + DRM_INFO("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); for (i = 0; i < ps->performance_level_count; i++) { pl = &ps->performance_levels[i]; if (adev->asic_type >= CHIP_TAHITI) - printk("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", - i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); + DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", + i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); else - printk("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u\n", - i, pl->sclk, pl->mclk, pl->vddc, pl->vddci); + DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u\n", + i, pl->sclk, pl->mclk, pl->vddc, pl->vddci); } amdgpu_dpm_print_ps_status(adev, rps); } -- cgit v1.1 From 1919696eedc1ed5c3ace229576e4fa322fb256dd Mon Sep 17 00:00:00 2001 From: Maruthi Srinivas Bayyavarapu Date: Tue, 26 Apr 2016 20:35:36 +0530 Subject: drm/amdgpu: enable SI DPM Signed-off-by: Maruthi Bayyavarapu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 10 ++++++++++ drivers/gpu/drm/amd/amdgpu/si.c | 8 ++++---- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 5ebea9d..dc6df07 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -30,7 +30,7 @@ amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \ amdgpu_amdkfd_gfx_v7.o -amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o +amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o amdgpu-y += \ vi.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index ecc4141..1e7f160 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -30,6 +30,7 @@ #include "amdgpu_pm.h" #include #include "amdgpu_powerplay.h" +#include "si_dpm.h" #include "cik_dpm.h" #include "vi_dpm.h" @@ -59,6 +60,15 @@ static int amdgpu_powerplay_init(struct amdgpu_device *adev) amd_pp->pp_handle = (void *)adev; switch (adev->asic_type) { +#ifdef CONFIG_DRM_AMDGPU_SI + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: + case CHIP_HAINAN: + amd_pp->ip_funcs = &si_dpm_ip_funcs; + break; +#endif #ifdef CONFIG_DRM_AMDGPU_CIK case CHIP_BONAIRE: case CHIP_HAWAII: diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index c905470..fee76b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1117,6 +1117,7 @@ static u32 si_get_xclk(struct amdgpu_device *adev) return reference_clock; } + //xxx:not implemented static int si_set_uvd_clocks(struct amdgpu_device *adev, u32 vclk, u32 dclk) { @@ -1850,14 +1851,13 @@ static const struct amdgpu_ip_block_version verde_ip_blocks[] = .rev = 0, .funcs = &si_ih_ip_funcs, }, -/* { + { .type = AMD_IP_BLOCK_TYPE_SMC, .major = 6, .minor = 0, .rev = 0, - .funcs = &si_null_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, - */ { .type = AMD_IP_BLOCK_TYPE_DCE, .major = 6, @@ -1925,7 +1925,7 @@ static const struct amdgpu_ip_block_version hainan_ip_blocks[] = .major = 6, .minor = 0, .rev = 0, - .funcs = &si_null_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_GFX, -- cgit v1.1 From 295d0dafd31c9a26f3d34a9bdc75f226e18fd9a2 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Tue, 24 May 2016 21:02:53 +0800 Subject: drm/amdgpu: Add SI Family information Signed-off-by: Ken Wang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + include/uapi/drm/amdgpu_drm.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index aef9a9a..f95bcb8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1245,6 +1245,7 @@ static int amdgpu_early_init(struct amdgpu_device *adev) case CHIP_PITCAIRN: case CHIP_OLAND: case CHIP_HAINAN: + adev->family = AMDGPU_FAMILY_SI; r = si_set_ip_blocks(adev); if (r) return r; diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index ae2845f..d6b5a21 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -649,6 +649,7 @@ struct drm_amdgpu_info_hw_ip { * Supported GPU families */ #define AMDGPU_FAMILY_UNKNOWN 0 +#define AMDGPU_FAMILY_SI 110 /* Hainan, Oland, Verde, Pitcairn, Tahiti */ #define AMDGPU_FAMILY_CI 120 /* Bonaire, Hawaii */ #define AMDGPU_FAMILY_KV 125 /* Kaveri, Kabini, Mullins */ #define AMDGPU_FAMILY_VI 130 /* Iceland, Tonga */ -- cgit v1.1 From a8c65c137884f3b65815424d100abfba0c3b3b44 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 1 Aug 2016 16:05:47 -0400 Subject: drm/amdgpu/si: Add updated smc firmware for SI kickers Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 48 +++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 5dd53af..e90bb44 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -56,10 +56,15 @@ #define BIOS_SCRATCH_4 0x5cd MODULE_FIRMWARE("radeon/tahiti_smc.bin"); +MODULE_FIRMWARE("radeon/tahiti_k_smc.bin"); MODULE_FIRMWARE("radeon/pitcairn_smc.bin"); +MODULE_FIRMWARE("radeon/pitcairn_k_smc.bin"); MODULE_FIRMWARE("radeon/verde_smc.bin"); +MODULE_FIRMWARE("radeon/verde_k_smc.bin"); MODULE_FIRMWARE("radeon/oland_smc.bin"); +MODULE_FIRMWARE("radeon/oland_k_smc.bin"); MODULE_FIRMWARE("radeon/hainan_smc.bin"); +MODULE_FIRMWARE("radeon/hainan_k_smc.bin"); union power_info { struct _ATOM_POWERPLAY_INFO info; @@ -7665,16 +7670,51 @@ static int si_dpm_init_microcode(struct amdgpu_device *adev) chip_name = "tahiti"; break; case CHIP_PITCAIRN: - chip_name = "pitcairn"; + if ((adev->pdev->revision == 0x81) || + (adev->pdev->device == 0x6810) || + (adev->pdev->device == 0x6811) || + (adev->pdev->device == 0x6816) || + (adev->pdev->device == 0x6817) || + (adev->pdev->device == 0x6806)) + chip_name = "pitcairn_k"; + else + chip_name = "pitcairn"; break; case CHIP_VERDE: - chip_name = "verde"; + if ((adev->pdev->revision == 0x81) || + (adev->pdev->revision == 0x83) || + (adev->pdev->revision == 0x87) || + (adev->pdev->device == 0x6820) || + (adev->pdev->device == 0x6821) || + (adev->pdev->device == 0x6822) || + (adev->pdev->device == 0x6823) || + (adev->pdev->device == 0x682A) || + (adev->pdev->device == 0x682B)) + chip_name = "verde_k"; + else + chip_name = "verde"; break; case CHIP_OLAND: - chip_name = "oland"; + if ((adev->pdev->revision == 0xC7) || + (adev->pdev->revision == 0x80) || + (adev->pdev->revision == 0x81) || + (adev->pdev->revision == 0x83) || + (adev->pdev->device == 0x6604) || + (adev->pdev->device == 0x6605)) + chip_name = "oland_k"; + else + chip_name = "oland"; break; case CHIP_HAINAN: - chip_name = "hainan"; + if ((adev->pdev->revision == 0x81) || + (adev->pdev->revision == 0x83) || + (adev->pdev->revision == 0xC3) || + (adev->pdev->device == 0x6664) || + (adev->pdev->device == 0x6665) || + (adev->pdev->device == 0x6667)) + chip_name = "hainan_k"; + else + chip_name = "hainan"; break; default: BUG(); } -- cgit v1.1 From 78fbb6859b739f7f67c820ab8c9e7a25add977b5 Mon Sep 17 00:00:00 2001 From: Ken Wang Date: Thu, 21 Jan 2016 17:33:00 +0800 Subject: drm/amdgpu: add si pciids v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König Signed-off-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 74 +++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 6fed75454..28c3dcc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -200,6 +200,80 @@ MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the virtual_d module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444); static const struct pci_device_id pciidlist[] = { +#ifdef CONFIG_DRM_AMDGPU_SI + {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x6784, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, + {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|AMD_IS_MOBILITY}, + {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|AMD_IS_MOBILITY}, + {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|AMD_IS_MOBILITY}, + {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN}, + {0x1002, 0x6600, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6602, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6603, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6604, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6605, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6606, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6607, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6608, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND}, + {0x1002, 0x6610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND}, + {0x1002, 0x6611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND}, + {0x1002, 0x6613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND}, + {0x1002, 0x6617, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6620, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|AMD_IS_MOBILITY}, + {0x1002, 0x6631, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND}, + {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6821, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6822, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6823, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6824, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6826, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6827, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x682A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x682C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|AMD_IS_MOBILITY}, + {0x1002, 0x6835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x6837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x6838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x6839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x683B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x683D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x683F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE}, + {0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, + {0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, + {0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, + {0x1002, 0x6665, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, + {0x1002, 0x6667, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, + {0x1002, 0x666F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, +#endif #ifdef CONFIG_DRM_AMDGPU_CIK /* Kaveri */ {0x1002, 0x1304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU}, -- cgit v1.1 From 5c1354bd30c118326236e13cfdc49db03d2b5855 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Tue, 30 Aug 2016 16:13:10 +0800 Subject: drm/amdgpu: link all gtt when binding them V2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V2: spin lock instead of mutex for gtt list Signed-off-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 9 +++++++++ 3 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 86762cd..829b0b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2121,6 +2121,10 @@ struct amdgpu_device { /* link all shadow bo */ struct list_head shadow_list; struct mutex shadow_list_lock; + /* link all gtt */ + spinlock_t gtt_list_lock; + struct list_head gtt_list; + }; bool amdgpu_device_is_px(struct drm_device *dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index f95bcb8..bfdd445 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1577,6 +1577,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, INIT_LIST_HEAD(&adev->shadow_list); mutex_init(&adev->shadow_list_lock); + INIT_LIST_HEAD(&adev->gtt_list); + spin_lock_init(&adev->gtt_list_lock); + if (adev->asic_type >= CHIP_BONAIRE) { adev->rmmio_base = pci_resource_start(adev->pdev, 5); adev->rmmio_size = pci_resource_len(adev->pdev, 5); @@ -1584,6 +1587,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->rmmio_base = pci_resource_start(adev->pdev, 2); adev->rmmio_size = pci_resource_len(adev->pdev, 2); } + adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size); if (adev->rmmio == NULL) { return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 5447973..26ca3dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -520,6 +520,7 @@ struct amdgpu_ttm_tt { spinlock_t guptasklock; struct list_head guptasks; atomic_t mmu_invalidations; + struct list_head list; }; int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) @@ -666,6 +667,9 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, ttm->num_pages, (unsigned)gtt->offset); return r; } + spin_lock(>t->adev->gtt_list_lock); + list_add_tail(>t->list, >t->adev->gtt_list); + spin_unlock(>t->adev->gtt_list_lock); return 0; } @@ -680,6 +684,10 @@ static int amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) if (gtt->userptr) amdgpu_ttm_tt_unpin_userptr(ttm); + spin_lock(>t->adev->gtt_list_lock); + list_del_init(>t->list); + spin_unlock(>t->adev->gtt_list_lock); + return 0; } @@ -716,6 +724,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_bo_device *bdev, kfree(gtt); return NULL; } + INIT_LIST_HEAD(>t->list); return >t->ttm.ttm; } -- cgit v1.1 From 2c0d7318c8b071bf9688bb5f2bedba95856e0d42 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Tue, 30 Aug 2016 16:36:25 +0800 Subject: drm/amdgpu: add gart recovery by gtt list V2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V2: a. gart recovery should be ahead of ring test. b. rename to amdgpu_ttm_recover_gart Signed-off-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 +++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 829b0b4..2cfaa64 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -620,6 +620,7 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, unsigned offset, int amdgpu_gart_bind(struct amdgpu_device *adev, unsigned offset, int pages, struct page **pagelist, dma_addr_t *dma_addr, uint32_t flags); +int amdgpu_ttm_recover_gart(struct amdgpu_device *adev); /* * GPU MC structures, functions & helpers diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index bfdd445..c2459ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2206,6 +2206,11 @@ retry: } if (!r) { amdgpu_irq_gpu_reset_resume_helper(adev); + if (need_full_reset && amdgpu_need_backup(adev)) { + r = amdgpu_ttm_recover_gart(adev); + if (r) + DRM_ERROR("gart recovery failed!!!\n"); + } r = amdgpu_ib_ring_tests(adev); if (r) { dev_err(adev->dev, "ib ring test failed (%d).\n", r); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 26ca3dd..3beb10b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -673,6 +673,31 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, return 0; } +int amdgpu_ttm_recover_gart(struct amdgpu_device *adev) +{ + struct amdgpu_ttm_tt *gtt, *tmp; + struct ttm_mem_reg bo_mem; + uint32_t flags; + int r; + + bo_mem.mem_type = TTM_PL_TT; + spin_lock(&adev->gtt_list_lock); + list_for_each_entry_safe(gtt, tmp, &adev->gtt_list, list) { + flags = amdgpu_ttm_tt_pte_flags(gtt->adev, >t->ttm.ttm, &bo_mem); + r = amdgpu_gart_bind(adev, gtt->offset, gtt->ttm.ttm.num_pages, + gtt->ttm.ttm.pages, gtt->ttm.dma_address, + flags); + if (r) { + spin_unlock(&adev->gtt_list_lock); + DRM_ERROR("failed to bind %lu pages at 0x%08X\n", + gtt->ttm.ttm.num_pages, (unsigned)gtt->offset); + return r; + } + } + spin_unlock(&adev->gtt_list_lock); + return 0; +} + static int amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) { struct amdgpu_ttm_tt *gtt = (void *)ttm; -- cgit v1.1 From e6c71b48c9713c5581e9ac6dcb469db176468120 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 1 Sep 2016 14:10:46 -0400 Subject: drm/amdgpu/gfx6: drop some dead code The mqd is only used on CI and newer. Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 17a560c..040bc7f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -1725,28 +1725,6 @@ static void gfx_v6_0_ring_set_wptr_compute(struct amdgpu_ring *ring) } - -static void gfx_v6_0_cp_compute_fini(struct amdgpu_device *adev) -{ - int i, r; - - for (i = 0; i < adev->gfx.num_compute_rings; i++) { - struct amdgpu_ring *ring = &adev->gfx.compute_ring[i]; - - if (ring->mqd_obj) { - r = amdgpu_bo_reserve(ring->mqd_obj, false); - if (unlikely(r != 0)) - dev_warn(adev->dev, "(%d) reserve MQD bo failed\n", r); - - amdgpu_bo_unpin(ring->mqd_obj); - amdgpu_bo_unreserve(ring->mqd_obj); - - amdgpu_bo_unref(&ring->mqd_obj); - ring->mqd_obj = NULL; - } - } -} - static int gfx_v6_0_cp_compute_resume(struct amdgpu_device *adev) { struct amdgpu_ring *ring; @@ -2865,7 +2843,6 @@ static int gfx_v6_0_sw_fini(void *handle) for (i = 0; i < adev->gfx.num_compute_rings; i++) amdgpu_ring_fini(&adev->gfx.compute_ring[i]); - gfx_v6_0_cp_compute_fini(adev); gfx_v6_0_rlc_fini(adev); return 0; -- cgit v1.1 From 85e154c22e3c29d4db52ccc1c1cc58a2cadc103b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 27 Aug 2016 14:53:08 -0400 Subject: drm/amdgpu: set runtime pm state to active on resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sbios always powers up the dGPU on resume. Acked-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 28c3dcc..94d0135 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -482,6 +482,14 @@ static int amdgpu_pmops_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); + + /* GPU comes up enabled by the bios on resume */ + if (amdgpu_device_is_px(drm_dev)) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } + return amdgpu_device_resume(drm_dev, true, true); } -- cgit v1.1 From f46cf3735f4c05eb752d020d34ace1c85ccf567c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 27 Aug 2016 12:57:20 -0400 Subject: drm/amdgpu: skip suspend/resume on DRM_SWITCH_POWER_DYNAMIC_OFF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed this case previously. No need to do anything if the device is already off. runtime pm will handle it. Acked-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c2459ab..1aa0364 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1839,7 +1839,8 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) adev = dev->dev_private; - if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF || + dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; drm_kms_helper_poll_disable(dev); @@ -1920,7 +1921,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) struct drm_crtc *crtc; int r; - if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF || + dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; if (fbcon) { -- cgit v1.1 From 103917b387ba9b72114d494fb29e012f51b4be3e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 31 Aug 2016 17:34:23 -0400 Subject: drm/radeon: set runtime pm state to active on resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sbios always powers up the dGPU on resume. Acked-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_drv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 8faa4d5..c9e6928 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -374,6 +374,14 @@ static int radeon_pmops_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); + + /* GPU comes up enabled by the bios on resume */ + if (radeon_is_px(drm_dev)) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } + return radeon_resume_kms(drm_dev, true, true); } -- cgit v1.1 From 5e0b1617fc38a27cf494c5d0b51f08de77ce0d20 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 31 Aug 2016 17:31:30 -0400 Subject: drm/radeon: skip suspend/resume on DRM_SWITCH_POWER_DYNAMIC_OFF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed this case previously. No need to do anything if the device is already off. runtime pm will handle it. Acked-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index a00dd2f..cfb3e4f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1594,7 +1594,8 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, rdev = dev->dev_private; - if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF || + dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; drm_kms_helper_poll_disable(dev); @@ -1689,7 +1690,8 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) struct drm_crtc *crtc; int r; - if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF || + dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; if (fbcon) { -- cgit v1.1 From dc08267ac4ee7d4b602dd0ac000114e4426e2769 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 27 Aug 2016 12:30:25 -0400 Subject: drm/amdgpu: handle runtime pm correctly in amdgpu_driver_open_kms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to fix the error paths. Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index f1b9e0f..cc4ae11 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -542,12 +542,16 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) return r; fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); - if (unlikely(!fpriv)) - return -ENOMEM; + if (unlikely(!fpriv)) { + r = -ENOMEM; + goto out_suspend; + } r = amdgpu_vm_init(adev, &fpriv->vm); - if (r) - goto error_free; + if (r) { + kfree(fpriv); + goto out_suspend; + } mutex_init(&fpriv->bo_list_lock); idr_init(&fpriv->bo_list_handles); @@ -556,12 +560,9 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) file_priv->driver_priv = fpriv; +out_suspend: pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); - return 0; - -error_free: - kfree(fpriv); return r; } -- cgit v1.1 From 32c59dc14b72803f20742e5b6e515d39e90dbb83 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 31 Aug 2016 17:27:03 -0400 Subject: drm/radeon: handle runtime pm correctly in amdgpu_driver_open_kms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to fix the error paths. Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_kms.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 835563c..0aa8eac 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -641,11 +641,11 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) if (rdev->family >= CHIP_CAYMAN) { struct radeon_fpriv *fpriv; struct radeon_vm *vm; - int r; fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); if (unlikely(!fpriv)) { - return -ENOMEM; + r = -ENOMEM; + goto out_suspend; } if (rdev->accel_working) { @@ -653,14 +653,14 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) r = radeon_vm_init(rdev, vm); if (r) { kfree(fpriv); - return r; + goto out_suspend; } r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (r) { radeon_vm_fini(rdev, vm); kfree(fpriv); - return r; + goto out_suspend; } /* map the ib pool buffer read only into @@ -674,15 +674,16 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) if (r) { radeon_vm_fini(rdev, vm); kfree(fpriv); - return r; + goto out_suspend; } } file_priv->driver_priv = fpriv; } +out_suspend: pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); - return 0; + return r; } /** -- cgit v1.1 From d6bda7b4b4997f1062844dbc8b47708d244c10be Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 27 Aug 2016 12:27:24 -0400 Subject: drm/amdgpu: handle runtime pm in drm pre/post close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close was not handled correctly. Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index cc4ae11..c2c7fb1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -601,6 +601,9 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, kfree(fpriv); file_priv->driver_priv = NULL; + + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); } /** @@ -615,6 +618,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, void amdgpu_driver_preclose_kms(struct drm_device *dev, struct drm_file *file_priv) { + pm_runtime_get_sync(dev->dev); } /* -- cgit v1.1 From 9b96b63fed542598054dbf249360d413f7bd6059 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 31 Aug 2016 17:23:31 -0400 Subject: drm/radeon: handle runtime pm in drm pre/post close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close was not handled correctly. Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_kms.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 0aa8eac..4388dde 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -718,6 +718,8 @@ void radeon_driver_postclose_kms(struct drm_device *dev, kfree(fpriv); file_priv->driver_priv = NULL; } + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); } /** @@ -734,6 +736,8 @@ void radeon_driver_preclose_kms(struct drm_device *dev, { struct radeon_device *rdev = dev->dev_private; + pm_runtime_get_sync(dev->dev); + mutex_lock(&rdev->gem.mutex); if (rdev->hyperz_filp == file_priv) rdev->hyperz_filp = NULL; -- cgit v1.1 From 61e113067b636fe73d5d0ac877bcfcebe7cfd034 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 22 Aug 2016 13:50:22 -0400 Subject: drm/amdgpu: wire up a pci shutdown callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normally on shutdown or reboot we don't care about necessarily making sure the hw is in a good state because the system is about to be powered down or reset. However, after a shutdown or reboot in a VM, it's best to tear down the hw properly otherwise there can be problems with the next VM use. Reviewed-by: Christian König Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 94d0135..ea54e30 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -471,6 +471,19 @@ amdgpu_pci_remove(struct pci_dev *pdev) drm_put_dev(dev); } +static void +amdgpu_pci_shutdown(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = dev->dev_private; + + /* if we are running in a VM, make sure the device + * torn down properly on reboot/shutdown + */ + if (adev->virtualization.is_virtual) + amdgpu_pci_remove(pdev); +} + static int amdgpu_pmops_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -692,6 +705,7 @@ static struct pci_driver amdgpu_kms_pci_driver = { .id_table = pciidlist, .probe = amdgpu_pci_probe, .remove = amdgpu_pci_remove, + .shutdown = amdgpu_pci_shutdown, .driver.pm = &amdgpu_pm_ops, }; -- cgit v1.1 From a801abe4773dadcea4be4dc0affcc3a22d41543c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 22 Aug 2016 14:29:44 -0400 Subject: drm/radeon: wire up a pci shutdown callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normally on shutdown or reboot we don't care about necessarily making sure the hw is in a good state because the system is about to be powered down or reset. However, after a shutdown or reboot in a VM, it's best to tear down the hw properly otherwise there can be problems with the next VM use. Reviewed-by: Christian König Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 2 +- drivers/gpu/drm/radeon/radeon_drv.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index cfb3e4f..8425b12 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -639,7 +639,7 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) * Used at driver startup. * Returns true if virtual or false if not. */ -static bool radeon_device_is_virtual(void) +bool radeon_device_is_virtual(void) { #ifdef CONFIG_X86 return boot_cpu_has(X86_FEATURE_HYPERVISOR); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c9e6928..5fdd48c 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -310,6 +310,8 @@ MODULE_DEVICE_TABLE(pci, pciidlist); static struct drm_driver kms_driver; +bool radeon_device_is_virtual(void); + static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) { struct apertures_struct *ap; @@ -363,6 +365,16 @@ radeon_pci_remove(struct pci_dev *pdev) drm_put_dev(dev); } +static void +radeon_pci_shutdown(struct pci_dev *pdev) +{ + /* if we are running in a VM, make sure the device + * torn down properly on reboot/shutdown + */ + if (radeon_device_is_virtual()) + radeon_pci_remove(pdev); +} + static int radeon_pmops_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -583,6 +595,7 @@ static struct pci_driver radeon_kms_pci_driver = { .id_table = pciidlist, .probe = radeon_pci_probe, .remove = radeon_pci_remove, + .shutdown = radeon_pci_shutdown, .driver.pm = &radeon_pm_ops, }; -- cgit v1.1 From 1abdc3d73dd9dc2f3dc619d466d378e70cbcc24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 31 Aug 2016 17:28:11 +0200 Subject: drm/amdgpu: only try again if we actually run into -ENOMEM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All other errors can't be fixed by using a different memory domain. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 8292757..d7a9573 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -371,11 +371,9 @@ retry: p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) - initial_bytes_moved; - if (unlikely(r)) { - if (r != -ERESTARTSYS && domain != bo->allowed_domains) { - domain = bo->allowed_domains; - goto retry; - } + if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) { + domain = bo->allowed_domains; + goto retry; } return r; -- cgit v1.1 From 662bfa61fff1de4dd96029d556d7b301e27c3556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 1 Sep 2016 12:13:18 +0200 Subject: drm/amdgpu: prevent command submission failures under memory pressure v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As last resort try to evict BOs from the current working set into other memory domains. This effectively prevents command submission failures when VM page tables have been swapped out. v2: fix typos Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 63 +++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2cfaa64..39baabe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1225,6 +1225,7 @@ struct amdgpu_cs_parser { struct fence *fence; uint64_t bytes_moved_threshold; uint64_t bytes_moved; + struct amdgpu_bo_list_entry *evictable; /* user fence */ struct amdgpu_bo_list_entry uf_entry; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index d7a9573..e29e7b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -379,6 +379,58 @@ retry: return r; } +/* Last resort, try to evict something from the current working set */ +static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, + struct amdgpu_bo_list_entry *lobj) +{ + uint32_t domain = lobj->robj->allowed_domains; + int r; + + if (!p->evictable) + return false; + + for (;&p->evictable->tv.head != &p->validated; + p->evictable = list_prev_entry(p->evictable, tv.head)) { + + struct amdgpu_bo_list_entry *candidate = p->evictable; + struct amdgpu_bo *bo = candidate->robj; + u64 initial_bytes_moved; + uint32_t other; + + /* If we reached our current BO we can forget it */ + if (candidate == lobj) + break; + + other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); + + /* Check if this BO is in one of the domains we need space for */ + if (!(other & domain)) + continue; + + /* Check if we can move this BO somewhere else */ + other = bo->allowed_domains & ~domain; + if (!other) + continue; + + /* Good we can try to move this BO somewhere else */ + amdgpu_ttm_placement_from_domain(bo, other); + initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved); + r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); + p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) - + initial_bytes_moved; + + if (unlikely(r)) + break; + + p->evictable = list_prev_entry(p->evictable, tv.head); + list_move(&candidate->tv.head, &p->validated); + + return true; + } + + return false; +} + int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, struct list_head *validated) { @@ -403,9 +455,15 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, binding_userptr = true; } - r = amdgpu_cs_bo_validate(p, bo); + if (p->evictable == lobj) + p->evictable = NULL; + + do { + r = amdgpu_cs_bo_validate(p, bo); + } while (r == -ENOMEM && amdgpu_cs_try_evict(p, lobj)); if (r) return r; + if (bo->shadow) { r = amdgpu_cs_bo_validate(p, bo); if (r) @@ -533,6 +591,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev); p->bytes_moved = 0; + p->evictable = list_last_entry(&p->validated, + struct amdgpu_bo_list_entry, + tv.head); r = amdgpu_cs_list_validate(p, &duplicates); if (r) { -- cgit v1.1 From 791a57db3e5eda12e30a5f496c84c1a9e20e8c0c Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 31 Aug 2016 17:25:49 +0800 Subject: drm/amd/powerplay: refine struct name for code style reason. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c | 2 +- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 4 ++-- drivers/gpu/drm/amd/powerplay/inc/power_state.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c index 6c321b0..ccf7ebe 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c @@ -1523,7 +1523,7 @@ int get_number_of_vce_state_table_entries( int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, unsigned long i, - struct PP_VCEState *vce_state, + struct pp_vce_state *vce_state, void **clock_info, unsigned long *flag) { diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index aca94e0..25f4b42 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -36,7 +36,7 @@ struct pp_instance; struct pp_hwmgr; struct pp_hw_power_state; struct pp_power_state; -struct PP_VCEState; +struct pp_vce_state; struct phm_fan_speed_info; struct pp_atomctrl_voltage_table; @@ -354,7 +354,7 @@ struct pp_table_func { int (*pptable_get_vce_state_table_entry)( struct pp_hwmgr *hwmgr, unsigned long i, - struct PP_VCEState *vce_state, + struct pp_vce_state *vce_state, void **clock_info, unsigned long *flag); }; diff --git a/drivers/gpu/drm/amd/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/powerplay/inc/power_state.h index a3f0ce4..08b4b9f 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/power_state.h +++ b/drivers/gpu/drm/amd/powerplay/inc/power_state.h @@ -158,7 +158,7 @@ struct pp_power_state { /*Structure to hold a VCE state entry*/ -struct PP_VCEState { +struct pp_vce_state { uint32_t evclk; uint32_t ecclk; uint32_t sclk; -- cgit v1.1 From 48d7b759a8bc96054b59fc07098e05dcca0c93bb Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 31 Aug 2016 17:27:11 +0800 Subject: drm/amd/powerplay: add vce state tables initialize for ppt v1. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../amd/powerplay/hwmgr/tonga_processpptables.c | 58 ++++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 22 ++++++-- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c index cfb647f..622ac02 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c @@ -1164,6 +1164,54 @@ static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, return result; } +static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr) +{ + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + const ATOM_Tonga_VCE_State_Table *vce_state_table = + (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pp_table) + le16_to_cpu(pp_table->usVCEStateTableOffset)); + + if (vce_state_table == NULL) + return 0; + + return vce_state_table->ucNumEntries; +} + + +static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i, + struct pp_vce_state *vce_state, void **clock_info, uint32_t *flag) +{ + const ATOM_Tonga_VCE_State_Record *vce_state_record; + const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr); + const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usVCEStateTableOffset)); + const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usSclkDependencyTableOffset)); + const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usMclkDependencyTableOffset)); + const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usMMDependencyTableOffset)); + + PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries), + "Requested state entry ID is out of range!", + return -EINVAL); + + vce_state_record = (ATOM_Tonga_VCE_State_Record *)((char *)&vce_state_table->entries[1] + + (sizeof(ATOM_Tonga_VCE_State_Record) * i)); + + *flag = vce_state_record->ucFlag; + + vce_state->evclk = mm_dep_table->entries[vce_state_record->ucVCEClockIndex].ulEClk; + vce_state->ecclk = mm_dep_table->entries[vce_state_record->ucVCEClockIndex].ulEClk; + vce_state->sclk = sclk_dep_table->entries[vce_state_record->ucSCLKIndex].ulSclk; + + if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries) + vce_state->mclk = mclk_dep_table->entries[mclk_dep_table->ucNumEntries - 1].ulMclk; + else + vce_state->mclk = mclk_dep_table->entries[vce_state_record->ucMCLKIndex].ulMclk; + + return 0; +} + /** * Create a Power State out of an entry in the PowerPlay table. * This function is called by the hardware back-end. @@ -1181,6 +1229,8 @@ int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, const ATOM_Tonga_State_Array * state_arrays; const ATOM_Tonga_State *state_entry; const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + int i, j; + uint32_t flags = 0; PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;); power_state->classification.bios_index = entry_index; @@ -1210,5 +1260,13 @@ int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, PP_StateClassificationFlag_Boot)) result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); + hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr); + + if ((i != 0) && (i <= PP_MAX_VCE_LEVELS)) { + for (j = 0; j < i; j++) + ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags); + } + return result; } + diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 25f4b42..1456565 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -31,16 +31,13 @@ #include "hwmgr_ppt.h" #include "ppatomctrl.h" #include "hwmgr_ppt.h" +#include "power_state.h" struct pp_instance; struct pp_hwmgr; -struct pp_hw_power_state; -struct pp_power_state; -struct pp_vce_state; struct phm_fan_speed_info; struct pp_atomctrl_voltage_table; - extern int amdgpu_powercontainment; extern int amdgpu_sclk_deep_sleep_en; @@ -52,7 +49,6 @@ enum DISPLAY_GAP { }; typedef enum DISPLAY_GAP DISPLAY_GAP; - struct vi_dpm_level { bool enabled; uint32_t value; @@ -573,6 +569,18 @@ struct phm_microcode_version_info { uint32_t NB; }; +#define PP_MAX_VCE_LEVELS 6 + +enum PP_VCE_LEVEL { + PP_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */ + PP_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */ + PP_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */ + PP_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */ + PP_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */ + PP_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */ +}; + + /** * The main hardware manager structure. */ @@ -586,6 +594,10 @@ struct pp_hwmgr { uint32_t soft_pp_table_size; void *hardcode_pp_table; bool need_pp_table_upload; + + struct pp_vce_state vce_states[PP_MAX_VCE_LEVELS]; + uint32_t num_vce_state_tables; + enum amd_dpm_forced_level dpm_level; bool block_hw_access; struct phm_gfx_arbiter gfx_arbiter; -- cgit v1.1 From cfcc283cee50e98e47a56ab2b3f85540a1f93ab4 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 31 Aug 2016 18:13:08 +0800 Subject: drm/amd/powerplay: refine struct name for coding style reason. delete useless member. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/power_state.h | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/powerplay/inc/power_state.h index 08b4b9f..9ceaed9 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/power_state.h +++ b/drivers/gpu/drm/amd/powerplay/inc/power_state.h @@ -171,30 +171,28 @@ enum PP_MMProfilingState { PP_MMProfilingState_Stopped }; -struct PP_Clock_Engine_Request { - unsigned long clientType; - unsigned long ctxid; +struct pp_clock_engine_request { + unsigned long client_type; + unsigned long ctx_id; uint64_t context_handle; unsigned long sclk; - unsigned long sclkHardMin; + unsigned long sclk_hard_min; unsigned long mclk; unsigned long iclk; unsigned long evclk; unsigned long ecclk; - unsigned long ecclkHardMin; + unsigned long ecclk_hard_min; unsigned long vclk; unsigned long dclk; - unsigned long samclk; - unsigned long acpclk; - unsigned long sclkOverdrive; - unsigned long mclkOverdrive; + unsigned long sclk_over_drive; + unsigned long mclk_over_drive; unsigned long sclk_threshold; unsigned long flag; unsigned long vclk_ceiling; unsigned long dclk_ceiling; unsigned long num_cus; - unsigned long pmflag; - enum PP_MMProfilingState MMProfilingState; + unsigned long pm_flag; + enum PP_MMProfilingState mm_profiling_state; }; #endif -- cgit v1.1 From 48fad3aff638c7bc16656e31047f689aa44020a1 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 1 Sep 2016 02:30:42 +0800 Subject: drm/amd/powerplay: original power state table should not be changed. power state table was set based on vbios and should not be changed. when client need to change power state, just make a copy and send to smu. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 1 - drivers/gpu/drm/amd/powerplay/eventmgr/psm.c | 5 +++-- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 2de34a5..3e7235f 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -538,7 +538,6 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); break; case AMD_PP_EVENT_READJUST_POWER_STATE: - pp_handle->hwmgr->current_ps = pp_handle->hwmgr->boot_ps; ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); break; default: diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c index a46225c..1d1875a 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c @@ -70,11 +70,12 @@ int psm_set_states(struct pp_eventmgr *eventmgr, unsigned long *state_id) int i; table_entries = hwmgr->num_ps; + state = hwmgr->ps; for (i = 0; i < table_entries; i++) { if (state->id == *state_id) { - hwmgr->request_ps = state; + memcpy(hwmgr->request_ps, state, hwmgr->ps_size); return 0; } state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); @@ -106,7 +107,7 @@ int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip) if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) { phm_apply_state_adjust_rules(hwmgr, requested, pcurrent); phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware); - hwmgr->current_ps = requested; + memcpy(hwmgr->current_ps, hwmgr->request_ps, hwmgr->ps_size); } return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 50d465d..9794f10 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -128,6 +128,8 @@ int hwmgr_fini(struct pp_hwmgr *hwmgr) kfree(hwmgr->set_temperature_range.function_list); kfree(hwmgr->ps); + kfree(hwmgr->current_ps); + kfree(hwmgr->request_ps); kfree(hwmgr); return 0; } @@ -152,10 +154,17 @@ int hw_init_power_state_table(struct pp_hwmgr *hwmgr) sizeof(struct pp_power_state); hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL); - if (hwmgr->ps == NULL) return -ENOMEM; + hwmgr->request_ps = kzalloc(size, GFP_KERNEL); + if (hwmgr->request_ps == NULL) + return -ENOMEM; + + hwmgr->current_ps = kzalloc(size, GFP_KERNEL); + if (hwmgr->current_ps == NULL) + return -ENOMEM; + state = hwmgr->ps; for (i = 0; i < table_entries; i++) { @@ -163,7 +172,8 @@ int hw_init_power_state_table(struct pp_hwmgr *hwmgr) if (state->classification.flags & PP_StateClassificationFlag_Boot) { hwmgr->boot_ps = state; - hwmgr->current_ps = hwmgr->request_ps = state; + memcpy(hwmgr->current_ps, state, size); + memcpy(hwmgr->request_ps, state, size); } state->id = i + 1; /* assigned unique num for every power state id */ @@ -173,6 +183,7 @@ int hw_init_power_state_table(struct pp_hwmgr *hwmgr) state = (struct pp_power_state *)((unsigned long)state + size); } + return 0; } -- cgit v1.1 From deca1d1f16eebfa0d070eed50a221e01cf716ee0 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 1 Sep 2016 13:29:49 -0400 Subject: drm/amd/amdgpu: Add GRBM lock to various SI functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing lock around SE/SH/INSTANCE selections. Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 040bc7f..1f1b619 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -946,6 +946,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev, u32 disabled_rbs = 0; u32 enabled_rbs = 0; + mutex_lock(&adev->grbm_idx_mutex); for (i = 0; i < se_num; i++) { for (j = 0; j < sh_per_se; j++) { gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff); @@ -954,6 +955,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev, } } gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); mask = 1; for (i = 0; i < max_rb_num_per_se * se_num; i++) { @@ -965,6 +967,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev, adev->gfx.config.backend_enable_mask = enabled_rbs; adev->gfx.config.num_rbs = hweight32(enabled_rbs); + mutex_lock(&adev->grbm_idx_mutex); for (i = 0; i < se_num; i++) { gfx_v6_0_select_se_sh(adev, i, 0xffffffff, 0xffffffff); data = 0; @@ -986,6 +989,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev, WREG32(PA_SC_RASTER_CONFIG, data); } gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); } /* static void gmc_v6_0_init_compute_vmid(struct amdgpu_device *adev) @@ -1017,6 +1021,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev, u32 data, mask; u32 active_cu = 0; + mutex_lock(&adev->grbm_idx_mutex); for (i = 0; i < se_num; i++) { for (j = 0; j < sh_per_se; j++) { gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff); @@ -1035,6 +1040,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev, } } gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); } static void gfx_v6_0_gpu_init(struct amdgpu_device *adev) @@ -2475,10 +2481,12 @@ static u32 gfx_v6_0_get_cu_active_bitmap(struct amdgpu_device *adev, u32 mask = 0, tmp, tmp1; int i; + mutex_lock(&adev->grbm_idx_mutex); gfx_v6_0_select_se_sh(adev, se, sh, 0xffffffff); tmp = RREG32(CC_GC_SHADER_ARRAY_CONFIG); tmp1 = RREG32(GC_USER_SHADER_ARRAY_CONFIG); gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); tmp &= 0xffff0000; -- cgit v1.1 From 142333dbb9fbecf0e6693ac4545676f36225ee89 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 1 Sep 2016 13:31:35 -0400 Subject: drm/amd/amdgpu: Simplify mask creation in gfx6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 1f1b619..6569554 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -911,13 +911,7 @@ static void gfx_v6_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, static u32 gfx_v6_0_create_bitmask(u32 bit_width) { - u32 i, mask = 0; - - for (i = 0; i < bit_width; i++) { - mask <<= 1; - mask |= 1; - } - return mask; + return (u32)(((u64)1 << bit_width) - 1); } static u32 gfx_v6_0_get_rb_disabled(struct amdgpu_device *adev, -- cgit v1.1 From 4aeacf0f9aa8a6ade9ce85f0074ba848230eb34f Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 1 Sep 2016 13:39:37 -0400 Subject: drm/amd/amdgpu: Various tidy ups for gfx6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Various whitespace and logical simplifications for gfx6. Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 40 +++++------------------------------ 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 6569554..f430d6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -1211,11 +1211,8 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev) SC_EARLYZ_TILE_FIFO_SIZE(adev->gfx.config.sc_earlyz_tile_fifo_size))); WREG32(VGT_NUM_INSTANCES, 1); - WREG32(CP_PERFMON_CNTL, 0); - WREG32(SQ_CONFIG, 0); - WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | FORCE_EOV_MAX_REZ_CNT(255))); @@ -1240,7 +1237,6 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev) WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); udelay(50); - } @@ -1661,21 +1657,14 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev) static u32 gfx_v6_0_ring_get_rptr_gfx(struct amdgpu_ring *ring) { - u32 rptr; - - rptr = ring->adev->wb.wb[ring->rptr_offs]; - - return rptr; + return ring->adev->wb.wb[ring->rptr_offs]; } static u32 gfx_v6_0_ring_get_wptr_gfx(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - u32 wptr; - wptr = RREG32(CP_RB0_WPTR); - - return wptr; + return RREG32(CP_RB0_WPTR); } static void gfx_v6_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) @@ -1688,9 +1677,7 @@ static void gfx_v6_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) static u32 gfx_v6_0_ring_get_rptr_compute(struct amdgpu_ring *ring) { - u32 rptr = ring->adev->wb.wb[ring->rptr_offs]; - - return rptr; + return ring->adev->wb.wb[ring->rptr_offs]; } static u32 gfx_v6_0_ring_get_wptr_compute(struct amdgpu_ring *ring) @@ -1748,14 +1735,12 @@ static int gfx_v6_0_cp_compute_resume(struct amdgpu_device *adev) ring->wptr = 0; WREG32(CP_RB1_WPTR, ring->wptr); - rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); WREG32(CP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr)); WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF); mdelay(1); WREG32(CP_RB1_CNTL, tmp); - WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); ring = &adev->gfx.compute_ring[1]; @@ -1775,7 +1760,6 @@ static int gfx_v6_0_cp_compute_resume(struct amdgpu_device *adev) mdelay(1); WREG32(CP_RB2_CNTL, tmp); - WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); adev->gfx.compute_ring[0].ready = true; @@ -1803,12 +1787,7 @@ static void gfx_v6_0_cp_enable(struct amdgpu_device *adev, bool enable) static int gfx_v6_0_cp_load_microcode(struct amdgpu_device *adev) { - int r; - - r = gfx_v6_0_cp_gfx_load_microcode(adev); - - return r; - + return gfx_v6_0_cp_gfx_load_microcode(adev); } static void gfx_v6_0_enable_gui_idle_interrupt(struct amdgpu_device *adev, @@ -2150,7 +2129,6 @@ static void gfx_v6_0_rlc_stop(struct amdgpu_device *adev) WREG32(RLC_CNTL, 0); gfx_v6_0_enable_gui_idle_interrupt(adev, false); - gfx_v6_0_wait_for_rlc_serdes(adev); } @@ -2201,11 +2179,8 @@ static int gfx_v6_0_rlc_resume(struct amdgpu_device *adev) return -EINVAL; gfx_v6_0_rlc_stop(adev); - gfx_v6_0_rlc_reset(adev); - gfx_v6_0_init_pg(adev); - gfx_v6_0_init_cg(adev); WREG32(RLC_RL_BASE, 0); @@ -2232,7 +2207,6 @@ static int gfx_v6_0_rlc_resume(struct amdgpu_device *adev) WREG32(RLC_UCODE_ADDR, 0); gfx_v6_0_enable_lbpw(adev, gfx_v6_0_lbpw_supported(adev)); - gfx_v6_0_rlc_start(adev); return 0; @@ -2256,7 +2230,6 @@ static void gfx_v6_0_enable_cgcg(struct amdgpu_device *adev, bool enable) WREG32(RLC_SERDES_WR_CTRL, 0x00b000ff); gfx_v6_0_wait_for_rlc_serdes(adev); - gfx_v6_0_update_rlc(adev, tmp); WREG32(RLC_SERDES_WR_CTRL, 0x007000ff); @@ -2908,13 +2881,10 @@ static bool gfx_v6_0_is_idle(void *handle) static int gfx_v6_0_wait_for_idle(void *handle) { unsigned i; - u32 tmp; struct amdgpu_device *adev = (struct amdgpu_device *)handle; for (i = 0; i < adev->usec_timeout; i++) { - tmp = RREG32(GRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK; - - if (!tmp) + if (gfx_v6_0_is_idle(handle)) return 0; udelay(1); } -- cgit v1.1 From 6f924e202675651369b85ee8bea591768bf7a55d Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 2 Sep 2016 08:13:48 -0400 Subject: drm/amd/amdgpu: Merge get_rptr functions in gfx6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index f430d6a..d090f26 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -1655,7 +1655,7 @@ static int gfx_v6_0_cp_gfx_resume(struct amdgpu_device *adev) return 0; } -static u32 gfx_v6_0_ring_get_rptr_gfx(struct amdgpu_ring *ring) +static u32 gfx_v6_0_ring_get_rptr(struct amdgpu_ring *ring) { return ring->adev->wb.wb[ring->rptr_offs]; } @@ -1675,11 +1675,6 @@ static void gfx_v6_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) (void)RREG32(CP_RB0_WPTR); } -static u32 gfx_v6_0_ring_get_rptr_compute(struct amdgpu_ring *ring) -{ - return ring->adev->wb.wb[ring->rptr_offs]; -} - static u32 gfx_v6_0_ring_get_wptr_compute(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; @@ -3129,7 +3124,7 @@ const struct amd_ip_funcs gfx_v6_0_ip_funcs = { }; static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { - .get_rptr = gfx_v6_0_ring_get_rptr_gfx, + .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr_gfx, .set_wptr = gfx_v6_0_ring_set_wptr_gfx, .parse_cs = NULL, @@ -3146,7 +3141,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { }; static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { - .get_rptr = gfx_v6_0_ring_get_rptr_compute, + .get_rptr = gfx_v6_0_ring_get_rptr, .get_wptr = gfx_v6_0_ring_get_wptr_compute, .set_wptr = gfx_v6_0_ring_set_wptr_compute, .parse_cs = NULL, -- cgit v1.1 From f1c0efc537d4d66967cdacd6ccbb93257dc8da3d Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 2 Sep 2016 08:14:42 -0400 Subject: drm/amd/amdgpu: Merge get_rptr functions in gfx7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index f4fbec3..1c3bb2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2443,7 +2443,7 @@ static int gfx_v7_0_cp_gfx_resume(struct amdgpu_device *adev) return 0; } -static u32 gfx_v7_0_ring_get_rptr_gfx(struct amdgpu_ring *ring) +static u32 gfx_v7_0_ring_get_rptr(struct amdgpu_ring *ring) { return ring->adev->wb.wb[ring->rptr_offs]; } @@ -2463,11 +2463,6 @@ static void gfx_v7_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) (void)RREG32(mmCP_RB0_WPTR); } -static u32 gfx_v7_0_ring_get_rptr_compute(struct amdgpu_ring *ring) -{ - return ring->adev->wb.wb[ring->rptr_offs]; -} - static u32 gfx_v7_0_ring_get_wptr_compute(struct amdgpu_ring *ring) { /* XXX check if swapping is necessary on BE */ @@ -4928,7 +4923,7 @@ const struct amd_ip_funcs gfx_v7_0_ip_funcs = { }; static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { - .get_rptr = gfx_v7_0_ring_get_rptr_gfx, + .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_gfx, .set_wptr = gfx_v7_0_ring_set_wptr_gfx, .parse_cs = NULL, @@ -4946,7 +4941,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { }; static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { - .get_rptr = gfx_v7_0_ring_get_rptr_compute, + .get_rptr = gfx_v7_0_ring_get_rptr, .get_wptr = gfx_v7_0_ring_get_wptr_compute, .set_wptr = gfx_v7_0_ring_set_wptr_compute, .parse_cs = NULL, -- cgit v1.1 From e7706b422c087da851448c420c90821622ee1721 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 2 Sep 2016 08:15:42 -0400 Subject: drm/amd/amdgpu: Merge get_rptr functions in gfx8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index b8bc413..24480f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5831,7 +5831,7 @@ static int gfx_v8_0_set_clockgating_state(void *handle, return 0; } -static u32 gfx_v8_0_ring_get_rptr_gfx(struct amdgpu_ring *ring) +static u32 gfx_v8_0_ring_get_rptr(struct amdgpu_ring *ring) { return ring->adev->wb.wb[ring->rptr_offs]; } @@ -6047,11 +6047,6 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring, } } -static u32 gfx_v8_0_ring_get_rptr_compute(struct amdgpu_ring *ring) -{ - return ring->adev->wb.wb[ring->rptr_offs]; -} - static u32 gfx_v8_0_ring_get_wptr_compute(struct amdgpu_ring *ring) { return ring->adev->wb.wb[ring->wptr_offs]; @@ -6259,7 +6254,7 @@ const struct amd_ip_funcs gfx_v8_0_ip_funcs = { }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { - .get_rptr = gfx_v8_0_ring_get_rptr_gfx, + .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_gfx, .set_wptr = gfx_v8_0_ring_set_wptr_gfx, .parse_cs = NULL, @@ -6278,7 +6273,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { - .get_rptr = gfx_v8_0_ring_get_rptr_compute, + .get_rptr = gfx_v8_0_ring_get_rptr, .get_wptr = gfx_v8_0_ring_get_wptr_compute, .set_wptr = gfx_v8_0_ring_set_wptr_compute, .parse_cs = NULL, -- cgit v1.1 From 832c6ef765a6943edeb30db25f33c0a56560c532 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 2 Sep 2016 08:19:15 -0400 Subject: drm/amd/amdgpu: Merge get_wptr functions in gfx6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index d090f26..a6b7617 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -1660,11 +1660,18 @@ static u32 gfx_v6_0_ring_get_rptr(struct amdgpu_ring *ring) return ring->adev->wb.wb[ring->rptr_offs]; } -static u32 gfx_v6_0_ring_get_wptr_gfx(struct amdgpu_ring *ring) +static u32 gfx_v6_0_ring_get_wptr(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - return RREG32(CP_RB0_WPTR); + if (ring == &adev->gfx.gfx_ring[0]) + return RREG32(CP_RB0_WPTR); + else if (ring == &adev->gfx.compute_ring[0]) + return RREG32(CP_RB1_WPTR); + else if (ring == &adev->gfx.compute_ring[1]) + return RREG32(CP_RB2_WPTR); + else + BUG(); } static void gfx_v6_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) @@ -1675,22 +1682,6 @@ static void gfx_v6_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) (void)RREG32(CP_RB0_WPTR); } -static u32 gfx_v6_0_ring_get_wptr_compute(struct amdgpu_ring *ring) -{ - struct amdgpu_device *adev = ring->adev; - u32 wptr; - - if (ring == &adev->gfx.compute_ring[0]) { - wptr = RREG32(CP_RB1_WPTR); - } else if (ring == &adev->gfx.compute_ring[1]) { - wptr = RREG32(CP_RB2_WPTR); - } else { - BUG(); - } - - return wptr; -} - static void gfx_v6_0_ring_set_wptr_compute(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; @@ -3125,7 +3116,7 @@ const struct amd_ip_funcs gfx_v6_0_ip_funcs = { static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .get_rptr = gfx_v6_0_ring_get_rptr, - .get_wptr = gfx_v6_0_ring_get_wptr_gfx, + .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_gfx, .parse_cs = NULL, .emit_ib = gfx_v6_0_ring_emit_ib_gfx, @@ -3142,7 +3133,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { .get_rptr = gfx_v6_0_ring_get_rptr, - .get_wptr = gfx_v6_0_ring_get_wptr_compute, + .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_compute, .parse_cs = NULL, .emit_ib = gfx_v6_0_ring_emit_ib_compute, -- cgit v1.1 From ea4a8c1d94e98693612b01908076d6133be52c6e Mon Sep 17 00:00:00 2001 From: Maruthi Srinivas Bayyavarapu Date: Tue, 30 Aug 2016 15:16:36 +0530 Subject: drm/amdgpu: add VCE VM mode support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds VCE VM mode support from Stoney onwards. Session tracking is an open issue, yet to be supported. v2: Fixed warnings from checkpatch.pl Signed-off-by: Maruthi Bayyavarapu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 63 +++++++++++++++++++++++++++++++++-- drivers/gpu/drm/amd/amdgpu/vid.h | 4 +++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index b083c36..a55ddc0 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -775,6 +775,39 @@ static int vce_v3_0_set_powergating_state(void *handle, return vce_v3_0_start(adev); } +static void vce_v3_0_ring_emit_ib(struct amdgpu_ring *ring, + struct amdgpu_ib *ib, unsigned int vm_id, bool ctx_switch) +{ + amdgpu_ring_write(ring, VCE_CMD_IB_VM); + amdgpu_ring_write(ring, vm_id); + amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); + amdgpu_ring_write(ring, ib->length_dw); +} + +static void vce_v3_0_emit_vm_flush(struct amdgpu_ring *ring, + unsigned int vm_id, uint64_t pd_addr) +{ + amdgpu_ring_write(ring, VCE_CMD_UPDATE_PTB); + amdgpu_ring_write(ring, vm_id); + amdgpu_ring_write(ring, pd_addr >> 12); + + amdgpu_ring_write(ring, VCE_CMD_FLUSH_TLB); + amdgpu_ring_write(ring, vm_id); + amdgpu_ring_write(ring, VCE_CMD_END); +} + +static void vce_v3_0_emit_pipeline_sync(struct amdgpu_ring *ring) +{ + uint32_t seq = ring->fence_drv.sync_seq; + uint64_t addr = ring->fence_drv.gpu_addr; + + amdgpu_ring_write(ring, VCE_CMD_WAIT_GE); + amdgpu_ring_write(ring, lower_32_bits(addr)); + amdgpu_ring_write(ring, upper_32_bits(addr)); + amdgpu_ring_write(ring, seq); +} + const struct amd_ip_funcs vce_v3_0_ip_funcs = { .name = "vce_v3_0", .early_init = vce_v3_0_early_init, @@ -795,7 +828,7 @@ const struct amd_ip_funcs vce_v3_0_ip_funcs = { .set_powergating_state = vce_v3_0_set_powergating_state, }; -static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = { +static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { .get_rptr = vce_v3_0_ring_get_rptr, .get_wptr = vce_v3_0_ring_get_wptr, .set_wptr = vce_v3_0_ring_set_wptr, @@ -810,12 +843,36 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = { .end_use = amdgpu_vce_ring_end_use, }; +static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { + .get_rptr = vce_v3_0_ring_get_rptr, + .get_wptr = vce_v3_0_ring_get_wptr, + .set_wptr = vce_v3_0_ring_set_wptr, + .parse_cs = NULL, + .emit_ib = vce_v3_0_ring_emit_ib, + .emit_vm_flush = vce_v3_0_emit_vm_flush, + .emit_pipeline_sync = vce_v3_0_emit_pipeline_sync, + .emit_fence = amdgpu_vce_ring_emit_fence, + .test_ring = amdgpu_vce_ring_test_ring, + .test_ib = amdgpu_vce_ring_test_ib, + .insert_nop = amdgpu_ring_insert_nop, + .pad_ib = amdgpu_ring_generic_pad_ib, + .begin_use = amdgpu_vce_ring_begin_use, + .end_use = amdgpu_vce_ring_end_use, +}; + static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev) { int i; - for (i = 0; i < adev->vce.num_rings; i++) - adev->vce.ring[i].funcs = &vce_v3_0_ring_funcs; + if (adev->asic_type >= CHIP_STONEY) { + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].funcs = &vce_v3_0_ring_vm_funcs; + DRM_INFO("VCE enabled in VM mode\n"); + } else { + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].funcs = &vce_v3_0_ring_phys_funcs; + DRM_INFO("VCE enabled in physical mode\n"); + } } static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/vid.h b/drivers/gpu/drm/amd/amdgpu/vid.h index 062ee16..f62b261 100644 --- a/drivers/gpu/drm/amd/amdgpu/vid.h +++ b/drivers/gpu/drm/amd/amdgpu/vid.h @@ -369,4 +369,8 @@ #define VCE_CMD_IB_AUTO 0x00000005 #define VCE_CMD_SEMAPHORE 0x00000006 +#define VCE_CMD_IB_VM 0x00000102 +#define VCE_CMD_WAIT_GE 0x00000106 +#define VCE_CMD_UPDATE_PTB 0x00000107 +#define VCE_CMD_FLUSH_TLB 0x00000108 #endif -- cgit v1.1 From d4946ccfd0373610ffa6181cffae236bf07d3aff Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Fri, 26 Aug 2016 14:15:03 +0800 Subject: drm/amdgpu: new method to sync ce&de MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sync switch buffer scheme with windows kmd for gfx v8, step2: Insert 128NOP after&before VM flush to prevent CE vm fault. Signed-off-by: Monk Liu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 24480f1..c49d06b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5911,12 +5911,6 @@ static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, { u32 header, control = 0; - /* insert SWITCH_BUFFER packet before first IB in the ring frame */ - if (ctx_switch) { - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); - amdgpu_ring_write(ring, 0); - } - if (ib->flags & AMDGPU_IB_FLAG_CE) header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); else @@ -5986,14 +5980,6 @@ static void gfx_v8_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, seq); amdgpu_ring_write(ring, 0xffffffff); amdgpu_ring_write(ring, 4); /* poll interval */ - - if (usepfp) { - /* synce CE with ME to prevent CE fetch CEIB before context switch done */ - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); - amdgpu_ring_write(ring, 0); - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); - amdgpu_ring_write(ring, 0); - } } static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring, @@ -6001,6 +5987,10 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring, { int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX); + /* GFX8 emits 128 dw nop to prevent DE do vm_flush before CE finish CEIB */ + if (usepfp) + amdgpu_ring_insert_nop(ring, 128); + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) | WRITE_DATA_DST_SEL(0)) | @@ -6040,10 +6030,8 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring, /* sync PFP to ME, otherwise we might get invalid PFP reads */ amdgpu_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); amdgpu_ring_write(ring, 0x0); - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); - amdgpu_ring_write(ring, 0); - amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); - amdgpu_ring_write(ring, 0); + /* GFX8 emits 128 dw nop to prevent CE access VM before vm_flush finish */ + amdgpu_ring_insert_nop(ring, 128); } } -- cgit v1.1 From 3aecd24c65b9539b6faac2a52a9aaa7bc90f4677 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Thu, 25 Aug 2016 15:40:48 +0800 Subject: drm/amdgpu: change job->ctx field name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit job->ctx actually is a fence_context of the entity it belongs to, naming it as ctx is too vague, and we'll need add amdgpu_ctx into the job structure later. Signed-off-by: Monk Liu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 12 ++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 39baabe..10ec29c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1241,7 +1241,7 @@ struct amdgpu_job { struct fence *fence; /* the hw fence */ uint32_t num_ibs; void *owner; - uint64_t ctx; + uint64_t fence_ctx; /* the fence_context this job uses */ bool vm_needs_flush; unsigned vm_id; uint64_t vm_pd_addr; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index e29e7b9..56bde64 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -989,7 +989,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, } job->owner = p->filp; - job->ctx = entity->fence_context; + job->fence_ctx = entity->fence_context; p->fence = fence_get(&job->base.s_fence->finished); cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, p->fence); job->uf_sequence = cs->out.handle; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 11f2fba..04263f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -124,7 +124,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, bool skip_preamble, need_ctx_switch; unsigned patch_offset = ~0; struct amdgpu_vm *vm; - uint64_t ctx; + uint64_t fence_ctx; unsigned i; int r = 0; @@ -135,10 +135,10 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, /* ring tests don't use a job */ if (job) { vm = job->vm; - ctx = job->ctx; + fence_ctx = job->fence_ctx; } else { vm = NULL; - ctx = 0; + fence_ctx = 0; } if (!ring->ready) { @@ -174,8 +174,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, /* always set cond_exec_polling to CONTINUE */ *ring->cond_exe_cpu_addr = 1; - skip_preamble = ring->current_ctx == ctx; - need_ctx_switch = ring->current_ctx != ctx; + skip_preamble = ring->current_ctx == fence_ctx; + need_ctx_switch = ring->current_ctx != fence_ctx; for (i = 0; i < num_ibs; ++i) { ib = &ibs[i]; @@ -209,7 +209,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, if (patch_offset != ~0 && ring->funcs->patch_cond_exec) amdgpu_ring_patch_cond_exec(ring, patch_offset); - ring->current_ctx = ctx; + ring->current_ctx = fence_ctx; if (ring->funcs->emit_switch_buffer) amdgpu_ring_emit_switch_buffer(ring); amdgpu_ring_commit(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 6674d40..ac8d401 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -124,7 +124,7 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, return r; job->owner = owner; - job->ctx = entity->fence_context; + job->fence_ctx = entity->fence_context; *f = fence_get(&job->base.s_fence->finished); amdgpu_job_free_resources(job); amd_sched_entity_push_job(&job->base); -- cgit v1.1 From 74b0b157845748e5817cae56c891b05d98da5f47 Mon Sep 17 00:00:00 2001 From: jimqu Date: Wed, 7 Sep 2016 17:09:12 +0800 Subject: drm/amd/amdgpu: S4 issue for amdgpu (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reset the asic if adapter is not powerdown when doing freeze() thaw() and restore(), in order to get a valid state of adapter. v2: squash in warning fix from Rex Signed-off-by: JimQu Acked-by: Christian König Tested By: Shawn Starr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 ++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 23 +++++++++++++++++++++-- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 1aa0364..d324a07 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1895,6 +1895,10 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) /* Shut down the device */ pci_disable_device(dev->pdev); pci_set_power_state(dev->pdev, PCI_D3hot); + } else { + r = amdgpu_asic_reset(adev); + if (r) + DRM_ERROR("amdgpu asic reset failed\n"); } if (fbcon) { @@ -1925,22 +1929,26 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; - if (fbcon) { + if (fbcon) console_lock(); - } + if (resume) { pci_set_power_state(dev->pdev, PCI_D0); pci_restore_state(dev->pdev); - if (pci_enable_device(dev->pdev)) { + r = pci_enable_device(dev->pdev); + if (r) { if (fbcon) console_unlock(); - return -1; + return r; } } /* post card */ - if (!amdgpu_card_posted(adev)) - amdgpu_atom_asic_init(adev->mode_info.atom_context); + if (!amdgpu_card_posted(adev) || !resume) { + r = amdgpu_atom_asic_init(adev->mode_info.atom_context); + if (r) + DRM_ERROR("amdgpu asic init failed\n"); + } r = amdgpu_resume(adev); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index ea54e30..3bbc0faf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -487,6 +487,7 @@ amdgpu_pci_shutdown(struct pci_dev *pdev) static int amdgpu_pmops_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); return amdgpu_device_suspend(drm_dev, true, true); } @@ -509,6 +510,7 @@ static int amdgpu_pmops_resume(struct device *dev) static int amdgpu_pmops_freeze(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); return amdgpu_device_suspend(drm_dev, false, true); } @@ -516,6 +518,23 @@ static int amdgpu_pmops_freeze(struct device *dev) static int amdgpu_pmops_thaw(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); + + struct drm_device *drm_dev = pci_get_drvdata(pdev); + return amdgpu_device_resume(drm_dev, false, true); +} + +static int amdgpu_pmops_poweroff(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + struct drm_device *drm_dev = pci_get_drvdata(pdev); + return amdgpu_device_suspend(drm_dev, true, true); +} + +static int amdgpu_pmops_restore(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); return amdgpu_device_resume(drm_dev, false, true); } @@ -622,8 +641,8 @@ static const struct dev_pm_ops amdgpu_pm_ops = { .resume = amdgpu_pmops_resume, .freeze = amdgpu_pmops_freeze, .thaw = amdgpu_pmops_thaw, - .poweroff = amdgpu_pmops_freeze, - .restore = amdgpu_pmops_resume, + .poweroff = amdgpu_pmops_poweroff, + .restore = amdgpu_pmops_restore, .runtime_suspend = amdgpu_pmops_runtime_suspend, .runtime_resume = amdgpu_pmops_runtime_resume, .runtime_idle = amdgpu_pmops_runtime_idle, -- cgit v1.1 From 2377cd945fcd024a4083729a90b33231d2e1e721 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 5 Sep 2016 17:49:19 +0800 Subject: drm/amd/powerplay: enable/disable auto thermal throttle for tonga. Signed-off-by: Rex Zhu Acked-by: Flora Cui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c | 82 +++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c index e7c281f..5616ec5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -203,6 +203,7 @@ uint8_t tonga_get_voltage_id(pp_atomctrl_voltage_table *voltage_table, return i - 1; } + /** * @brief PhwTonga_GetVoltageOrder * Returns index of requested voltage record in lookup(table) @@ -4327,6 +4328,79 @@ int tonga_program_voting_clients(struct pp_hwmgr *hwmgr) return 0; } +static void tonga_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources) +{ + bool protection; + enum DPM_EVENT_SRC src; + + switch (sources) { + default: + printk(KERN_ERR "Unknown throttling event sources."); + /* fall through */ + case 0: + protection = false; + /* src is unused */ + break; + case (1 << PHM_AutoThrottleSource_Thermal): + protection = true; + src = DPM_EVENT_SRC_DIGITAL; + break; + case (1 << PHM_AutoThrottleSource_External): + protection = true; + src = DPM_EVENT_SRC_EXTERNAL; + break; + case (1 << PHM_AutoThrottleSource_External) | + (1 << PHM_AutoThrottleSource_Thermal): + protection = true; + src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL; + break; + } + /* Order matters - don't enable thermal protection for the wrong source. */ + if (protection) { + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL, + DPM_EVENT_SRC, src); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + THERMAL_PROTECTION_DIS, + !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)); + } else + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + THERMAL_PROTECTION_DIS, 1); +} + +static int tonga_enable_auto_throttle_source(struct pp_hwmgr *hwmgr, + PHM_AutoThrottleSource source) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + if (!(data->active_auto_throttle_sources & (1 << source))) { + data->active_auto_throttle_sources |= 1 << source; + tonga_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); + } + return 0; +} + +static int tonga_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) +{ + return tonga_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); +} + +static int tonga_disable_auto_throttle_source(struct pp_hwmgr *hwmgr, + PHM_AutoThrottleSource source) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + if (data->active_auto_throttle_sources & (1 << source)) { + data->active_auto_throttle_sources &= ~(1 << source); + tonga_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); + } + return 0; +} + +static int tonga_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) +{ + return tonga_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); +} int tonga_enable_dpm_tasks(struct pp_hwmgr *hwmgr) { @@ -4410,6 +4484,10 @@ int tonga_enable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((tmp_result == 0), "Failed to power control set level!", result = tmp_result); + tmp_result = tonga_enable_thermal_auto_throttle(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable thermal auto throttle!", result = tmp_result); + return result; } @@ -4421,6 +4499,10 @@ int tonga_disable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((0 == tmp_result), "SMC is still running!", return 0); + tmp_result = tonga_disable_thermal_auto_throttle(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable thermal auto throttle!", result = tmp_result); + tmp_result = tonga_stop_dpm(hwmgr); PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to stop DPM!", result = tmp_result); -- cgit v1.1 From a3fd80740a659ae1d20d090749958cc06f172b7e Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 5 Sep 2016 18:34:18 +0800 Subject: drm/amd/powerplay: fix issue power containment not enabled on Tonga. Signed-off-by: Rex Zhu Acked-by: Flora Cui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.c index 9496ade..24d9a05 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.c @@ -56,9 +56,6 @@ void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) else tonga_hwmgr->power_tune_defaults = &tonga_power_tune_data_set_array[0]; - /* Assume disabled */ - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CAC); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, -- cgit v1.1 From cb5df31b2d218a0a01952f9551f114b1bc32064c Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 6 Sep 2016 08:42:02 -0400 Subject: drm/amd/amdgpu: Tidy up SI DMA code Signed-off-by: Tom St Denis Reviewed-by: Edward O'Callaghan Reviewed-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dma.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 377f4ae..2abdaa6 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -39,16 +39,11 @@ static void si_dma_set_irq_funcs(struct amdgpu_device *adev); static uint32_t si_dma_ring_get_rptr(struct amdgpu_ring *ring) { - u32 rptr; - - rptr = ring->adev->wb.wb[ring->rptr_offs/4]; - - return rptr; + return ring->adev->wb.wb[ring->rptr_offs>>2]; } static uint32_t si_dma_ring_get_wptr(struct amdgpu_ring *ring) { - struct amdgpu_device *adev = ring->adev; u32 me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1; @@ -188,7 +183,6 @@ static int si_dma_start(struct amdgpu_device *adev) ring->wptr = 0; WREG32(DMA_RB_WPTR + sdma_offsets[i], ring->wptr << 2); - WREG32(DMA_RB_CNTL + sdma_offsets[i], rb_cntl | DMA_RB_ENABLE); ring->ready = true; @@ -476,11 +470,10 @@ static void si_dma_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { amdgpu_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); - if (vm_id < 8) { + if (vm_id < 8) amdgpu_ring_write(ring, (0xf << 16) | (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + vm_id)); - } else { + else amdgpu_ring_write(ring, (0xf << 16) | (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + (vm_id - 8))); - } amdgpu_ring_write(ring, pd_addr >> 12); /* bits 0-7 are the VM contexts0-7 */ @@ -558,14 +551,9 @@ static int si_dma_sw_fini(void *handle) static int si_dma_hw_init(void *handle) { - int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = si_dma_start(adev); - if (r) - return r; - - return r; + return si_dma_start(adev); } static int si_dma_hw_fini(void *handle) @@ -605,13 +593,10 @@ static bool si_dma_is_idle(void *handle) static int si_dma_wait_for_idle(void *handle) { unsigned i; - u32 tmp; struct amdgpu_device *adev = (struct amdgpu_device *)handle; for (i = 0; i < adev->usec_timeout; i++) { - tmp = RREG32(SRBM_STATUS2) & (DMA_BUSY_MASK | DMA1_BUSY_MASK); - - if (!tmp) + if (si_dma_is_idle(handle)) return 0; udelay(1); } @@ -674,11 +659,6 @@ static int si_dma_process_trap_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - u8 instance_id, queue_id; - - instance_id = (entry->ring_id & 0x3) >> 0; - queue_id = (entry->ring_id & 0xc) >> 2; - amdgpu_fence_process(&adev->sdma.instance[0].ring); return 0; @@ -688,11 +668,6 @@ static int si_dma_process_trap_irq_1(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - u8 instance_id, queue_id; - - instance_id = (entry->ring_id & 0x3) >> 0; - queue_id = (entry->ring_id & 0xc) >> 2; - amdgpu_fence_process(&adev->sdma.instance[1].ring); return 0; -- cgit v1.1 From 9623e4bfaa5e78727cae5c19b9ee5f94cf6bb24a Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 6 Sep 2016 09:42:55 -0400 Subject: drm/amd/amdgpu: Allow calling si_dpm_fini at any point Allow calling fini even if ps array is not allocated. Signed-off-by: Tom St Denis Reviewed-by: Edward O'Callaghan Reviewed-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index e90bb44..2a72b2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -7519,9 +7519,9 @@ static void si_dpm_fini(struct amdgpu_device *adev) { int i; - for (i = 0; i < adev->pm.dpm.num_ps; i++) { - kfree(adev->pm.dpm.ps[i].ps_priv); - } + if (adev->pm.dpm.ps) + for (i = 0; i < adev->pm.dpm.num_ps; i++) + kfree(adev->pm.dpm.ps[i].ps_priv); kfree(adev->pm.dpm.ps); kfree(adev->pm.dpm.priv); kfree(adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries); -- cgit v1.1 From c3d98645854485ca3c07b0e110ec6d61f77558fa Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 6 Sep 2016 09:44:47 -0400 Subject: drm/amd/amdgpu: Clean up SI DPM table assignments Hoist common assignments out of cases. Signed-off-by: Tom St Denis Reviewed-by: Edward O'Callaghan Reviewed-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 42 +++++++++---------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 2a72b2b..8d62391 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -2014,39 +2014,28 @@ static void si_initialize_powertune_defaults(struct amdgpu_device *adev) break; } } else if (adev->asic_type == CHIP_PITCAIRN) { + si_pi->cac_weights = cac_weights_pitcairn; + si_pi->lcac_config = lcac_pitcairn; + si_pi->cac_override = cac_override_pitcairn; + si_pi->powertune_data = &powertune_data_pitcairn; + switch (adev->pdev->device) { case 0x6810: case 0x6818: - si_pi->cac_weights = cac_weights_pitcairn; - si_pi->lcac_config = lcac_pitcairn; - si_pi->cac_override = cac_override_pitcairn; - si_pi->powertune_data = &powertune_data_pitcairn; si_pi->dte_data = dte_data_curacao_xt; update_dte_from_pl2 = true; break; case 0x6819: case 0x6811: - si_pi->cac_weights = cac_weights_pitcairn; - si_pi->lcac_config = lcac_pitcairn; - si_pi->cac_override = cac_override_pitcairn; - si_pi->powertune_data = &powertune_data_pitcairn; si_pi->dte_data = dte_data_curacao_pro; update_dte_from_pl2 = true; break; case 0x6800: case 0x6806: - si_pi->cac_weights = cac_weights_pitcairn; - si_pi->lcac_config = lcac_pitcairn; - si_pi->cac_override = cac_override_pitcairn; - si_pi->powertune_data = &powertune_data_pitcairn; si_pi->dte_data = dte_data_neptune_xt; update_dte_from_pl2 = true; break; default: - si_pi->cac_weights = cac_weights_pitcairn; - si_pi->lcac_config = lcac_pitcairn; - si_pi->cac_override = cac_override_pitcairn; - si_pi->powertune_data = &powertune_data_pitcairn; si_pi->dte_data = dte_data_pitcairn; break; } @@ -2102,16 +2091,17 @@ static void si_initialize_powertune_defaults(struct amdgpu_device *adev) break; } } else if (adev->asic_type == CHIP_OLAND) { + si_pi->lcac_config = lcac_mars_pro; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_mars_pro; + si_pi->dte_data = dte_data_mars_pro; + switch (adev->pdev->device) { case 0x6601: case 0x6621: case 0x6603: case 0x6605: si_pi->cac_weights = cac_weights_mars_pro; - si_pi->lcac_config = lcac_mars_pro; - si_pi->cac_override = cac_override_oland; - si_pi->powertune_data = &powertune_data_mars_pro; - si_pi->dte_data = dte_data_mars_pro; update_dte_from_pl2 = true; break; case 0x6600: @@ -2119,28 +2109,16 @@ static void si_initialize_powertune_defaults(struct amdgpu_device *adev) case 0x6620: case 0x6604: si_pi->cac_weights = cac_weights_mars_xt; - si_pi->lcac_config = lcac_mars_pro; - si_pi->cac_override = cac_override_oland; - si_pi->powertune_data = &powertune_data_mars_pro; - si_pi->dte_data = dte_data_mars_pro; update_dte_from_pl2 = true; break; case 0x6611: case 0x6613: case 0x6608: si_pi->cac_weights = cac_weights_oland_pro; - si_pi->lcac_config = lcac_mars_pro; - si_pi->cac_override = cac_override_oland; - si_pi->powertune_data = &powertune_data_mars_pro; - si_pi->dte_data = dte_data_mars_pro; update_dte_from_pl2 = true; break; case 0x6610: si_pi->cac_weights = cac_weights_oland_xt; - si_pi->lcac_config = lcac_mars_pro; - si_pi->cac_override = cac_override_oland; - si_pi->powertune_data = &powertune_data_mars_pro; - si_pi->dte_data = dte_data_mars_pro; update_dte_from_pl2 = true; break; default: -- cgit v1.1 From 77d318a6b9f2f8599d913b7b5013cdf0342c71ed Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 6 Sep 2016 09:45:43 -0400 Subject: drm/amd/amdgpu: Correct whitespace in SI DPM code Replace 8 spaces with tabs, correct {} braces, etc. Signed-off-by: Tom St Denis Reviewed-by: Edward O'Callaghan Reviewed-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 441 +++++++++++++++++------------------- 1 file changed, 209 insertions(+), 232 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 8d62391..8e6bbaf 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -84,11 +84,11 @@ union fan_info { }; union pplib_clock_info { - struct _ATOM_PPLIB_R600_CLOCK_INFO r600; - struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; - struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; - struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; - struct _ATOM_PPLIB_SI_CLOCK_INFO si; + struct _ATOM_PPLIB_R600_CLOCK_INFO r600; + struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; + struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; + struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; + struct _ATOM_PPLIB_SI_CLOCK_INFO si; }; const u32 r600_utc[R600_PM_NUMBER_OF_TC] = @@ -1852,8 +1852,8 @@ extern u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg); static struct si_power_info *si_get_pi(struct amdgpu_device *adev) { - struct si_power_info *pi = adev->pm.dpm.priv; - return pi; + struct si_power_info *pi = adev->pm.dpm.priv; + return pi; } static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff, @@ -1954,23 +1954,23 @@ static void si_update_dte_from_pl2(struct amdgpu_device *adev, struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev) { - struct rv7xx_power_info *pi = adev->pm.dpm.priv; + struct rv7xx_power_info *pi = adev->pm.dpm.priv; - return pi; + return pi; } struct ni_power_info *ni_get_pi(struct amdgpu_device *adev) { - struct ni_power_info *pi = adev->pm.dpm.priv; + struct ni_power_info *pi = adev->pm.dpm.priv; - return pi; + return pi; } struct si_ps *si_get_ps(struct amdgpu_ps *aps) { - struct si_ps *ps = aps->ps_priv; + struct si_ps *ps = aps->ps_priv; - return ps; + return ps; } static void si_initialize_powertune_defaults(struct amdgpu_device *adev) @@ -2147,7 +2147,7 @@ static void si_initialize_powertune_defaults(struct amdgpu_device *adev) si_pi->enable_dte = false; if (si_pi->powertune_data->enable_powertune_by_default) { - ni_pi->enable_power_containment= true; + ni_pi->enable_power_containment = true; ni_pi->enable_cac = true; if (si_pi->dte_data.enable_dte_by_default) { si_pi->enable_dte = true; @@ -2426,13 +2426,12 @@ static int si_populate_power_containment_values(struct amdgpu_device *adev, if ((max_ps_percent == 0) || (prev_sclk == max_sclk) || - disable_uvd_power_tune) { + disable_uvd_power_tune) min_sclk = max_sclk; - } else if (i == 1) { + else if (i == 1) min_sclk = prev_sclk; - } else { + else min_sclk = (prev_sclk * (u32)max_ps_percent) / 100; - } if (min_sclk < state->performance_levels[0].sclk) min_sclk = state->performance_levels[0].sclk; @@ -2632,7 +2631,6 @@ static int si_get_cac_std_voltage_max_min(struct amdgpu_device *adev, u32 i; u32 v0_loadline; - if (table == NULL) return -EINVAL; @@ -3079,14 +3077,14 @@ static int si_get_vce_clock_voltage(struct amdgpu_device *adev, static bool si_dpm_vblank_too_short(struct amdgpu_device *adev) { - u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); - /* we never hit the non-gddr5 limit so disable it */ - u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0; + u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); + /* we never hit the non-gddr5 limit so disable it */ + u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0; - if (vblank_time < switch_limit) - return true; - else - return false; + if (vblank_time < switch_limit) + return true; + else + return false; } @@ -3099,47 +3097,47 @@ static int ni_copy_and_switch_arb_sets(struct amdgpu_device *adev, u32 mc_cg_config; switch (arb_freq_src) { - case MC_CG_ARB_FREQ_F0: + case MC_CG_ARB_FREQ_F0: mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING); mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT; break; - case MC_CG_ARB_FREQ_F1: + case MC_CG_ARB_FREQ_F1: mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_1); mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1); burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT; break; - case MC_CG_ARB_FREQ_F2: + case MC_CG_ARB_FREQ_F2: mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_2); mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2); burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT; break; - case MC_CG_ARB_FREQ_F3: + case MC_CG_ARB_FREQ_F3: mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_3); mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3); burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT; break; - default: + default: return -EINVAL; } switch (arb_freq_dest) { - case MC_CG_ARB_FREQ_F0: + case MC_CG_ARB_FREQ_F0: WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing); WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK); break; - case MC_CG_ARB_FREQ_F1: + case MC_CG_ARB_FREQ_F1: WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK); break; - case MC_CG_ARB_FREQ_F2: + case MC_CG_ARB_FREQ_F2: WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing); WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2); WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK); break; - case MC_CG_ARB_FREQ_F3: + case MC_CG_ARB_FREQ_F3: WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing); WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2); WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK); @@ -3158,9 +3156,9 @@ static int ni_copy_and_switch_arb_sets(struct amdgpu_device *adev, static void ni_update_current_ps(struct amdgpu_device *adev, struct amdgpu_ps *rps) { - struct si_ps *new_ps = si_get_ps(rps); + struct si_ps *new_ps = si_get_ps(rps); struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct ni_power_info *ni_pi = ni_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); eg_pi->current_rps = *rps; ni_pi->current_ps = *new_ps; @@ -3170,9 +3168,9 @@ static void ni_update_current_ps(struct amdgpu_device *adev, static void ni_update_requested_ps(struct amdgpu_device *adev, struct amdgpu_ps *rps) { - struct si_ps *new_ps = si_get_ps(rps); + struct si_ps *new_ps = si_get_ps(rps); struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct ni_power_info *ni_pi = ni_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); eg_pi->requested_rps = *rps; ni_pi->requested_ps = *new_ps; @@ -3183,8 +3181,8 @@ static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev, struct amdgpu_ps *new_ps, struct amdgpu_ps *old_ps) { - struct si_ps *new_state = si_get_ps(new_ps); - struct si_ps *current_state = si_get_ps(old_ps); + struct si_ps *new_state = si_get_ps(new_ps); + struct si_ps *current_state = si_get_ps(old_ps); if ((new_ps->vclk == old_ps->vclk) && (new_ps->dclk == old_ps->dclk)) @@ -3201,8 +3199,8 @@ static void ni_set_uvd_clock_after_set_eng_clock(struct amdgpu_device *adev, struct amdgpu_ps *new_ps, struct amdgpu_ps *old_ps) { - struct si_ps *new_state = si_get_ps(new_ps); - struct si_ps *current_state = si_get_ps(old_ps); + struct si_ps *new_state = si_get_ps(new_ps); + struct si_ps *current_state = si_get_ps(old_ps); if ((new_ps->vclk == old_ps->vclk) && (new_ps->dclk == old_ps->dclk)) @@ -3217,134 +3215,133 @@ static void ni_set_uvd_clock_after_set_eng_clock(struct amdgpu_device *adev, static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage) { - unsigned int i; + unsigned int i; - for (i = 0; i < table->count; i++) { - if (voltage <= table->entries[i].value) - return table->entries[i].value; - } + for (i = 0; i < table->count; i++) + if (voltage <= table->entries[i].value) + return table->entries[i].value; - return table->entries[table->count - 1].value; + return table->entries[table->count - 1].value; } static u32 btc_find_valid_clock(struct amdgpu_clock_array *clocks, - u32 max_clock, u32 requested_clock) + u32 max_clock, u32 requested_clock) { - unsigned int i; + unsigned int i; - if ((clocks == NULL) || (clocks->count == 0)) - return (requested_clock < max_clock) ? requested_clock : max_clock; + if ((clocks == NULL) || (clocks->count == 0)) + return (requested_clock < max_clock) ? requested_clock : max_clock; - for (i = 0; i < clocks->count; i++) { - if (clocks->values[i] >= requested_clock) - return (clocks->values[i] < max_clock) ? clocks->values[i] : max_clock; - } + for (i = 0; i < clocks->count; i++) { + if (clocks->values[i] >= requested_clock) + return (clocks->values[i] < max_clock) ? clocks->values[i] : max_clock; + } - return (clocks->values[clocks->count - 1] < max_clock) ? - clocks->values[clocks->count - 1] : max_clock; + return (clocks->values[clocks->count - 1] < max_clock) ? + clocks->values[clocks->count - 1] : max_clock; } static u32 btc_get_valid_mclk(struct amdgpu_device *adev, - u32 max_mclk, u32 requested_mclk) + u32 max_mclk, u32 requested_mclk) { - return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_mclk_values, - max_mclk, requested_mclk); + return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_mclk_values, + max_mclk, requested_mclk); } static u32 btc_get_valid_sclk(struct amdgpu_device *adev, - u32 max_sclk, u32 requested_sclk) + u32 max_sclk, u32 requested_sclk) { - return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_sclk_values, - max_sclk, requested_sclk); + return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_sclk_values, + max_sclk, requested_sclk); } void btc_get_max_clock_from_voltage_dependency_table(struct amdgpu_clock_voltage_dependency_table *table, - u32 *max_clock) + u32 *max_clock) { - u32 i, clock = 0; + u32 i, clock = 0; - if ((table == NULL) || (table->count == 0)) { - *max_clock = clock; - return; - } + if ((table == NULL) || (table->count == 0)) { + *max_clock = clock; + return; + } - for (i = 0; i < table->count; i++) { - if (clock < table->entries[i].clk) - clock = table->entries[i].clk; - } - *max_clock = clock; + for (i = 0; i < table->count; i++) { + if (clock < table->entries[i].clk) + clock = table->entries[i].clk; + } + *max_clock = clock; } static void btc_apply_voltage_dependency_rules(struct amdgpu_clock_voltage_dependency_table *table, - u32 clock, u16 max_voltage, u16 *voltage) + u32 clock, u16 max_voltage, u16 *voltage) { - u32 i; + u32 i; - if ((table == NULL) || (table->count == 0)) - return; + if ((table == NULL) || (table->count == 0)) + return; - for (i= 0; i < table->count; i++) { - if (clock <= table->entries[i].clk) { - if (*voltage < table->entries[i].v) - *voltage = (u16)((table->entries[i].v < max_voltage) ? - table->entries[i].v : max_voltage); - return; - } - } + for (i= 0; i < table->count; i++) { + if (clock <= table->entries[i].clk) { + if (*voltage < table->entries[i].v) + *voltage = (u16)((table->entries[i].v < max_voltage) ? + table->entries[i].v : max_voltage); + return; + } + } - *voltage = (*voltage > max_voltage) ? *voltage : max_voltage; + *voltage = (*voltage > max_voltage) ? *voltage : max_voltage; } static void btc_adjust_clock_combinations(struct amdgpu_device *adev, - const struct amdgpu_clock_and_voltage_limits *max_limits, - struct rv7xx_pl *pl) + const struct amdgpu_clock_and_voltage_limits *max_limits, + struct rv7xx_pl *pl) { - if ((pl->mclk == 0) || (pl->sclk == 0)) - return; + if ((pl->mclk == 0) || (pl->sclk == 0)) + return; - if (pl->mclk == pl->sclk) - return; + if (pl->mclk == pl->sclk) + return; - if (pl->mclk > pl->sclk) { - if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > adev->pm.dpm.dyn_state.mclk_sclk_ratio) - pl->sclk = btc_get_valid_sclk(adev, - max_limits->sclk, - (pl->mclk + - (adev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) / - adev->pm.dpm.dyn_state.mclk_sclk_ratio); - } else { - if ((pl->sclk - pl->mclk) > adev->pm.dpm.dyn_state.sclk_mclk_delta) - pl->mclk = btc_get_valid_mclk(adev, - max_limits->mclk, - pl->sclk - - adev->pm.dpm.dyn_state.sclk_mclk_delta); - } + if (pl->mclk > pl->sclk) { + if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > adev->pm.dpm.dyn_state.mclk_sclk_ratio) + pl->sclk = btc_get_valid_sclk(adev, + max_limits->sclk, + (pl->mclk + + (adev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) / + adev->pm.dpm.dyn_state.mclk_sclk_ratio); + } else { + if ((pl->sclk - pl->mclk) > adev->pm.dpm.dyn_state.sclk_mclk_delta) + pl->mclk = btc_get_valid_mclk(adev, + max_limits->mclk, + pl->sclk - + adev->pm.dpm.dyn_state.sclk_mclk_delta); + } } static void btc_apply_voltage_delta_rules(struct amdgpu_device *adev, - u16 max_vddc, u16 max_vddci, - u16 *vddc, u16 *vddci) -{ - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - u16 new_voltage; - - if ((0 == *vddc) || (0 == *vddci)) - return; - - if (*vddc > *vddci) { - if ((*vddc - *vddci) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { - new_voltage = btc_find_voltage(&eg_pi->vddci_voltage_table, - (*vddc - adev->pm.dpm.dyn_state.vddc_vddci_delta)); - *vddci = (new_voltage < max_vddci) ? new_voltage : max_vddci; - } - } else { - if ((*vddci - *vddc) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { - new_voltage = btc_find_voltage(&eg_pi->vddc_voltage_table, - (*vddci - adev->pm.dpm.dyn_state.vddc_vddci_delta)); - *vddc = (new_voltage < max_vddc) ? new_voltage : max_vddc; - } - } + u16 max_vddc, u16 max_vddci, + u16 *vddc, u16 *vddci) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + u16 new_voltage; + + if ((0 == *vddc) || (0 == *vddci)) + return; + + if (*vddc > *vddci) { + if ((*vddc - *vddci) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { + new_voltage = btc_find_voltage(&eg_pi->vddci_voltage_table, + (*vddc - adev->pm.dpm.dyn_state.vddc_vddci_delta)); + *vddci = (new_voltage < max_vddci) ? new_voltage : max_vddci; + } + } else { + if ((*vddci - *vddc) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { + new_voltage = btc_find_voltage(&eg_pi->vddc_voltage_table, + (*vddci - adev->pm.dpm.dyn_state.vddc_vddci_delta)); + *vddc = (new_voltage < max_vddc) ? new_voltage : max_vddc; + } + } } static enum amdgpu_pcie_gen r600_get_pcie_gen_support(struct amdgpu_device *adev, @@ -3626,9 +3623,9 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev, } } - for (i = 0; i < ps->performance_level_count; i++) - btc_adjust_clock_combinations(adev, max_limits, - &ps->performance_levels[i]); + for (i = 0; i < ps->performance_level_count; i++) + btc_adjust_clock_combinations(adev, max_limits, + &ps->performance_levels[i]); for (i = 0; i < ps->performance_level_count; i++) { if (ps->performance_levels[i].vddc < min_vce_voltage) @@ -3767,7 +3764,7 @@ static void si_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources) case 0: default: want_thermal_protection = false; - break; + break; case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL): want_thermal_protection = true; dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGITAL; @@ -3969,7 +3966,7 @@ static int si_process_firmware_header(struct amdgpu_device *adev) if (ret) return ret; - si_pi->state_table_start = tmp; + si_pi->state_table_start = tmp; ret = si_read_smc_sram_dword(adev, SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + @@ -4128,7 +4125,7 @@ static void si_program_response_times(struct amdgpu_device *adev) si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mvdd_chg_time, 1); voltage_response_time = (u32)adev->pm.dpm.voltage_response_time; - backbias_response_time = (u32)adev->pm.dpm.backbias_response_time; + backbias_response_time = (u32)adev->pm.dpm.backbias_response_time; if (voltage_response_time == 0) voltage_response_time = 1000; @@ -4367,14 +4364,11 @@ static u8 si_get_strobe_mode_settings(struct amdgpu_device *adev, u32 mclk) static int si_upload_firmware(struct amdgpu_device *adev) { struct si_power_info *si_pi = si_get_pi(adev); - int ret; si_reset_smc(adev); si_stop_smc_clock(adev); - ret = si_load_smc_ucode(adev, si_pi->sram_end); - - return ret; + return si_load_smc_ucode(adev, si_pi->sram_end); } static bool si_validate_phase_shedding_tables(struct amdgpu_device *adev, @@ -4790,7 +4784,7 @@ static int si_populate_memory_timing_parameters(struct amdgpu_device *adev, amdgpu_atombios_set_engine_dram_timings(adev, pl->sclk, - pl->mclk); + pl->mclk); dram_timing = RREG32(MC_ARB_DRAM_TIMING); dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); @@ -4825,7 +4819,7 @@ static int si_do_program_memory_timing_parameters(struct amdgpu_device *adev, si_pi->sram_end); if (ret) break; - } + } return ret; } @@ -4938,9 +4932,7 @@ static int si_populate_smc_initial_state(struct amdgpu_device *adev, reg = CG_R(0xffff) | CG_L(0); table->initialState.levels[0].aT = cpu_to_be32(reg); - table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp); - table->initialState.levels[0].gen2PCIE = (u8)si_pi->boot_pcie_gen; if (adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { @@ -5302,9 +5294,9 @@ static int si_calculate_sclk_params(struct amdgpu_device *adev, spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; spll_func_cntl_2 |= SCLK_MUX_SEL(2); - spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; - spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); - spll_func_cntl_3 |= SPLL_DITHEN; + spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; + spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); + spll_func_cntl_3 |= SPLL_DITHEN; if (pi->sclk_ss) { struct amdgpu_atom_ss ss; @@ -5411,15 +5403,15 @@ static int si_populate_mclk_value(struct amdgpu_device *adev, tmp = freq_nom / reference_clock; tmp = tmp * tmp; if (amdgpu_atombios_get_asic_ss_info(adev, &ss, - ASIC_INTERNAL_MEMORY_SS, freq_nom)) { + ASIC_INTERNAL_MEMORY_SS, freq_nom)) { u32 clks = reference_clock * 5 / ss.rate; u32 clkv = (u32)((((131 * ss.percentage * ss.rate) / 100) * tmp) / freq_nom); - mpll_ss1 &= ~CLKV_MASK; - mpll_ss1 |= CLKV(clkv); + mpll_ss1 &= ~CLKV_MASK; + mpll_ss1 |= CLKV(clkv); - mpll_ss2 &= ~CLKS_MASK; - mpll_ss2 |= CLKS(clks); + mpll_ss2 &= ~CLKS_MASK; + mpll_ss2 |= CLKS(clks); } } @@ -5746,7 +5738,7 @@ static int si_convert_power_state_to_smc(struct amdgpu_device *adev, ni_pi->enable_power_containment = false; ret = si_populate_sq_ramping_values(adev, amdgpu_state, smc_state); - if (ret) + if (ret) ni_pi->enable_sq_ramping = false; return si_populate_smc_t(adev, amdgpu_state, smc_state); @@ -5771,10 +5763,8 @@ static int si_upload_sw_state(struct amdgpu_device *adev, if (ret) return ret; - ret = si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, - state_size, si_pi->sram_end); - - return ret; + return si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, + state_size, si_pi->sram_end); } static int si_upload_ulv_state(struct amdgpu_device *adev) @@ -5915,46 +5905,46 @@ static bool si_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg) case MC_SEQ_RAS_TIMING: *out_reg = MC_SEQ_RAS_TIMING_LP; break; - case MC_SEQ_CAS_TIMING: + case MC_SEQ_CAS_TIMING: *out_reg = MC_SEQ_CAS_TIMING_LP; break; - case MC_SEQ_MISC_TIMING: + case MC_SEQ_MISC_TIMING: *out_reg = MC_SEQ_MISC_TIMING_LP; break; - case MC_SEQ_MISC_TIMING2: + case MC_SEQ_MISC_TIMING2: *out_reg = MC_SEQ_MISC_TIMING2_LP; break; - case MC_SEQ_RD_CTL_D0: + case MC_SEQ_RD_CTL_D0: *out_reg = MC_SEQ_RD_CTL_D0_LP; break; - case MC_SEQ_RD_CTL_D1: + case MC_SEQ_RD_CTL_D1: *out_reg = MC_SEQ_RD_CTL_D1_LP; break; - case MC_SEQ_WR_CTL_D0: + case MC_SEQ_WR_CTL_D0: *out_reg = MC_SEQ_WR_CTL_D0_LP; break; - case MC_SEQ_WR_CTL_D1: + case MC_SEQ_WR_CTL_D1: *out_reg = MC_SEQ_WR_CTL_D1_LP; break; - case MC_PMG_CMD_EMRS: + case MC_PMG_CMD_EMRS: *out_reg = MC_SEQ_PMG_CMD_EMRS_LP; break; - case MC_PMG_CMD_MRS: + case MC_PMG_CMD_MRS: *out_reg = MC_SEQ_PMG_CMD_MRS_LP; break; - case MC_PMG_CMD_MRS1: + case MC_PMG_CMD_MRS1: *out_reg = MC_SEQ_PMG_CMD_MRS1_LP; break; - case MC_SEQ_PMG_TIMING: + case MC_SEQ_PMG_TIMING: *out_reg = MC_SEQ_PMG_TIMING_LP; break; - case MC_PMG_CMD_MRS2: + case MC_PMG_CMD_MRS2: *out_reg = MC_SEQ_PMG_CMD_MRS2_LP; break; - case MC_SEQ_WR_CTL_2: + case MC_SEQ_WR_CTL_2: *out_reg = MC_SEQ_WR_CTL_2_LP; break; - default: + default: result = false; break; } @@ -6041,19 +6031,19 @@ static int si_initialize_mc_reg_table(struct amdgpu_device *adev) WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2)); WREG32(MC_SEQ_WR_CTL_2_LP, RREG32(MC_SEQ_WR_CTL_2)); - ret = amdgpu_atombios_init_mc_reg_table(adev, module_index, table); - if (ret) - goto init_mc_done; + ret = amdgpu_atombios_init_mc_reg_table(adev, module_index, table); + if (ret) + goto init_mc_done; - ret = si_copy_vbios_mc_reg_table(table, si_table); - if (ret) - goto init_mc_done; + ret = si_copy_vbios_mc_reg_table(table, si_table); + if (ret) + goto init_mc_done; si_set_s0_mc_reg_index(si_table); ret = si_set_mc_special_registers(adev, si_table); - if (ret) - goto init_mc_done; + if (ret) + goto init_mc_done; si_set_valid_flag(si_table); @@ -6122,7 +6112,7 @@ static void si_convert_mc_reg_table_to_smc(struct amdgpu_device *adev, struct amdgpu_ps *amdgpu_state, SMC_SIslands_MCRegisters *mc_reg_table) { - struct si_ps *state = si_get_ps(amdgpu_state); + struct si_ps *state = si_get_ps(amdgpu_state); int i; for (i = 0; i < state->performance_level_count; i++) { @@ -6173,7 +6163,7 @@ static int si_populate_mc_reg_table(struct amdgpu_device *adev, static int si_upload_mc_reg_table(struct amdgpu_device *adev, struct amdgpu_ps *amdgpu_new_state) { - struct si_ps *new_state = si_get_ps(amdgpu_new_state); + struct si_ps *new_state = si_get_ps(amdgpu_new_state); struct si_power_info *si_pi = si_get_pi(adev); u32 address = si_pi->mc_reg_table_start + offsetof(SMC_SIslands_MCRegisters, @@ -6184,26 +6174,24 @@ static int si_upload_mc_reg_table(struct amdgpu_device *adev, si_convert_mc_reg_table_to_smc(adev, amdgpu_new_state, smc_mc_reg_table); - return si_copy_bytes_to_smc(adev, address, (u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT], sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count, si_pi->sram_end); - } static void si_enable_voltage_control(struct amdgpu_device *adev, bool enable) { - if (enable) - WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN); - else - WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN); + if (enable) + WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN); + else + WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN); } static enum amdgpu_pcie_gen si_get_maximum_link_speed(struct amdgpu_device *adev, struct amdgpu_ps *amdgpu_state) { - struct si_ps *state = si_get_ps(amdgpu_state); + struct si_ps *state = si_get_ps(amdgpu_state); int i; u16 pcie_speed, max_speed = 0; @@ -6525,25 +6513,17 @@ static int si_thermal_setup_fan_table(struct amdgpu_device *adev) fan_table.temp_min = cpu_to_be16((50 + adev->pm.dpm.fan.t_min) / 100); fan_table.temp_med = cpu_to_be16((50 + adev->pm.dpm.fan.t_med) / 100); fan_table.temp_max = cpu_to_be16((50 + adev->pm.dpm.fan.t_max) / 100); - fan_table.slope1 = cpu_to_be16(slope1); fan_table.slope2 = cpu_to_be16(slope2); - fan_table.fdo_min = cpu_to_be16(fdo_min); - fan_table.hys_down = cpu_to_be16(adev->pm.dpm.fan.t_hyst); - fan_table.hys_up = cpu_to_be16(1); - fan_table.hys_slope = cpu_to_be16(1); - fan_table.temp_resp_lim = cpu_to_be16(5); - reference_clock = amdgpu_asic_get_xclk(adev); fan_table.refresh_period = cpu_to_be32((adev->pm.dpm.fan.cycle_delay * reference_clock) / 1600); - fan_table.fdo_max = cpu_to_be16((u16)duty100); tmp = (RREG32(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT; @@ -6916,9 +6896,7 @@ static int si_dpm_enable(struct amdgpu_device *adev) si_start_dpm(adev); si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true); - si_thermal_start_thermal_controller(adev); - ni_update_current_ps(adev, boot_ps); return 0; @@ -6972,7 +6950,6 @@ static int si_dpm_pre_set_power_state(struct amdgpu_device *adev) struct amdgpu_ps *new_ps = &requested_ps; ni_update_requested_ps(adev, new_ps); - si_apply_state_adjust_rules(adev, &eg_pi->requested_rps); return 0; @@ -7232,8 +7209,8 @@ static void si_parse_pplib_clock_info(struct amdgpu_device *adev, } union pplib_power_state { - struct _ATOM_PPLIB_STATE v1; - struct _ATOM_PPLIB_STATE_V2 v2; + struct _ATOM_PPLIB_STATE v1; + struct _ATOM_PPLIB_STATE_V2 v2; }; static int si_parse_power_table(struct amdgpu_device *adev) @@ -7248,7 +7225,7 @@ static int si_parse_power_table(struct amdgpu_device *adev) struct _NonClockInfoArray *non_clock_info_array; union power_info *power_info; int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; + u16 data_offset; u8 frev, crev; u8 *power_state_offset; struct si_ps *ps; @@ -7896,46 +7873,46 @@ static int si_dpm_get_temp(struct amdgpu_device *adev) static u32 si_dpm_get_sclk(struct amdgpu_device *adev, bool low) { - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); - if (low) - return requested_state->performance_levels[0].sclk; - else - return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk; + if (low) + return requested_state->performance_levels[0].sclk; + else + return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk; } static u32 si_dpm_get_mclk(struct amdgpu_device *adev, bool low) { - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); - if (low) - return requested_state->performance_levels[0].mclk; - else - return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk; + if (low) + return requested_state->performance_levels[0].mclk; + else + return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk; } static void si_dpm_print_power_state(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - struct si_ps *ps = si_get_ps(rps); - struct rv7xx_pl *pl; - int i; - - amdgpu_dpm_print_class_info(rps->class, rps->class2); - amdgpu_dpm_print_cap_info(rps->caps); - DRM_INFO("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); - for (i = 0; i < ps->performance_level_count; i++) { - pl = &ps->performance_levels[i]; - if (adev->asic_type >= CHIP_TAHITI) - DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", + struct amdgpu_ps *rps) +{ + struct si_ps *ps = si_get_ps(rps); + struct rv7xx_pl *pl; + int i; + + amdgpu_dpm_print_class_info(rps->class, rps->class2); + amdgpu_dpm_print_cap_info(rps->caps); + DRM_INFO("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + for (i = 0; i < ps->performance_level_count; i++) { + pl = &ps->performance_levels[i]; + if (adev->asic_type >= CHIP_TAHITI) + DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); - else - DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u\n", + else + DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u\n", i, pl->sclk, pl->mclk, pl->vddc, pl->vddci); - } - amdgpu_dpm_print_ps_status(adev, rps); + } + amdgpu_dpm_print_ps_status(adev, rps); } static int si_dpm_early_init(void *handle) -- cgit v1.1 From 6e9057a8f90f3a9d662d8c0a347850e1fa331a30 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 6 Sep 2016 11:36:42 -0400 Subject: drm/amd/amdgpu: Tidy up SI IH code Signed-off-by: Tom St Denis Reviewed-by: Edward O'Callaghan Reviewed-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_ih.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c index 994ff02..8fae3d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c @@ -57,7 +57,6 @@ static void si_ih_disable_interrupts(struct amdgpu_device *adev) static int si_ih_irq_init(struct amdgpu_device *adev) { - int ret = 0; int rb_bufsz; u32 interrupt_cntl, ih_cntl, ih_rb_cntl; u64 wptr_off; @@ -72,18 +71,15 @@ static int si_ih_irq_init(struct amdgpu_device *adev) WREG32(IH_RB_BASE, adev->irq.ih.gpu_addr >> 8); rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4); - ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | - IH_WPTR_OVERFLOW_CLEAR | - (rb_bufsz << 1)); - - ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; + ih_rb_cntl = IH_WPTR_OVERFLOW_ENABLE | + IH_WPTR_OVERFLOW_CLEAR | + (rb_bufsz << 1) | + IH_WPTR_WRITEBACK_ENABLE; wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4); WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); - WREG32(IH_RB_CNTL, ih_rb_cntl); - WREG32(IH_RB_RPTR, 0); WREG32(IH_RB_WPTR, 0); @@ -93,10 +89,9 @@ static int si_ih_irq_init(struct amdgpu_device *adev) WREG32(IH_CNTL, ih_cntl); pci_set_master(adev->pdev); - si_ih_enable_interrupts(adev); - return ret; + return 0; } static void si_ih_irq_disable(struct amdgpu_device *adev) @@ -165,9 +160,7 @@ static int si_ih_sw_init(void *handle) if (r) return r; - r = amdgpu_irq_init(adev); - - return r; + return amdgpu_irq_init(adev); } static int si_ih_sw_fini(void *handle) @@ -182,14 +175,9 @@ static int si_ih_sw_fini(void *handle) static int si_ih_hw_init(void *handle) { - int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = si_ih_irq_init(adev); - if (r) - return r; - - return 0; + return si_ih_irq_init(adev); } static int si_ih_hw_fini(void *handle) @@ -229,12 +217,10 @@ static bool si_ih_is_idle(void *handle) static int si_ih_wait_for_idle(void *handle) { unsigned i; - u32 tmp; struct amdgpu_device *adev = (struct amdgpu_device *)handle; for (i = 0; i < adev->usec_timeout; i++) { - tmp = RREG32(SRBM_STATUS) & SRBM_STATUS__IH_BUSY_MASK; - if (!tmp) + if (si_ih_is_idle(handle)) return 0; udelay(1); } -- cgit v1.1 From f80c738c614e4410c3c343141c0edabfea421862 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 6 Sep 2016 11:56:42 -0400 Subject: drm/amd/amdgpu: Tidy up SI SMC code (v2) As well as merge SMC clock functions into one to reduce LOC. v2: Fix swapped ck enable bit bug: https://bugs.freedesktop.org/show_bug.cgi?id=97801 Signed-off-by: Tom St Denis Reviewed-by: Edward O'Callaghan Reviewed-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/si_smc.c | 25 ++++++++----------------- drivers/gpu/drm/amd/amdgpu/sislands_smc.h | 3 +-- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 8e6bbaf..7b9debe 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -3944,13 +3944,13 @@ static void si_dpm_start_smc(struct amdgpu_device *adev) { si_program_jump_on_start(adev); si_start_smc(adev); - si_start_smc_clock(adev); + si_smc_clock(adev, true); } static void si_dpm_stop_smc(struct amdgpu_device *adev) { si_reset_smc(adev); - si_stop_smc_clock(adev); + si_smc_clock(adev, false); } static int si_process_firmware_header(struct amdgpu_device *adev) @@ -4366,7 +4366,7 @@ static int si_upload_firmware(struct amdgpu_device *adev) struct si_power_info *si_pi = si_get_pi(adev); si_reset_smc(adev); - si_stop_smc_clock(adev); + si_smc_clock(adev, false); return si_load_smc_ucode(adev, si_pi->sram_end); } diff --git a/drivers/gpu/drm/amd/amdgpu/si_smc.c b/drivers/gpu/drm/amd/amdgpu/si_smc.c index c1c2594..47bbb40 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/si_smc.c @@ -84,7 +84,6 @@ int si_copy_bytes_to_smc(struct amdgpu_device *adev, goto done; original_data = RREG32(SMC_IND_DATA_0); - extra_shift = 8 * (4 - byte_count); while (byte_count > 0) { @@ -94,7 +93,6 @@ int si_copy_bytes_to_smc(struct amdgpu_device *adev, } data <<= extra_shift; - data |= (original_data & ~((~0UL) << extra_shift)); ret = si_set_smc_sram_address(adev, addr, limit); @@ -128,8 +126,8 @@ void si_reset_smc(struct amdgpu_device *adev) RREG32(CB_CGTT_SCLK_CTRL); RREG32(CB_CGTT_SCLK_CTRL); - tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); - tmp |= RST_REG; + tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL) | + RST_REG; WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); } @@ -140,20 +138,14 @@ int si_program_jump_on_start(struct amdgpu_device *adev) return si_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1); } -void si_stop_smc_clock(struct amdgpu_device *adev) -{ - u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); - - tmp |= CK_DISABLE; - - WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); -} - -void si_start_smc_clock(struct amdgpu_device *adev) +void si_smc_clock(struct amdgpu_device *adev, bool enable) { u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); - tmp &= ~CK_DISABLE; + if (enable) + tmp &= ~CK_DISABLE; + else + tmp |= CK_DISABLE; WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); } @@ -185,9 +177,8 @@ PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg) break; udelay(1); } - tmp = RREG32(SMC_RESP_0); - return (PPSMC_Result)tmp; + return (PPSMC_Result)RREG32(SMC_RESP_0); } PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h index 542ab46..c5b3377 100644 --- a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h +++ b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h @@ -408,8 +408,7 @@ int si_copy_bytes_to_smc(struct amdgpu_device *adev, void si_start_smc(struct amdgpu_device *adev); void si_reset_smc(struct amdgpu_device *adev); int si_program_jump_on_start(struct amdgpu_device *adev); -void si_stop_smc_clock(struct amdgpu_device *adev); -void si_start_smc_clock(struct amdgpu_device *adev); +void si_smc_clock(struct amdgpu_device *adev, bool enable); bool si_is_smc_running(struct amdgpu_device *adev); PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg); PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev); -- cgit v1.1 From e5c5304f138726ee5c8aeda2c7bcbcbc52da102a Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 6 Sep 2016 12:07:21 -0400 Subject: drm/amd/amdgpu: Comment out currently unused SI DPM struct The tahiti_le structure is not currently used. Comment it out to avoid warnings. Signed-off-by: Tom St Denis Acked-by: Edward O'Callaghan Reviewed-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 7b9debe..92a0417 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -340,6 +340,7 @@ static const struct si_dte_data dte_data_tahiti = false }; +#if 0 static const struct si_dte_data dte_data_tahiti_le = { { 0x1E8480, 0x7A1200, 0x2160EC0, 0x3938700, 0 }, @@ -357,6 +358,7 @@ static const struct si_dte_data dte_data_tahiti_le = 85, true }; +#endif static const struct si_dte_data dte_data_tahiti_pro = { -- cgit v1.1 From 075719c3cb79f309fc775a7f8f49d91a0351ceb3 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 6 Sep 2016 13:09:26 -0400 Subject: drm/amd/amdgpu: Convert messages in gmc v6 to dev_*() Make the kernel log messaging more consistent and use the dev_*() functions instead of a mix of DRM_*() and printk(). Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 1d2952b..b13c8aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -126,7 +126,7 @@ static int gmc_v6_0_init_microcode(struct amdgpu_device *adev) out: if (err) { - printk(KERN_ERR + dev_err(adev->dev, "si_mc: Failed to load firmware \"%s\"\n", fw_name); release_firmware(adev->mc.fw); @@ -452,7 +452,7 @@ static int gmc_v6_0_gart_enable(struct amdgpu_device *adev) WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); gmc_v6_0_gart_flush_gpu_tlb(adev, 0); - DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + dev_info(adev->dev, "PCIE GART of %uM enabled (table at 0x%016llX).\n", (unsigned)(adev->mc.gtt_size >> 20), (unsigned long long)adev->gart.table_addr); adev->gart.ready = true; @@ -464,7 +464,7 @@ static int gmc_v6_0_gart_init(struct amdgpu_device *adev) int r; if (adev->gart.robj) { - WARN(1, "gmc_v6_0 PCIE GART already initialized\n"); + dev_warn(adev->dev, "gmc_v6_0 PCIE GART already initialized\n"); return 0; } r = amdgpu_gart_init(adev); @@ -549,7 +549,7 @@ static void gmc_v6_0_vm_decode_fault(struct amdgpu_device *adev, mc_id = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS, xxMEMORY_CLIENT_ID); - printk("VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n", + dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n", protections, vmid, addr, REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS, xxMEMORY_CLIENT_RW) ? @@ -752,17 +752,17 @@ static int gmc_v6_0_sw_init(void *handle) if (r) { adev->need_dma32 = true; dma_bits = 32; - printk(KERN_WARNING "amdgpu: No suitable DMA available.\n"); + dev_warn(adev->dev, "amdgpu: No suitable DMA available.\n"); } r = pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits)); if (r) { pci_set_consistent_dma_mask(adev->pdev, DMA_BIT_MASK(32)); - printk(KERN_WARNING "amdgpu: No coherent DMA available.\n"); + dev_warn(adev->dev, "amdgpu: No coherent DMA available.\n"); } r = gmc_v6_0_init_microcode(adev); if (r) { - DRM_ERROR("Failed to load mc firmware!\n"); + dev_err(adev->dev, "Failed to load mc firmware!\n"); return r; } @@ -820,7 +820,7 @@ static int gmc_v6_0_hw_init(void *handle) if (!(adev->flags & AMD_IS_APU)) { r = gmc_v6_0_mc_load_microcode(adev); if (r) { - DRM_ERROR("Failed to load MC firmware!\n"); + dev_err(adev->dev, "Failed to load MC firmware!\n"); return r; } } -- cgit v1.1 From f166d9f297684faa153dabc2b8887f61bbe7858c Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Wed, 7 Sep 2016 08:03:28 -0400 Subject: drm/amd/amdgpu: Remove double lock from gfx v6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function gfx_v6_0_get_cu_info() was taking the grbm_idx_mutex which was then taken by a dependent function gfx_v6_0_get_cu_active_bitmap(). This patch removes the select from the parent function to avoid the double lock. Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index a6b7617..a1484b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -3193,13 +3193,11 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev) memset(cu_info, 0, sizeof(*cu_info)); - mutex_lock(&adev->grbm_idx_mutex); for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { mask = 1; ao_bitmap = 0; counter = 0; - gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff); bitmap = gfx_v6_0_get_cu_active_bitmap(adev, i, j); cu_info->bitmap[i][j] = bitmap; @@ -3215,8 +3213,6 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev) ao_cu_mask |= (ao_bitmap << (i * 16 + j * 8)); } } - gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); - mutex_unlock(&adev->grbm_idx_mutex); cu_info->number = active_cu_number; cu_info->ao_cu_mask = ao_cu_mask; -- cgit v1.1 From fd5065584d5f3532d9ffb6e3832e8064f9242c7e Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 12 Sep 2016 10:16:21 +0800 Subject: drm/amdgpu: move some release handles into fail labels (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up the codes to move the release handles into fail labels. v2: squash in Christian's regression fix Signed-off-by: Huang Rui Reviewed-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 5cc95f1..7a05f79 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -247,35 +247,28 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) const struct common_firmware_header *header = NULL; err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true, - AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, bo); + AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, bo); if (err) { dev_err(adev->dev, "(%d) Firmware buffer allocate failed\n", err); - err = -ENOMEM; goto failed; } err = amdgpu_bo_reserve(*bo, false); if (err) { - amdgpu_bo_unref(bo); dev_err(adev->dev, "(%d) Firmware buffer reserve failed\n", err); - goto failed; + goto failed_reserve; } err = amdgpu_bo_pin(*bo, AMDGPU_GEM_DOMAIN_GTT, &fw_mc_addr); if (err) { - amdgpu_bo_unreserve(*bo); - amdgpu_bo_unref(bo); dev_err(adev->dev, "(%d) Firmware buffer pin failed\n", err); - goto failed; + goto failed_pin; } err = amdgpu_bo_kmap(*bo, &fw_buf_ptr); if (err) { dev_err(adev->dev, "(%d) Firmware buffer kmap failed\n", err); - amdgpu_bo_unpin(*bo); - amdgpu_bo_unreserve(*bo); - amdgpu_bo_unref(bo); - goto failed; + goto failed_kmap; } amdgpu_bo_unreserve(*bo); @@ -290,10 +283,16 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) fw_offset += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE); } } + return 0; +failed_kmap: + amdgpu_bo_unpin(*bo); +failed_pin: + amdgpu_bo_unreserve(*bo); +failed_reserve: + amdgpu_bo_unref(bo); failed: - if (err) - adev->firmware.smu_load = false; + adev->firmware.smu_load = false; return err; } -- cgit v1.1 From ad2473af273b81cf184d6e43a395a128d4db7b87 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Wed, 7 Sep 2016 08:42:41 -0400 Subject: drm/amd/amdgpu: Fix return values in SI DPM code Fix a couple of spots where errors were not returned as well as add some error messages to si_patch_dependency_based_on_leakage() which were not being read. Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 92a0417..e4f7c10 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -2824,7 +2824,7 @@ done_free: kfree(cac_tables); - return 0; + return ret; } static int si_program_cac_config_registers(struct amdgpu_device *adev, @@ -6376,10 +6376,16 @@ static int si_patch_dependency_tables_based_on_leakage(struct amdgpu_device *ade ret = si_patch_single_dependency_table_based_on_leakage(adev, &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk); + if (ret) + DRM_ERROR("Could not patch vddc_on_sclk leakage table\n"); ret = si_patch_single_dependency_table_based_on_leakage(adev, &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk); + if (ret) + DRM_ERROR("Could not patch vddc_on_mclk leakage table\n"); ret = si_patch_single_dependency_table_based_on_leakage(adev, &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk); + if (ret) + DRM_ERROR("Could not patch vddci_on_mclk leakage table\n"); return ret; } @@ -6542,7 +6548,7 @@ static int si_thermal_setup_fan_table(struct amdgpu_device *adev) adev->pm.dpm.fan.ucode_fan_control = false; } - return 0; + return ret; } static int si_fan_ctrl_start_smc_fan_control(struct amdgpu_device *adev) -- cgit v1.1 From aa1d562e645d2542b48bdd42903726adfc87efb3 Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Thu, 8 Sep 2016 10:13:32 +0800 Subject: drm/amdgpu: add a new helper to free a BO in kernel allocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free the BO allocated by amdgpu_bo_create_kernel() Signed-off-by: Junwei Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 29 +++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index b17734e..162411b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -287,6 +287,35 @@ error_free: return r; } +/** + * amdgpu_bo_free_kernel - free BO for kernel use + * + * @bo: amdgpu BO to free + * + * unmaps and unpin a BO for kernel internal use. + */ +void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, + void **cpu_addr) +{ + if (*bo == NULL) + return; + + if (likely(amdgpu_bo_reserve(*bo, false) == 0)) { + if (cpu_addr) + amdgpu_bo_kunmap(*bo); + + amdgpu_bo_unpin(*bo); + amdgpu_bo_unreserve(*bo); + } + amdgpu_bo_unref(bo); + + if (gpu_addr) + *gpu_addr = 0; + + if (cpu_addr) + *cpu_addr = NULL; +} + int amdgpu_bo_create_restricted(struct amdgpu_device *adev, unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index b6a2739..3032c54 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -128,6 +128,8 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev, unsigned long size, int align, u32 domain, struct amdgpu_bo **bo_ptr, u64 *gpu_addr, void **cpu_addr); +void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, + void **cpu_addr); int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr); void amdgpu_bo_kunmap(struct amdgpu_bo *bo); struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo); -- cgit v1.1 From 8640faed5a8a8f55d6decd2d9c9f35ae687b1e4c Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Wed, 7 Sep 2016 17:14:46 +0800 Subject: drm/amdgpu: free the BO in kernel by helper amdgpu_bo_free_kernel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Junwei Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c | 16 +++------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 19 ++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 15 +++------------ drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +++--- 5 files changed, 16 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c index 5ebb3f4..3ab4c65 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c @@ -119,8 +119,6 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, unsigned ring_size, */ void amdgpu_ih_ring_fini(struct amdgpu_device *adev) { - int r; - if (adev->irq.ih.use_bus_addr) { if (adev->irq.ih.ring) { /* add 8 bytes for the rptr/wptr shadows and @@ -132,17 +130,9 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev) adev->irq.ih.ring = NULL; } } else { - if (adev->irq.ih.ring_obj) { - r = amdgpu_bo_reserve(adev->irq.ih.ring_obj, false); - if (likely(r == 0)) { - amdgpu_bo_kunmap(adev->irq.ih.ring_obj); - amdgpu_bo_unpin(adev->irq.ih.ring_obj); - amdgpu_bo_unreserve(adev->irq.ih.ring_obj); - } - amdgpu_bo_unref(&adev->irq.ih.ring_obj); - adev->irq.ih.ring = NULL; - adev->irq.ih.ring_obj = NULL; - } + amdgpu_bo_free_kernel(&adev->irq.ih.ring_obj, + &adev->irq.ih.gpu_addr, + (void **)&adev->irq.ih.ring); amdgpu_wb_free(adev, adev->irq.ih.wptr_offs); amdgpu_wb_free(adev, adev->irq.ih.rptr_offs); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 242ba04..777f11b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -252,28 +252,17 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, */ void amdgpu_ring_fini(struct amdgpu_ring *ring) { - int r; - struct amdgpu_bo *ring_obj; - - ring_obj = ring->ring_obj; ring->ready = false; - ring->ring = NULL; - ring->ring_obj = NULL; amdgpu_wb_free(ring->adev, ring->cond_exe_offs); amdgpu_wb_free(ring->adev, ring->fence_offs); amdgpu_wb_free(ring->adev, ring->rptr_offs); amdgpu_wb_free(ring->adev, ring->wptr_offs); - if (ring_obj) { - r = amdgpu_bo_reserve(ring_obj, false); - if (likely(r == 0)) { - amdgpu_bo_kunmap(ring_obj); - amdgpu_bo_unpin(ring_obj); - amdgpu_bo_unreserve(ring_obj); - } - amdgpu_bo_unref(&ring_obj); - } + amdgpu_bo_free_kernel(&ring->ring_obj, + &ring->gpu_addr, + (void **)&ring->ring); + amdgpu_debugfs_ring_fini(ring); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index cc766cc..a71efeb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -249,22 +249,13 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) int amdgpu_uvd_sw_fini(struct amdgpu_device *adev) { - int r; - kfree(adev->uvd.saved_bo); amd_sched_entity_fini(&adev->uvd.ring.sched, &adev->uvd.entity); - if (adev->uvd.vcpu_bo) { - r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false); - if (!r) { - amdgpu_bo_kunmap(adev->uvd.vcpu_bo); - amdgpu_bo_unpin(adev->uvd.vcpu_bo); - amdgpu_bo_unreserve(adev->uvd.vcpu_bo); - } - - amdgpu_bo_unref(&adev->uvd.vcpu_bo); - } + amdgpu_bo_free_kernel(&adev->uvd.vcpu_bo, + &adev->uvd.gpu_addr, + (void **)&adev->uvd.cpu_addr); amdgpu_ring_fini(&adev->uvd.ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 1c3bb2d..a93a803 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4490,9 +4490,9 @@ static int gfx_v7_0_sw_fini(void *handle) int i; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - amdgpu_bo_unref(&adev->gds.oa_gfx_bo); - amdgpu_bo_unref(&adev->gds.gws_gfx_bo); - amdgpu_bo_unref(&adev->gds.gds_gfx_bo); + amdgpu_bo_free_kernel(&adev->gds.oa_gfx_bo, NULL, NULL); + amdgpu_bo_free_kernel(&adev->gds.gws_gfx_bo, NULL, NULL); + amdgpu_bo_free_kernel(&adev->gds.gds_gfx_bo, NULL, NULL); for (i = 0; i < adev->gfx.num_gfx_rings; i++) amdgpu_ring_fini(&adev->gfx.gfx_ring[i]); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index c49d06b..4491505 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -2109,9 +2109,9 @@ static int gfx_v8_0_sw_fini(void *handle) int i; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - amdgpu_bo_unref(&adev->gds.oa_gfx_bo); - amdgpu_bo_unref(&adev->gds.gws_gfx_bo); - amdgpu_bo_unref(&adev->gds.gds_gfx_bo); + amdgpu_bo_free_kernel(&adev->gds.oa_gfx_bo, NULL, NULL); + amdgpu_bo_free_kernel(&adev->gds.gws_gfx_bo, NULL, NULL); + amdgpu_bo_free_kernel(&adev->gds.gds_gfx_bo, NULL, NULL); for (i = 0; i < adev->gfx.num_gfx_rings; i++) amdgpu_ring_fini(&adev->gfx.gfx_ring[i]); -- cgit v1.1 From e7b54945f5eb3394ec630e350b5faa686c6a0eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 7 Sep 2016 11:51:06 +0900 Subject: drm/amdgpu/si: Call amdgpu_ttm_set_active_vram_size from si_dma_start/stop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this, we were only ever using the first 256MB of VRAM. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97593 Tested-by: Konstantin A. Lepikhov Tested-by: Arek Ruśniak Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dma.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 2abdaa6..4cbd408 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -132,6 +132,8 @@ static void si_dma_stop(struct amdgpu_device *adev) rb_cntl &= ~DMA_RB_ENABLE; WREG32(DMA_RB_CNTL + sdma_offsets[i], rb_cntl); + if (adev->mman.buffer_funcs_ring == ring) + amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size); ring->ready = false; } } @@ -192,6 +194,9 @@ static int si_dma_start(struct amdgpu_device *adev) ring->ready = false; return r; } + + if (adev->mman.buffer_funcs_ring == ring) + amdgpu_ttm_set_active_vram_size(adev, adev->mc.real_vram_size); } return 0; -- cgit v1.1 From 519df8a6f21d4f7a86f137dd65f75ebf66663f7d Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 7 Sep 2016 15:06:58 +0800 Subject: drm/amd/powerplay: calculate flexible array member's address. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h | 2 +- .../amd/powerplay/hwmgr/tonga_processpptables.c | 218 +++++++++++++-------- drivers/gpu/drm/amd/powerplay/inc/pp_debug.h | 3 + 3 files changed, 140 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h index f127198..1e870f5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h @@ -164,7 +164,7 @@ typedef struct _ATOM_Tonga_State { typedef struct _ATOM_Tonga_State_Array { UCHAR ucRevId; UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_State states[1]; /* Dynamically allocate entries. */ + ATOM_Tonga_State entries[1]; /* Dynamically allocate entries. */ } ATOM_Tonga_State_Array; typedef struct _ATOM_Tonga_MCLK_Dependency_Record { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c index 622ac02..0f3dad3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c @@ -154,12 +154,14 @@ const void *get_powerplay_table(struct pp_hwmgr *hwmgr) static int get_vddc_lookup_table( struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table **lookup_table, - const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables, - uint32_t max_levels + const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables, + uint32_t max_levels ) { uint32_t table_size, i; phm_ppt_v1_voltage_lookup_table *table; + phm_ppt_v1_voltage_lookup_record *record; + ATOM_Tonga_Voltage_Lookup_Record *atom_record; PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries), "Invalid CAC Leakage PowerPlay Table!", return 1); @@ -177,15 +179,17 @@ static int get_vddc_lookup_table( table->count = vddc_lookup_pp_tables->ucNumEntries; for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) { - table->entries[i].us_calculated = 0; - table->entries[i].us_vdd = - vddc_lookup_pp_tables->entries[i].usVdd; - table->entries[i].us_cac_low = - vddc_lookup_pp_tables->entries[i].usCACLow; - table->entries[i].us_cac_mid = - vddc_lookup_pp_tables->entries[i].usCACMid; - table->entries[i].us_cac_high = - vddc_lookup_pp_tables->entries[i].usCACHigh; + record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_voltage_lookup_record, + entries, table, i); + atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_Voltage_Lookup_Record, + entries, vddc_lookup_pp_tables, i); + record->us_calculated = 0; + record->us_vdd = atom_record->usVdd; + record->us_cac_low = atom_record->usCACLow; + record->us_cac_mid = atom_record->usCACMid; + record->us_cac_high = atom_record->usCACHigh; } *lookup_table = table; @@ -314,11 +318,12 @@ static int init_dpm_2_parameters( static int get_valid_clk( struct pp_hwmgr *hwmgr, struct phm_clock_array **clk_table, - const phm_ppt_v1_clock_voltage_dependency_table * clk_volt_pp_table + phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table ) { uint32_t table_size, i; struct phm_clock_array *table; + phm_ppt_v1_clock_voltage_dependency_record *dep_record; PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count), "Invalid PowerPlay Table!", return -1); @@ -335,9 +340,12 @@ static int get_valid_clk( table->count = (uint32_t)clk_volt_pp_table->count; - for (i = 0; i < table->count; i++) - table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk; - + for (i = 0; i < table->count; i++) { + dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, clk_volt_pp_table, i); + table->values[i] = (uint32_t)dep_record->clk; + } *clk_table = table; return 0; @@ -346,7 +354,7 @@ static int get_valid_clk( static int get_hard_limits( struct pp_hwmgr *hwmgr, struct phm_clock_and_voltage_limits *limits, - const ATOM_Tonga_Hard_Limit_Table * limitable + ATOM_Tonga_Hard_Limit_Table const *limitable ) { PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1); @@ -364,11 +372,13 @@ static int get_hard_limits( static int get_mclk_voltage_dependency_table( struct pp_hwmgr *hwmgr, phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table, - const ATOM_Tonga_MCLK_Dependency_Table * mclk_dep_table + ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table ) { uint32_t table_size, i; phm_ppt_v1_clock_voltage_dependency_table *mclk_table; + phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record; + ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries), "Invalid PowerPlay Table!", return -1); @@ -386,16 +396,17 @@ static int get_mclk_voltage_dependency_table( mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { - mclk_table->entries[i].vddInd = - mclk_dep_table->entries[i].ucVddcInd; - mclk_table->entries[i].vdd_offset = - mclk_dep_table->entries[i].usVddgfxOffset; - mclk_table->entries[i].vddci = - mclk_dep_table->entries[i].usVddci; - mclk_table->entries[i].mvdd = - mclk_dep_table->entries[i].usMvdd; - mclk_table->entries[i].clk = - mclk_dep_table->entries[i].ulMclk; + mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, mclk_table, i); + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, i); + mclk_table_record->vddInd = mclk_dep_record->ucVddcInd; + mclk_table_record->vdd_offset = mclk_dep_record->usVddgfxOffset; + mclk_table_record->vddci = mclk_dep_record->usVddci; + mclk_table_record->mvdd = mclk_dep_record->usMvdd; + mclk_table_record->clk = mclk_dep_record->ulMclk; } *pp_tonga_mclk_dep_table = mclk_table; @@ -411,10 +422,12 @@ static int get_sclk_voltage_dependency_table( { uint32_t table_size, i; phm_ppt_v1_clock_voltage_dependency_table *sclk_table; + phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record; if (sclk_dep_table->ucRevId < 1) { const ATOM_Tonga_SCLK_Dependency_Table *tonga_table = (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table; + ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries), "Invalid PowerPlay Table!", return -1); @@ -432,20 +445,23 @@ static int get_sclk_voltage_dependency_table( sclk_table->count = (uint32_t)tonga_table->ucNumEntries; for (i = 0; i < tonga_table->ucNumEntries; i++) { - sclk_table->entries[i].vddInd = - tonga_table->entries[i].ucVddInd; - sclk_table->entries[i].vdd_offset = - tonga_table->entries[i].usVddcOffset; - sclk_table->entries[i].clk = - tonga_table->entries[i].ulSclk; - sclk_table->entries[i].cks_enable = - (((tonga_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; - sclk_table->entries[i].cks_voffset = - (tonga_table->entries[i].ucCKSVOffsetandDisable & 0x7F); + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_SCLK_Dependency_Record, + entries, tonga_table, i); + sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, sclk_table, i); + sclk_table_record->vddInd = sclk_dep_record->ucVddInd; + sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset; + sclk_table_record->clk = sclk_dep_record->ulSclk; + sclk_table_record->cks_enable = + (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; + sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); } } else { const ATOM_Polaris_SCLK_Dependency_Table *polaris_table = (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table; + ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record; PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries), "Invalid PowerPlay Table!", return -1); @@ -463,17 +479,19 @@ static int get_sclk_voltage_dependency_table( sclk_table->count = (uint32_t)polaris_table->ucNumEntries; for (i = 0; i < polaris_table->ucNumEntries; i++) { - sclk_table->entries[i].vddInd = - polaris_table->entries[i].ucVddInd; - sclk_table->entries[i].vdd_offset = - polaris_table->entries[i].usVddcOffset; - sclk_table->entries[i].clk = - polaris_table->entries[i].ulSclk; - sclk_table->entries[i].cks_enable = - (((polaris_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; - sclk_table->entries[i].cks_voffset = - (polaris_table->entries[i].ucCKSVOffsetandDisable & 0x7F); - sclk_table->entries[i].sclk_offset = polaris_table->entries[i].ulSclkOffset; + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Polaris_SCLK_Dependency_Record, + entries, polaris_table, i); + sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, sclk_table, i); + sclk_table_record->vddInd = sclk_dep_record->ucVddInd; + sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset; + sclk_table_record->clk = sclk_dep_record->ulSclk; + sclk_table_record->cks_enable = + (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; + sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); + sclk_table_record->sclk_offset = sclk_dep_record->ulSclkOffset; } } *pp_tonga_sclk_dep_table = sclk_table; @@ -484,16 +502,19 @@ static int get_sclk_voltage_dependency_table( static int get_pcie_table( struct pp_hwmgr *hwmgr, phm_ppt_v1_pcie_table **pp_tonga_pcie_table, - const PPTable_Generic_SubTable_Header * pTable + PPTable_Generic_SubTable_Header const *ptable ) { uint32_t table_size, i, pcie_count; phm_ppt_v1_pcie_table *pcie_table; struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_pcie_record *pcie_record; + + if (ptable->ucRevId < 1) { + const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable; + ATOM_Tonga_PCIE_Record *atom_pcie_record; - if (pTable->ucRevId < 1) { - const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)pTable; PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), "Invalid PowerPlay Table!", return -1); @@ -519,18 +540,23 @@ static int get_pcie_table( Disregarding the excess entries... \n"); pcie_table->count = pcie_count; - for (i = 0; i < pcie_count; i++) { - pcie_table->entries[i].gen_speed = - atom_pcie_table->entries[i].ucPCIEGenSpeed; - pcie_table->entries[i].lane_width = - atom_pcie_table->entries[i].usPCIELaneWidth; + pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_pcie_record, + entries, pcie_table, i); + atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_PCIE_Record, + entries, atom_pcie_table, i); + pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; + pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth; } *pp_tonga_pcie_table = pcie_table; } else { /* Polaris10/Polaris11 and newer. */ - const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)pTable; + const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable; + ATOM_Polaris10_PCIE_Record *atom_pcie_record; + PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), "Invalid PowerPlay Table!", return -1); @@ -558,12 +584,15 @@ static int get_pcie_table( pcie_table->count = pcie_count; for (i = 0; i < pcie_count; i++) { - pcie_table->entries[i].gen_speed = - atom_pcie_table->entries[i].ucPCIEGenSpeed; - pcie_table->entries[i].lane_width = - atom_pcie_table->entries[i].usPCIELaneWidth; - pcie_table->entries[i].pcie_sclk = - atom_pcie_table->entries[i].ulPCIE_Sclk; + pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_pcie_record, + entries, pcie_table, i); + atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Polaris10_PCIE_Record, + entries, atom_pcie_table, i); + pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; + pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth; + pcie_record->pcie_sclk = atom_pcie_record->ulPCIE_Sclk; } *pp_tonga_pcie_table = pcie_table; @@ -685,6 +714,7 @@ static int get_mm_clock_voltage_table( uint32_t table_size, i; const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record; phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; + phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record; PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries), "Invalid PowerPlay Table!", return -1); @@ -701,14 +731,19 @@ static int get_mm_clock_voltage_table( mm_table->count = mm_dependency_table->ucNumEntries; for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { - mm_dependency_record = &mm_dependency_table->entries[i]; - mm_table->entries[i].vddcInd = mm_dependency_record->ucVddcInd; - mm_table->entries[i].vddgfx_offset = mm_dependency_record->usVddgfxOffset; - mm_table->entries[i].aclk = mm_dependency_record->ulAClk; - mm_table->entries[i].samclock = mm_dependency_record->ulSAMUClk; - mm_table->entries[i].eclk = mm_dependency_record->ulEClk; - mm_table->entries[i].vclk = mm_dependency_record->ulVClk; - mm_table->entries[i].dclk = mm_dependency_record->ulDClk; + mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MM_Dependency_Record, + entries, mm_dependency_table, i); + mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_mm_clock_voltage_dependency_record, + entries, mm_table, i); + mm_table_record->vddcInd = mm_dependency_record->ucVddcInd; + mm_table_record->vddgfx_offset = mm_dependency_record->usVddgfxOffset; + mm_table_record->aclk = mm_dependency_record->ulAClk; + mm_table_record->samclock = mm_dependency_record->ulSAMUClk; + mm_table_record->eclk = mm_dependency_record->ulEClk; + mm_table_record->vclk = mm_dependency_record->ulVClk; + mm_table_record->dclk = mm_dependency_record->ulDClk; } *tonga_mm_table = mm_table; @@ -1176,11 +1211,13 @@ static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr) return vce_state_table->ucNumEntries; } - static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i, struct pp_vce_state *vce_state, void **clock_info, uint32_t *flag) { const ATOM_Tonga_VCE_State_Record *vce_state_record; + ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; + ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; + ATOM_Tonga_MM_Dependency_Record *mm_dep_record; const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr); const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable) + le16_to_cpu(pptable->usVCEStateTableOffset)); @@ -1195,20 +1232,35 @@ static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i "Requested state entry ID is out of range!", return -EINVAL); - vce_state_record = (ATOM_Tonga_VCE_State_Record *)((char *)&vce_state_table->entries[1] - + (sizeof(ATOM_Tonga_VCE_State_Record) * i)); - + vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_VCE_State_Record, + entries, vce_state_table, i); + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_SCLK_Dependency_Record, + entries, sclk_dep_table, + vce_state_record->ucSCLKIndex); + mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MM_Dependency_Record, + entries, mm_dep_table, + vce_state_record->ucVCEClockIndex); *flag = vce_state_record->ucFlag; - vce_state->evclk = mm_dep_table->entries[vce_state_record->ucVCEClockIndex].ulEClk; - vce_state->ecclk = mm_dep_table->entries[vce_state_record->ucVCEClockIndex].ulEClk; - vce_state->sclk = sclk_dep_table->entries[vce_state_record->ucSCLKIndex].ulSclk; + vce_state->evclk = mm_dep_record->ulEClk; + vce_state->ecclk = mm_dep_record->ulEClk; + vce_state->sclk = sclk_dep_record->ulSclk; if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries) - vce_state->mclk = mclk_dep_table->entries[mclk_dep_table->ucNumEntries - 1].ulMclk; + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, + mclk_dep_table->ucNumEntries - 1); else - vce_state->mclk = mclk_dep_table->entries[vce_state_record->ucMCLKIndex].ulMclk; + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, + vce_state_record->ucMCLKIndex); + vce_state->mclk = mclk_dep_record->ulMclk; return 0; } @@ -1226,7 +1278,7 @@ int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, struct pp_power_state *, void *, uint32_t)) { int result = 0; - const ATOM_Tonga_State_Array * state_arrays; + const ATOM_Tonga_State_Array *state_arrays; const ATOM_Tonga_State *state_entry; const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); int i, j; @@ -1247,7 +1299,9 @@ int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), "Invalid PowerPlay Table State Array Entry.", return -1); - state_entry = &(state_arrays->states[entry_index]); + state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_State, entries, + state_arrays, entry_index); result = call_back_func(hwmgr, (void *)state_entry, power_state, (void *)pp_table, diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h index d7d83b7..bfdbec1 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h @@ -43,5 +43,8 @@ } while (0) +#define GET_FLEXIBLE_ARRAY_MEMBER_ADDR(type, member, ptr, n) \ + (type *)((char *)&(ptr)->member + (sizeof(type) * (n))) + #endif /* PP_DEBUG_H */ -- cgit v1.1 From 1db422de72c31fcf81f31311468a747aad389fa5 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 11 Aug 2016 19:52:25 +0800 Subject: drm/amd/powerplay: declare functions instand of include header file. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smumgr.h | 6 ++++++ drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h index dede153..34abfd2 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h @@ -121,6 +121,12 @@ extern int smu_allocate_memory(void *device, uint32_t size, extern int smu_free_memory(void *device, void *handle); +extern int cz_smum_init(struct pp_smumgr *smumgr); +extern int iceland_smum_init(struct pp_smumgr *smumgr); +extern int tonga_smum_init(struct pp_smumgr *smumgr); +extern int fiji_smum_init(struct pp_smumgr *smumgr); +extern int polaris10_smum_init(struct pp_smumgr *smumgr); + #define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT #define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index e6dc95d..83d8f7e 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -28,11 +28,6 @@ #include "smumgr.h" #include "cgs_common.h" #include "linux/delay.h" -#include "cz_smumgr.h" -#include "tonga_smumgr.h" -#include "iceland_smumgr.h" -#include "fiji_smumgr.h" -#include "polaris10_smumgr.h" int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle) { -- cgit v1.1 From 753ad49c9fdfc732972b0d03f2889f473ed35e59 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Fri, 26 Aug 2016 13:28:28 +0800 Subject: drm/amdgpu:implement CONTEXT_CONTROL (v5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1: for gfx8, use CONTEXT_CONTROL package to dynamically skip preamble CEIB and other load_xxx command in sequence. v2: support GFX7 as well. remove cntxcntl in compute ring funcs because CPC doesn't support this packet. v3: fix reduntant judgement in cntxcntl. v4: some cleanups, don't change cs_submit() v5: keep old MESA supported & bump up KMS version. Signed-off-by: Monk Liu Ack-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 ++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 8 ++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 12 +++++++++++- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 20 ++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 30 ++++++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 10ec29c..717c3b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -320,6 +320,7 @@ struct amdgpu_ring_funcs { void (*begin_use)(struct amdgpu_ring *ring); void (*end_use)(struct amdgpu_ring *ring); void (*emit_switch_buffer) (struct amdgpu_ring *ring); + void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags); }; /* @@ -966,6 +967,7 @@ struct amdgpu_ctx { spinlock_t ring_lock; struct fence **fences; struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS]; + bool preamble_presented; }; struct amdgpu_ctx_mgr { @@ -1231,6 +1233,10 @@ struct amdgpu_cs_parser { struct amdgpu_bo_list_entry uf_entry; }; +#define AMDGPU_PREAMBLE_IB_PRESENT (1 << 0) /* bit set means command submit involves a preamble IB */ +#define AMDGPU_PREAMBLE_IB_PRESENT_FIRST (1 << 1) /* bit set means preamble IB is first presented in belonging context */ +#define AMDGPU_HAVE_CTX_SWITCH (1 << 2) /* bit set means context switch occured */ + struct amdgpu_job { struct amd_sched_job base; struct amdgpu_device *adev; @@ -1239,6 +1245,7 @@ struct amdgpu_job { struct amdgpu_sync sync; struct amdgpu_ib *ibs; struct fence *fence; /* the hw fence */ + uint32_t preamble_status; uint32_t num_ibs; void *owner; uint64_t fence_ctx; /* the fence_context this job uses */ @@ -2276,6 +2283,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r)) #define amdgpu_ring_emit_hdp_invalidate(r) (r)->funcs->emit_hdp_invalidate((r)) #define amdgpu_ring_emit_switch_buffer(r) (r)->funcs->emit_switch_buffer((r)) +#define amdgpu_ring_emit_cntxcntl(r, d) (r)->funcs->emit_cntxcntl((r), (d)) #define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib))) #define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r)) #define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 56bde64..61b7e25 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -850,6 +850,14 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, if (r) return r; + if (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) { + parser->job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT; + if (!parser->ctx->preamble_presented) { + parser->job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT_FIRST; + parser->ctx->preamble_presented = true; + } + } + if (parser->job->ring && parser->job->ring != ring) return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 3bbc0faf..ca3d87a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -55,9 +55,10 @@ * - 3.3.0 - Add VM support for UVD on supported hardware. * - 3.4.0 - Add AMDGPU_INFO_NUM_EVICTIONS. * - 3.5.0 - Add support for new UVD_NO_OP register. + * - 3.6.0 - kmd involves use CONTEXT_CONTROL in ring buffer. */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 5 +#define KMS_DRIVER_MINOR 6 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 04263f0..2aa741c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -125,6 +125,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, unsigned patch_offset = ~0; struct amdgpu_vm *vm; uint64_t fence_ctx; + uint32_t status = 0; unsigned i; int r = 0; @@ -176,11 +177,20 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, skip_preamble = ring->current_ctx == fence_ctx; need_ctx_switch = ring->current_ctx != fence_ctx; + if (job && ring->funcs->emit_cntxcntl) { + if (need_ctx_switch) + status |= AMDGPU_HAVE_CTX_SWITCH; + status |= job->preamble_status; + amdgpu_ring_emit_cntxcntl(ring, status); + } + for (i = 0; i < num_ibs; ++i) { ib = &ibs[i]; /* drop preamble IBs if we don't have a context switch */ - if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && skip_preamble) + if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && + skip_preamble && + !(status & AMDGPU_PREAMBLE_IB_PRESENT_FIRST)) continue; amdgpu_ring_emit_ib(ring, ib, job ? job->vm_id : 0, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index a93a803..8c780f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2096,6 +2096,25 @@ static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring, amdgpu_ring_write(ring, control); } +static void gfx_v7_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) +{ + uint32_t dw2 = 0; + + dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */ + if (flags & AMDGPU_HAVE_CTX_SWITCH) { + /* set load_global_config & load_global_uconfig */ + dw2 |= 0x8001; + /* set load_cs_sh_regs */ + dw2 |= 0x01000000; + /* set load_per_context_state & load_gfx_sh_regs */ + dw2 |= 0x10002; + } + + amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1)); + amdgpu_ring_write(ring, dw2); + amdgpu_ring_write(ring, 0); +} + /** * gfx_v7_0_ring_test_ib - basic ring IB test * @@ -4938,6 +4957,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { .test_ib = gfx_v7_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, + .emit_cntxcntl = gfx_v7_ring_emit_cntxcntl, }; static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 4491505..dca8b36 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6076,6 +6076,35 @@ static void gfx_v8_ring_emit_sb(struct amdgpu_ring *ring) amdgpu_ring_write(ring, 0); } +static void gfx_v8_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) +{ + uint32_t dw2 = 0; + + dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */ + if (flags & AMDGPU_HAVE_CTX_SWITCH) { + /* set load_global_config & load_global_uconfig */ + dw2 |= 0x8001; + /* set load_cs_sh_regs */ + dw2 |= 0x01000000; + /* set load_per_context_state & load_gfx_sh_regs for GFX */ + dw2 |= 0x10002; + + /* set load_ce_ram if preamble presented */ + if (AMDGPU_PREAMBLE_IB_PRESENT & flags) + dw2 |= 0x10000000; + } else { + /* still load_ce_ram if this is the first time preamble presented + * although there is no context switch happens. + */ + if (AMDGPU_PREAMBLE_IB_PRESENT_FIRST & flags) + dw2 |= 0x10000000; + } + + amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1)); + amdgpu_ring_write(ring, dw2); + amdgpu_ring_write(ring, 0); +} + static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, enum amdgpu_interrupt_state state) { @@ -6258,6 +6287,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, .emit_switch_buffer = gfx_v8_ring_emit_sb, + .emit_cntxcntl = gfx_v8_ring_emit_cntxcntl, }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { -- cgit v1.1 From d28d6e6fa55e08a16a83ae572b1cbf4f03e8fbf1 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 7 Sep 2016 13:24:31 +0800 Subject: drm: modify drm_global_item_ref to avoid two times of writing ref->object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In previous drm_global_item_ref, there are two times of writing ref->object if item->refcount is 0. So this patch does a minor update to put alloc and init ref firstly, and then to modify the item of glob array. Use "else" to avoid two times of writing ref->object. It can make the code logic more clearly. Reviewed-by: Christian König Signed-off-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/drm_global.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_global.c b/drivers/gpu/drm/drm_global.c index 3d2e91c..b404287 100644 --- a/drivers/gpu/drm/drm_global.c +++ b/drivers/gpu/drm/drm_global.c @@ -65,30 +65,34 @@ void drm_global_release(void) int drm_global_item_ref(struct drm_global_reference *ref) { - int ret; + int ret = 0; struct drm_global_item *item = &glob[ref->global_type]; mutex_lock(&item->mutex); if (item->refcount == 0) { - item->object = kzalloc(ref->size, GFP_KERNEL); - if (unlikely(item->object == NULL)) { + ref->object = kzalloc(ref->size, GFP_KERNEL); + if (unlikely(ref->object == NULL)) { ret = -ENOMEM; - goto out_err; + goto error_unlock; } - - ref->object = item->object; ret = ref->init(ref); if (unlikely(ret != 0)) - goto out_err; + goto error_free; + item->object = ref->object; + } else { + ref->object = item->object; } + ++item->refcount; - ref->object = item->object; mutex_unlock(&item->mutex); return 0; -out_err: + +error_free: + kfree(ref->object); + ref->object = NULL; +error_unlock: mutex_unlock(&item->mutex); - item->object = NULL; return ret; } EXPORT_SYMBOL(drm_global_item_ref); -- cgit v1.1 From 71c76a086f04055e2da8d7d71c77e0b37ac310a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 3 Sep 2016 16:18:26 +0200 Subject: drm/amdgpu: fix GTT offset handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we run into problems on 32bit systems with more than 4GB GART. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3beb10b..a4914b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -648,7 +648,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, return r; } } - gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT); + gtt->offset = (u64)bo_mem->start << PAGE_SHIFT; if (!ttm->num_pages) { WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", ttm->num_pages, bo_mem, ttm); @@ -663,8 +663,8 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, ttm->pages, gtt->ttm.dma_address, flags); if (r) { - DRM_ERROR("failed to bind %lu pages at 0x%08X\n", - ttm->num_pages, (unsigned)gtt->offset); + DRM_ERROR("failed to bind %lu pages at 0x%08llX\n", + ttm->num_pages, gtt->offset); return r; } spin_lock(>t->adev->gtt_list_lock); @@ -689,8 +689,8 @@ int amdgpu_ttm_recover_gart(struct amdgpu_device *adev) flags); if (r) { spin_unlock(&adev->gtt_list_lock); - DRM_ERROR("failed to bind %lu pages at 0x%08X\n", - gtt->ttm.ttm.num_pages, (unsigned)gtt->offset); + DRM_ERROR("failed to bind %lu pages at 0x%08llX\n", + gtt->ttm.ttm.num_pages, gtt->offset); return r; } } -- cgit v1.1 From c855e25090cdafffb87119028eb018030a46dd9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 5 Sep 2016 17:00:57 +0200 Subject: drm/amdgpu: bind GTT on demand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't really need the GTT table any more most of the time. So bind it only on demand. Signed-off-by: Christian König Reviewed-by: Alex Deucher Acked-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 34 ++++++++++++++++++++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 7 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 33 ++++++++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 6 +++++- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 3 ++- 8 files changed, 84 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 717c3b4..2e8f469 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2521,6 +2521,7 @@ static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } struct amdgpu_bo_va_mapping * amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, uint64_t addr, struct amdgpu_bo **bo); +int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser); #include "amdgpu_object.h" #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 61b7e25..f7dccb1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -639,8 +639,12 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, } } - if (p->uf_entry.robj) - p->job->uf_addr += amdgpu_bo_gpu_offset(p->uf_entry.robj); + if (!r && p->uf_entry.robj) { + struct amdgpu_bo *uf = p->uf_entry.robj; + + r = amdgpu_ttm_bind(uf->tbo.ttm, &uf->tbo.mem); + p->job->uf_addr += amdgpu_bo_gpu_offset(uf); + } error_validate: if (r) { @@ -1163,3 +1167,29 @@ amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, return NULL; } + +/** + * amdgpu_cs_sysvm_access_required - make BOs accessible by the system VM + * + * @parser: command submission parser context + * + * Helper for UVD/VCE VM emulation, make sure BOs are accessible by the system VM. + */ +int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser) +{ + unsigned i; + int r; + + if (!parser->bo_list) + return 0; + + for (i = 0; i < parser->bo_list->num_entries; i++) { + struct amdgpu_bo *bo = parser->bo_list->array[i].robj; + + r = amdgpu_ttm_bind(bo->tbo.ttm, &bo->tbo.mem); + if (unlikely(r)) + return r; + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 162411b..5a6216c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -675,6 +675,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, dev_err(bo->adev->dev, "%p pin failed\n", bo); goto error; } + r = amdgpu_ttm_bind(bo->tbo.ttm, &bo->tbo.mem); + if (unlikely(r)) { + dev_err(bo->adev->dev, "%p bind failed\n", bo); + goto error; + } bo->pin_count = 1; if (gpu_addr != NULL) @@ -947,6 +952,8 @@ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence, u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) { WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM); + WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_TT && + !amdgpu_ttm_is_bound(bo->tbo.ttm)); WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) && !bo->pin_count); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a4914b7..73298fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -256,8 +256,12 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, new_start = new_mem->start << PAGE_SHIFT; switch (old_mem->mem_type) { - case TTM_PL_VRAM: case TTM_PL_TT: + r = amdgpu_ttm_bind(bo->ttm, old_mem); + if (r) + return r; + + case TTM_PL_VRAM: old_start += bo->bdev->man[old_mem->mem_type].gpu_offset; break; default: @@ -265,8 +269,12 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, return -EINVAL; } switch (new_mem->mem_type) { - case TTM_PL_VRAM: case TTM_PL_TT: + r = amdgpu_ttm_bind(bo->ttm, new_mem); + if (r) + return r; + + case TTM_PL_VRAM: new_start += bo->bdev->man[new_mem->mem_type].gpu_offset; break; default: @@ -638,7 +646,6 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) { struct amdgpu_ttm_tt *gtt = (void*)ttm; - uint32_t flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem); int r; if (gtt->userptr) { @@ -659,6 +666,26 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, bo_mem->mem_type == AMDGPU_PL_OA) return -EINVAL; + return 0; +} + +bool amdgpu_ttm_is_bound(struct ttm_tt *ttm) +{ + struct amdgpu_ttm_tt *gtt = (void *)ttm; + + return gtt && !list_empty(>t->list); +} + +int amdgpu_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) +{ + struct amdgpu_ttm_tt *gtt = (void *)ttm; + uint32_t flags; + int r; + + if (!ttm || amdgpu_ttm_is_bound(ttm)) + return 0; + + flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem); r = amdgpu_gart_bind(gtt->adev, gtt->offset, ttm->num_pages, ttm->pages, gtt->ttm.dma_address, flags); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 72f6bfc..214bae9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -77,4 +77,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct fence **fence); int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); +bool amdgpu_ttm_is_bound(struct ttm_tt *ttm); +int amdgpu_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index a71efeb..25dd58a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -882,6 +882,10 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx) return -EINVAL; } + r = amdgpu_cs_sysvm_access_required(parser); + if (r) + return r; + ctx.parser = parser; ctx.buf_sizes = buf_sizes; ctx.ib_idx = ib_idx; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 9b71d6c..b0c6702 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -634,7 +634,11 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) uint32_t allocated = 0; uint32_t tmp, handle = 0; uint32_t *size = &tmp; - int i, r = 0, idx = 0; + int i, r, idx = 0; + + r = amdgpu_cs_sysvm_access_required(p); + if (r) + return r; while (idx < ib->length_dw) { uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index bf56f18..bd5af32 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1163,7 +1163,8 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, } flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem); - gtt_flags = (adev == bo_va->bo->adev) ? flags : 0; + gtt_flags = (amdgpu_ttm_is_bound(bo_va->bo->tbo.ttm) && + adev == bo_va->bo->adev) ? flags : 0; spin_lock(&vm->status_lock); if (!list_empty(&bo_va->vm_status)) -- cgit v1.1 From 441f90ecf59e089d234ff3feea98de10779a048b Mon Sep 17 00:00:00 2001 From: Flora Cui Date: Fri, 9 Sep 2016 14:15:30 +0800 Subject: drm/amdgpu: update gart_pin_size if bo is in GTT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Flora Cui Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 5a6216c..e503ca1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -726,7 +726,7 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo) bo->adev->vram_pin_size -= amdgpu_bo_size(bo); if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) bo->adev->invisible_pin_size -= amdgpu_bo_size(bo); - } else { + } else if (bo->tbo.mem.mem_type == TTM_PL_TT) { bo->adev->gart_pin_size -= amdgpu_bo_size(bo); } -- cgit v1.1 From e9d035eca476cc6ee395d55adf8b64c7150201e2 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 7 Sep 2016 20:55:42 +0800 Subject: drm/amdgpu: use error label to handle exceptional case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use error label to decrease global item unref and make codes more readable. Reviewed-by: Christian König Signed-off-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 73298fa..b50535c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -89,10 +89,10 @@ int amdgpu_ttm_global_init(struct amdgpu_device *adev) global_ref->init = &amdgpu_ttm_mem_global_init; global_ref->release = &amdgpu_ttm_mem_global_release; r = drm_global_item_ref(global_ref); - if (r != 0) { + if (r) { DRM_ERROR("Failed setting up TTM memory accounting " "subsystem.\n"); - return r; + goto error_mem; } adev->mman.bo_global_ref.mem_glob = @@ -103,26 +103,30 @@ int amdgpu_ttm_global_init(struct amdgpu_device *adev) global_ref->init = &ttm_bo_global_init; global_ref->release = &ttm_bo_global_release; r = drm_global_item_ref(global_ref); - if (r != 0) { + if (r) { DRM_ERROR("Failed setting up TTM BO subsystem.\n"); - drm_global_item_unref(&adev->mman.mem_global_ref); - return r; + goto error_bo; } ring = adev->mman.buffer_funcs_ring; rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_KERNEL]; r = amd_sched_entity_init(&ring->sched, &adev->mman.entity, rq, amdgpu_sched_jobs); - if (r != 0) { + if (r) { DRM_ERROR("Failed setting up TTM BO move run queue.\n"); - drm_global_item_unref(&adev->mman.mem_global_ref); - drm_global_item_unref(&adev->mman.bo_global_ref.ref); - return r; + goto error_entity; } adev->mman.mem_global_referenced = true; return 0; + +error_entity: + drm_global_item_unref(&adev->mman.bo_global_ref.ref); +error_bo: + drm_global_item_unref(&adev->mman.mem_global_ref); +error_mem: + return r; } static void amdgpu_ttm_global_fini(struct amdgpu_device *adev) -- cgit v1.1 From c63e2d4c65e8e57b2c870ea46af9ac30d79d426b Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 9 Sep 2016 19:01:10 +0800 Subject: drm/amd/powerplay: mark symbols static where possible on tonga/iceland. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c | 6 +++--- drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c index 8a7ada5..00e2e9a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c @@ -781,7 +781,7 @@ static int iceland_upload_firmware(struct pp_hwmgr *hwmgr) * @param hwmgr the address of the powerplay hardware manager. * @return always 0 */ -int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) +static int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) { iceland_hwmgr *data = (iceland_hwmgr *)(hwmgr->backend); @@ -2606,7 +2606,7 @@ static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr) * @param pInput the pointer to input data (PowerState) * @return always 0 */ -int iceland_init_smc_table(struct pp_hwmgr *hwmgr) +static int iceland_init_smc_table(struct pp_hwmgr *hwmgr) { int result; iceland_hwmgr *data = (iceland_hwmgr *)(hwmgr->backend); @@ -4629,7 +4629,7 @@ static int iceland_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input) return 0; } -int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr) +static int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr) { iceland_hwmgr *data = (iceland_hwmgr *)(hwmgr->backend); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c index 5616ec5..50d0209 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -231,7 +231,7 @@ uint8_t tonga_get_voltage_index(phm_ppt_v1_voltage_lookup_table *look_up_table, return i-1; } -bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr) +static bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr) { /* * We return the status of Voltage Control instead of checking SCLK/MCLK DPM @@ -336,7 +336,7 @@ void tonga_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) } -int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) +static int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) { tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); @@ -773,7 +773,7 @@ int tonga_set_boot_state(struct pp_hwmgr *hwmgr) * @param hwmgr the address of the powerplay hardware manager. * @return always 0 */ -int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) +static int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) { tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); struct tonga_smumgr *tonga_smu = (struct tonga_smumgr *)(hwmgr->smumgr->backend); @@ -2896,7 +2896,7 @@ int tonga_populate_smc_initial_state(struct pp_hwmgr *hwmgr, * @param pInput the pointer to input data (PowerState) * @return always 0 */ -int tonga_init_smc_table(struct pp_hwmgr *hwmgr) +static int tonga_init_smc_table(struct pp_hwmgr *hwmgr) { int result; tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); @@ -3991,7 +3991,7 @@ int tonga_set_valid_flag(phw_tonga_mc_reg_table *table) return 0; } -int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +static int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) { int result; tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); -- cgit v1.1 From 6429fb6685d72356cfacbbdb748c977d2e63a709 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 16 Aug 2016 18:13:57 +0800 Subject: drm/amd/powerplay: add feature flags in hwmgr to enable/disable special features. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 1456565..a4d490a 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -70,6 +70,19 @@ enum PP_Result { #define PCIE_PERF_REQ_GEN2 3 #define PCIE_PERF_REQ_GEN3 4 +enum PP_FEATURE_MASK { + PP_SCLK_DPM_MASK = 0x1, + PP_MCLK_DPM_MASK = 0x2, + PP_PCIE_DPM_MASK = 0x4, + PP_SCLK_DEEP_SLEEP_MASK = 0x8, + PP_POWER_CONTAINMENT_MASK = 0x10, + PP_UVD_HANDSHAKE_MASK = 0x20, + PP_SMC_VOLTAGE_CONTROL_MASK = 0x40, + PP_VBI_TIME_SUPPORT_MASK = 0x80, + PP_ULV_MASK = 0x100, + PP_ENABLE_GFX_CG_THRU_SMU = 0x200 +}; + enum PHM_BackEnd_Magic { PHM_Dummy_Magic = 0xAA5555AA, PHM_RV770_Magic = 0xDCBAABCD, @@ -635,6 +648,7 @@ struct pp_hwmgr { struct pp_power_state *boot_ps; struct pp_power_state *uvd_ps; struct amd_pp_display_configuration display_config; + uint32_t feature_mask; }; -- cgit v1.1 From 5141e9d2f7811e1ba714e069c4f12b64de67030f Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 6 Sep 2016 16:34:37 +0800 Subject: drm/amd/powerplay: add module parameter to mask pp features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2e8f469..e69fd33 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -95,6 +95,7 @@ extern unsigned amdgpu_pg_mask; extern char *amdgpu_disable_cu; extern int amdgpu_sclk_deep_sleep_en; extern char *amdgpu_virtual_display; +extern unsigned amdgpu_pp_feature_mask; #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 #define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index ca3d87a..c96ae10 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -95,6 +95,7 @@ unsigned amdgpu_cg_mask = 0xffffffff; unsigned amdgpu_pg_mask = 0xffffffff; char *amdgpu_disable_cu = NULL; char *amdgpu_virtual_display = NULL; +unsigned amdgpu_pp_feature_mask = 0xffffffff; MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); @@ -177,6 +178,9 @@ module_param_named(powerplay, amdgpu_powerplay, int, 0444); MODULE_PARM_DESC(powercontainment, "Power Containment (1 = enable (default), 0 = disable)"); module_param_named(powercontainment, amdgpu_powercontainment, int, 0444); + +MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))"); +module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, int, 0444); #endif MODULE_PARM_DESC(sclkdeepsleep, "SCLK Deep Sleep (1 = enable (default), 0 = disable)"); -- cgit v1.1 From 9597f40365760873bf7fc399bb5c40c3d9949359 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 6 Sep 2016 16:35:01 +0800 Subject: drm/amd/powerplay: initialize platform caps in hwmgr_init. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c | 34 ------- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 109 ++++++++++++++++----- .../gpu/drm/amd/powerplay/inc/hardwaremanager.h | 1 - drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 + 4 files changed, 87 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c index 789f98a..14f8c1f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c @@ -24,8 +24,6 @@ #include "hwmgr.h" #include "hardwaremanager.h" #include "power_state.h" -#include "pp_acpi.h" -#include "amd_acpi.h" #include "pp_debug.h" #define PHM_FUNC_CHECK(hw) \ @@ -34,38 +32,6 @@ return -EINVAL; \ } while (0) -void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr) -{ - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableVoltageTransition); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableEngineTransition); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMemoryTransition); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGClockGating); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGCGTSSM); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLSClockGating); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Force3DClockSupport); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLightSleep); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMCLS); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisablePowerGating); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableDPM); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableSMUUVDHandshake); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalAutoThrottling); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_NoOD5Support); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UserMaxClockForMultiDisplays); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VpuRecoveryInProgress); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM); - - if (acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST) && - acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION)) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); -} - bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr) { return hwmgr->block_hw_access; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 9794f10..1aacda7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -32,6 +32,8 @@ #include "pp_debug.h" #include "ppatomctrl.h" #include "ppsmc.h" +#include "pp_acpi.h" +#include "amd_acpi.h" #define VOLTAGE_SCALE 4 @@ -41,24 +43,8 @@ extern int fiji_hwmgr_init(struct pp_hwmgr *hwmgr); extern int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr); extern int iceland_hwmgr_init(struct pp_hwmgr *hwmgr); -static int hwmgr_set_features_platform_caps(struct pp_hwmgr *hwmgr) -{ - if (amdgpu_sclk_deep_sleep_en) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep); - - if (amdgpu_powercontainment) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - - return 0; -} +static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr); +static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr); int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) { @@ -79,7 +65,8 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; hwmgr->power_source = PP_PowerSource_AC; - hwmgr_set_features_platform_caps(hwmgr); + hwmgr_init_default_caps(hwmgr); + hwmgr_set_user_specify_caps(hwmgr); switch (hwmgr->chip_family) { case AMDGPU_FAMILY_CZ: @@ -108,8 +95,6 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) return -EINVAL; } - phm_init_dynamic_caps(hwmgr); - return 0; } @@ -217,8 +202,6 @@ int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, } - - /** * Returns once the part of the register indicated by the mask has * reached the given value.The indirect space is described by giving @@ -613,3 +596,83 @@ void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr) printk(KERN_ERR "DAL requested level can not" " found a available voltage in VDDC DPM Table \n"); } + +void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr) +{ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableVoltageTransition); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableEngineTransition); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMemoryTransition); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGClockGating); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGCGTSSM); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLSClockGating); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Force3DClockSupport); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLightSleep); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMCLS); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisablePowerGating); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableDPM); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableSMUUVDHandshake); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalAutoThrottling); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_NoOD5Support); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UserMaxClockForMultiDisplays); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VpuRecoveryInProgress); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM); + + if (acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST) && + acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPatchPowerState); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableSMU7ThermalManagement); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPowerManagement); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UnTabledHardwareInterface); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMC); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicUVDState); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM); + + return; +} + +int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr) +{ + if (amdgpu_sclk_deep_sleep_en) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep); + + if (amdgpu_powercontainment) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + + hwmgr->feature_mask = amdgpu_pp_feature_mask; + + return 0; +} + diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h index 962cb53..d449583 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h @@ -341,7 +341,6 @@ extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr); extern int phm_setup_asic(struct pp_hwmgr *hwmgr); extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); extern int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr); -extern void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr); extern bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr); extern int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block); extern int phm_set_power_state(struct pp_hwmgr *hwmgr, diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index a4d490a..2a060f6 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -40,6 +40,7 @@ struct pp_atomctrl_voltage_table; extern int amdgpu_powercontainment; extern int amdgpu_sclk_deep_sleep_en; +extern unsigned amdgpu_pp_feature_mask; enum DISPLAY_GAP { DISPLAY_GAP_VBLANK_OR_WM = 0, /* Wait for vblank or MCHG watermark. */ -- cgit v1.1 From 8bea2527faa13dad21e4307af77b292a8e4ded2f Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 12 Sep 2016 15:17:37 +0800 Subject: drm/amd/powerplay: add helper function to get voltage id in votage table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 21 +++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 1aacda7..cb417c6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -443,6 +443,27 @@ uint8_t phm_get_voltage_index( return i - 1; } +uint8_t phm_get_voltage_id(pp_atomctrl_voltage_table *voltage_table, + uint32_t voltage) +{ + uint8_t count = (uint8_t) (voltage_table->count); + uint8_t i = 0; + + PP_ASSERT_WITH_CODE((NULL != voltage_table), + "Voltage Table empty.", return 0;); + PP_ASSERT_WITH_CODE((0 != count), + "Voltage Table empty.", return 0;); + + for (i = 0; i < count; i++) { + /* find first voltage bigger than requested */ + if (voltage_table->entries[i].value >= voltage) + return i; + } + + /* voltage is bigger than max voltage in the table */ + return i - 1; +} + uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci) { uint32_t i; diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 2a060f6..aa4f5f3 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -685,6 +685,8 @@ extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, st extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max); extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes); extern int32_t phm_get_dpm_level_enable_mask_value(void *table); +extern uint8_t phm_get_voltage_id(struct pp_atomctrl_voltage_table *voltage_table, + uint32_t voltage); extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage); extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci); extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level); @@ -709,8 +711,6 @@ extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr); PHM_FIELD_SHIFT(reg, field)) - - /* Operations on named fields. */ #define PHM_READ_FIELD(device, reg, field) \ -- cgit v1.1 From 026c881046a352c9ac4f68bb84a5f6c9bc4a7d73 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 16 Aug 2016 21:38:19 +0800 Subject: drm/amd/powerplay: wrap get evv voltage functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Deucher Acked-by: Christian König Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index cb417c6..ca63471 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -697,3 +697,20 @@ int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr) return 0; } +int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint32_t sclk, uint16_t id, uint16_t *voltage) +{ + uint32_t vol; + int ret = 0; + + if (hwmgr->chip_id < CHIP_POLARIS10) { + atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage); + if (*voltage >= 2000 || *voltage == 0) + *voltage = 1150; + } else { + ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol); + *voltage = (uint16_t)vol/100; + } + return ret; +} + diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index aa4f5f3..88a63b7 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -697,6 +697,9 @@ extern int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr); extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask); extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr); +extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint32_t sclk, uint16_t id, uint16_t *voltage); + #define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU #define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT -- cgit v1.1 From 00d57e6d6cb4a2b2c886935a9e1a1a2bcf26a85a Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 11 Aug 2016 19:36:54 +0800 Subject: drm/amd/powerplay: move smu related variable definitions to smumgr. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Deucher Acked-by: Christian König Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h | 5 +---- .../drm/amd/powerplay/hwmgr/polaris10_powertune.h | 13 ------------- .../gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h | 20 ++++++++++++++++++++ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h index 33c3394..378ab34 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h @@ -30,6 +30,7 @@ #include "ppatomctrl.h" #include "polaris10_ppsmc.h" #include "polaris10_powertune.h" +#include "polaris10_smumgr.h" #define POLARIS10_MAX_HARDWARE_POWERLEVELS 2 @@ -165,10 +166,6 @@ struct polaris10_pcie_perf_range { uint16_t max; uint16_t min; }; -struct polaris10_range_table { - uint32_t trans_lower_frequency; /* in 10khz */ - uint32_t trans_upper_frequency; -}; struct polaris10_hwmgr { struct polaris10_dpm_table dpm_table; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h index bc78e28..329119d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h @@ -66,19 +66,6 @@ struct polaris10_pt_config_reg { enum polaris10_pt_config_reg_type type; }; -struct polaris10_pt_defaults { - uint8_t SviLoadLineEn; - uint8_t SviLoadLineVddC; - uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; - uint8_t TDC_MAWt; - uint8_t TdcWaterfallCtl; - uint8_t DTEAmbientTempBase; - - uint32_t DisplayCac; - uint32_t BAPM_TEMP_GRADIENT; - uint16_t BAPMTI_R[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; - uint16_t BAPMTI_RC[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; -}; void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr); int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h index e5377ae..7c2445f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h @@ -26,12 +26,27 @@ #include #include +#include "smu74.h" struct polaris10_avfs { enum AVFS_BTC_STATUS avfs_btc_status; uint32_t avfs_btc_param; }; +struct polaris10_pt_defaults { + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + uint8_t TdcWaterfallCtl; + uint8_t DTEAmbientTempBase; + + uint32_t DisplayCac; + uint32_t BAPM_TEMP_GRADIENT; + uint16_t BAPMTI_R[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; + uint16_t BAPMTI_RC[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; +}; + struct polaris10_buffer_entry { uint32_t data_size; uint32_t mc_addr_low; @@ -40,6 +55,11 @@ struct polaris10_buffer_entry { unsigned long handle; }; +struct polaris10_range_table { + uint32_t trans_lower_frequency; /* in 10khz */ + uint32_t trans_upper_frequency; +}; + struct polaris10_smumgr { uint8_t *header; uint8_t *mec_image; -- cgit v1.1 From 41698abb4d418b83b4d9fdae1172e00b91e46b54 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 11 Aug 2016 17:56:56 +0800 Subject: drm/amd/powerplay: delete duplicated function and definition. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Deucher Acked-by: Christian König Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 7 +++++-- drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c | 8 -------- drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c | 5 ----- drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c | 9 --------- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 4 ++++ drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c | 1 - drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 1 + 7 files changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index ca63471..2d72e06 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -35,8 +35,6 @@ #include "pp_acpi.h" #include "amd_acpi.h" -#define VOLTAGE_SCALE 4 - extern int cz_hwmgr_init(struct pp_hwmgr *hwmgr); extern int tonga_hwmgr_init(struct pp_hwmgr *hwmgr); extern int fiji_hwmgr_init(struct pp_hwmgr *hwmgr); @@ -46,6 +44,11 @@ extern int iceland_hwmgr_init(struct pp_hwmgr *hwmgr); static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr); static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr); +uint8_t convert_to_vid(uint16_t vddc) +{ + return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); +} + int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) { struct pp_hwmgr *hwmgr; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c index 00e2e9a..5abe433 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c @@ -1355,14 +1355,6 @@ static int iceland_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, return 0; } -/** - * Convert a voltage value in mv unit to VID number required by SMU firmware - */ -static uint8_t convert_to_vid(uint16_t vddc) -{ - return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); -} - int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) { int i; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c index 9831871..d7c52be 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c @@ -736,11 +736,6 @@ int polaris10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) return 0; } -uint8_t convert_to_vid(uint16_t vddc) -{ - return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); -} - /** * Mvdd table preparation for SMC. * diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c index 50d0209..cf58f22 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -1317,15 +1317,6 @@ static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, } /** - * Convert a voltage value in mv unit to VID number required by SMU firmware - */ -static uint8_t convert_to_vid(uint16_t vddc) -{ - return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); -} - - -/** * Preparation of vddc and vddgfx CAC tables for SMC. * * @param hwmgr the address of the hardware manager diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 88a63b7..7caf8d0 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -42,6 +42,10 @@ extern int amdgpu_powercontainment; extern int amdgpu_sclk_deep_sleep_en; extern unsigned amdgpu_pp_feature_mask; +#define VOLTAGE_SCALE 4 + +uint8_t convert_to_vid(uint16_t vddc); + enum DISPLAY_GAP { DISPLAY_GAP_VBLANK_OR_WM = 0, /* Wait for vblank or MCHG watermark. */ DISPLAY_GAP_VBLANK = 1, /* Wait for vblank. */ diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index 704ff4c..8047ad2 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -40,7 +40,6 @@ #include "cgs_common.h" #define POLARIS10_SMC_SIZE 0x20000 -#define VOLTAGE_SCALE 4 /* Microcode file is stored in this buffer */ #define BUFFER_SIZE 80000 diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index 83d8f7e..bbeb786 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -29,6 +29,7 @@ #include "cgs_common.h" #include "linux/delay.h" + int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle) { struct pp_smumgr *smumgr; -- cgit v1.1 From efdf7a93195a712baff7aa077ae5e4542a9af2f9 Mon Sep 17 00:00:00 2001 From: Edward O'Callaghan Date: Sun, 4 Sep 2016 12:36:19 +1000 Subject: amd/powerplay: use kmemdup instead of kmalloc + memcpy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Save a few clocks by replacing calls to kmalloc followed by memcpy with a single call to kmemdup. Reviewed-by: Christian König Signed-off-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 3e7235f..b1d1940 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -764,15 +764,12 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) PP_CHECK_HW(hwmgr); if (!hwmgr->hardcode_pp_table) { - hwmgr->hardcode_pp_table = - kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL); + hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table, + hwmgr->soft_pp_table_size, + GFP_KERNEL); if (!hwmgr->hardcode_pp_table) return -ENOMEM; - - /* to avoid powerplay crash when hardcode pptable is empty */ - memcpy(hwmgr->hardcode_pp_table, hwmgr->soft_pp_table, - hwmgr->soft_pp_table_size); } memcpy(hwmgr->hardcode_pp_table, buf, size); -- cgit v1.1 From 9ca91fdd13ad877f4a303f6fb971aecbea4b67ae Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sat, 3 Sep 2016 14:01:41 +0800 Subject: drm/amdgpu: add missing header dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get a few warnings when building kernel with W=1: drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c:113:6: warning: no previous prototype for 'amdgpu_pll_compute' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/cz_smc.c:38:10: warning: no previous prototype for 'cz_get_argument' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/cz_smc.c:302:5: warning: no previous prototype for 'cz_smu_start' [-Wmissing-prototypes] .... In fact, these functions are declared in drivers/gpu/drm/amd/amdgpu/atombios_i2c.h drivers/gpu/drm/amd/amdgpu/amdgpu_pll.h drivers/gpu/drm/amd/amdgpu/cz_dpm.h drivers/gpu/drm/amd/amdgpu/vi_dpm.h. So this patch adds missing header dependencies. Reviewed-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c | 1 + drivers/gpu/drm/amd/amdgpu/atombios_i2c.c | 1 + drivers/gpu/drm/amd/amdgpu/cz_smc.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c index d153149..8e67c12 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pll.c @@ -25,6 +25,7 @@ #include "amdgpu.h" #include "atom.h" #include "atombios_encoders.h" +#include "amdgpu_pll.h" #include #include diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c b/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c index bc56c8a..b374653 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c @@ -27,6 +27,7 @@ #include "amdgpu.h" #include "atom.h" #include "amdgpu_atombios.h" +#include "atombios_i2c.h" #define TARGET_HW_I2C_CLOCK 50 diff --git a/drivers/gpu/drm/amd/amdgpu/cz_smc.c b/drivers/gpu/drm/amd/amdgpu/cz_smc.c index ac7fee7..69ac373c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_smc.c @@ -29,6 +29,8 @@ #include "cz_smumgr.h" #include "smu_ucode_xfer_cz.h" #include "amdgpu_ucode.h" +#include "cz_dpm.h" +#include "vi_dpm.h" #include "smu/smu_8_0_d.h" #include "smu/smu_8_0_sh_mask.h" -- cgit v1.1 From 761c2e82054fda665bcdec95b9daf3d468c5fd5b Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Sat, 3 Sep 2016 13:57:14 +0800 Subject: drm/amdgpu: mark symbols static where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get a few warnings when building kernel with W=1: drivers/gpu/drm/amd/amdgpu/cz_smc.c:51:5: warning: no previous prototype for 'cz_send_msg_to_smc_async' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/cz_smc.c:143:5: warning: no previous prototype for 'cz_write_smc_sram_dword' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/iceland_smc.c:124:6: warning: no previous prototype for 'iceland_start_smc' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c:3926:6: warning: no previous prototype for 'gfx_v8_0_rlc_stop' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/amdgpu_job.c:94:6: warning: no previous prototype for 'amdgpu_job_free_cb' [-Wmissing-prototypes] .... In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. So this patch marks these functions with 'static'. Reviewed-by: Christian König Acked-by: Huang Rui Reviewed-by: Edward O'Callaghan Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 +- drivers/gpu/drm/amd/amdgpu/cz_smc.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/iceland_smc.c | 8 ++++---- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 040993c..f1c53a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -616,7 +616,7 @@ static int amdgpu_cgs_irq_put(struct cgs_device *cgs_device, unsigned src_id, un return amdgpu_irq_put(adev, adev->irq.sources[src_id], type); } -int amdgpu_cgs_set_clockgating_state(struct cgs_device *cgs_device, +static int amdgpu_cgs_set_clockgating_state(struct cgs_device *cgs_device, enum amd_ip_block_type block_type, enum amd_clockgating_state state) { @@ -637,7 +637,7 @@ int amdgpu_cgs_set_clockgating_state(struct cgs_device *cgs_device, return r; } -int amdgpu_cgs_set_powergating_state(struct cgs_device *cgs_device, +static int amdgpu_cgs_set_powergating_state(struct cgs_device *cgs_device, enum amd_ip_block_type block_type, enum amd_powergating_state state) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index f7dccb1..9480be4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -431,7 +431,7 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, return false; } -int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, +static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, struct list_head *validated) { struct amdgpu_bo_list_entry *lobj; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index ac8d401..8c58079 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -91,7 +91,7 @@ void amdgpu_job_free_resources(struct amdgpu_job *job) amdgpu_ib_free(job->adev, &job->ibs[i], f); } -void amdgpu_job_free_cb(struct amd_sched_job *s_job) +static void amdgpu_job_free_cb(struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base); diff --git a/drivers/gpu/drm/amd/amdgpu/cz_smc.c b/drivers/gpu/drm/amd/amdgpu/cz_smc.c index 69ac373c4..95887e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_smc.c @@ -50,7 +50,7 @@ static struct cz_smu_private_data *cz_smu_get_priv(struct amdgpu_device *adev) return priv; } -int cz_send_msg_to_smc_async(struct amdgpu_device *adev, u16 msg) +static int cz_send_msg_to_smc_async(struct amdgpu_device *adev, u16 msg) { int i; u32 content = 0, tmp; @@ -142,7 +142,7 @@ int cz_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, return 0; } -int cz_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, +static int cz_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, u32 value, u32 limit) { int ret; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index dca8b36..e2ed71d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3862,7 +3862,7 @@ static void gfx_v8_0_init_pg(struct amdgpu_device *adev) } } -void gfx_v8_0_rlc_stop(struct amdgpu_device *adev) +static void gfx_v8_0_rlc_stop(struct amdgpu_device *adev) { WREG32_FIELD(RLC_CNTL, RLC_ENABLE_F32, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_smc.c b/drivers/gpu/drm/amd/amdgpu/iceland_smc.c index 2118399..ef7c27d 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_smc.c @@ -121,7 +121,7 @@ out: return result; } -void iceland_start_smc(struct amdgpu_device *adev) +static void iceland_start_smc(struct amdgpu_device *adev) { uint32_t val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL); @@ -129,7 +129,7 @@ void iceland_start_smc(struct amdgpu_device *adev) WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val); } -void iceland_reset_smc(struct amdgpu_device *adev) +static void iceland_reset_smc(struct amdgpu_device *adev) { uint32_t val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL); @@ -145,7 +145,7 @@ static int iceland_program_jump_on_start(struct amdgpu_device *adev) return 0; } -void iceland_stop_smc_clock(struct amdgpu_device *adev) +static void iceland_stop_smc_clock(struct amdgpu_device *adev) { uint32_t val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); @@ -153,7 +153,7 @@ void iceland_stop_smc_clock(struct amdgpu_device *adev) WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, val); } -void iceland_start_smc_clock(struct amdgpu_device *adev) +static void iceland_start_smc_clock(struct amdgpu_device *adev) { uint32_t val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); -- cgit v1.1 From 812a4654bb1fcada740cd2c1e101fc3f98fb891a Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Tue, 6 Sep 2016 14:16:28 +0800 Subject: drm/amd/powerplay/fiji: mark symbols static where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get a few warnings when building kernel with W=1: drivers/gpu/drm/amd/amdgpu/../powerplay/hwmgr/fiji_hwmgr.c:1633:9: warning: no previous prototype for 'fiji_get_voltage_index' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/../powerplay/hwmgr/fiji_hwmgr.c:5412:5: warning: no previous prototype for 'fiji_check_states_equal' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/../powerplay/hwmgr/fiji_thermal.c:424:5: warning: no previous prototype for 'tf_fiji_thermal_setup_fan_table' [-Wmissing-prototypes] .... In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. So this patch marks these functions with 'static'. Reviewed-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c | 33 +++++++++++++--------- drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c | 6 ++-- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c index e93492b..560d424 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c @@ -113,7 +113,7 @@ static const uint8_t fiji_clock_stretch_amount_conversion[2][6] = static const unsigned long PhwFiji_Magic = (unsigned long)(PHM_VIslands_Magic); -struct fiji_power_state *cast_phw_fiji_power_state( +static struct fiji_power_state *cast_phw_fiji_power_state( struct pp_hw_power_state *hw_ps) { PP_ASSERT_WITH_CODE((PhwFiji_Magic == hw_ps->magic), @@ -123,7 +123,8 @@ struct fiji_power_state *cast_phw_fiji_power_state( return (struct fiji_power_state *)hw_ps; } -const struct fiji_power_state *cast_const_phw_fiji_power_state( +static const struct +fiji_power_state *cast_const_phw_fiji_power_state( const struct pp_hw_power_state *hw_ps) { PP_ASSERT_WITH_CODE((PhwFiji_Magic == hw_ps->magic), @@ -1627,7 +1628,7 @@ static int fiji_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) * @param voltage - voltage to look for * @return 0 on success */ -uint8_t fiji_get_voltage_index( +static uint8_t fiji_get_voltage_index( struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage) { uint8_t count = (uint8_t) (lookup_table->count); @@ -1691,7 +1692,7 @@ static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr, * @return always 0 */ -int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, +static int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, struct SMU73_Discrete_DpmTable *table) { int result; @@ -2302,7 +2303,7 @@ static int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) * @param mclk the MCLK value to be used in the decision if MVDD should be high or low. * @param voltage the SMC VOLTAGE structure to be populated */ -int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr, +static int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, SMIO_Pattern *smio_pat) { const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); @@ -4623,7 +4624,7 @@ static int fiji_generate_dpm_level_enable_mask( return 0; } -int fiji_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +static int fiji_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) { return smum_send_msg_to_smc(hwmgr->smumgr, enable ? (PPSMC_Msg)PPSMC_MSG_UVDDPM_Enable : @@ -4637,14 +4638,14 @@ int fiji_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) PPSMC_MSG_VCEDPM_Disable); } -int fiji_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable) +static int fiji_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable) { return smum_send_msg_to_smc(hwmgr->smumgr, enable? PPSMC_MSG_SAMUDPM_Enable : PPSMC_MSG_SAMUDPM_Disable); } -int fiji_enable_disable_acp_dpm(struct pp_hwmgr *hwmgr, bool enable) +static int fiji_enable_disable_acp_dpm(struct pp_hwmgr *hwmgr, bool enable) { return smum_send_msg_to_smc(hwmgr->smumgr, enable? PPSMC_MSG_ACPDPM_Enable : @@ -4881,7 +4882,7 @@ static void fiji_apply_dal_minimum_voltage_request(struct pp_hwmgr *hwmgr) return; } -int fiji_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr) +static int fiji_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr) { int result; struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); @@ -5157,7 +5158,7 @@ static int fiji_program_display_gap(struct pp_hwmgr *hwmgr) return 0; } -int fiji_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +static int fiji_display_configuration_changed_task(struct pp_hwmgr *hwmgr) { return fiji_program_display_gap(hwmgr); } @@ -5188,7 +5189,7 @@ static int fiji_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm); } -int fiji_dpm_set_interrupt_state(void *private_data, +static int fiji_dpm_set_interrupt_state(void *private_data, unsigned src_id, unsigned type, int enabled) { @@ -5236,7 +5237,7 @@ int fiji_dpm_set_interrupt_state(void *private_data, return 0; } -int fiji_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr, +static int fiji_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *thermal_interrupt_info) { int result; @@ -5406,7 +5407,10 @@ static inline bool fiji_are_power_levels_equal(const struct fiji_performance_lev (pl1->pcie_lane == pl2->pcie_lane)); } -int fiji_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal) +static int +fiji_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, bool *equal) { const struct fiji_power_state *psa = cast_const_phw_fiji_power_state(pstate1); const struct fiji_power_state *psb = cast_const_phw_fiji_power_state(pstate2); @@ -5438,7 +5442,8 @@ int fiji_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_sta return 0; } -bool fiji_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +static bool +fiji_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) { struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); bool is_update_required = false; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c index 92976b6..7f431e7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c @@ -152,7 +152,7 @@ int fiji_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) return 0; } -int fiji_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +static int fiji_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) { int result; @@ -421,7 +421,7 @@ int fiji_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) * @param Result the last failure code * @return result from set temperature range routine */ -int tf_fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, +static int tf_fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) { struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); @@ -533,7 +533,7 @@ int tf_fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, * @param Result the last failure code * @return result from set temperature range routine */ -int tf_fiji_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, +static int tf_fiji_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) { /* If the fantable setup has failed we could have disabled -- cgit v1.1 From 5cd92f86f00f8d7823bd0794f7810222ce5f6d68 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Tue, 6 Sep 2016 15:17:48 +0800 Subject: drm/amd/powerplay/polaris10: mark symbols static where possible We get a few warnings when building kernel with W=1: drivers/gpu/drm/amd/amdgpu/../powerplay/hwmgr/polaris10_clockpowergating.c:34:5: warning: no previous prototype for 'polaris10_phm_powerup_uvd' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/../powerplay/hwmgr/polaris10_thermal.c:428:5: warning: no previous prototype for 'tf_polaris10_thermal_setup_fan_table' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/../powerplay/hwmgr/polaris10_hwmgr.c:125:31: warning: no previous prototype for 'cast_phw_polaris10_power_state' [-Wmissing-prototypes] .... In fact, these functions are only used in the file in which they are declared and don't need a declaration, but can be made static. So this patch marks these functions with 'static'. Reviewed-by: Alex Deucher Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- .../powerplay/hwmgr/polaris10_clockpowergating.c | 10 ++-- .../gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c | 63 ++++++++++++---------- .../drm/amd/powerplay/hwmgr/polaris10_thermal.c | 6 +-- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c index b5edb51..7e405b0 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c @@ -31,7 +31,7 @@ int polaris10_phm_powerdown_uvd(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_phm_powerup_uvd(struct pp_hwmgr *hwmgr) +static int polaris10_phm_powerup_uvd(struct pp_hwmgr *hwmgr) { if (phm_cf_want_uvd_power_gating(hwmgr)) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, @@ -47,7 +47,7 @@ int polaris10_phm_powerup_uvd(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_phm_powerdown_vce(struct pp_hwmgr *hwmgr) +static int polaris10_phm_powerdown_vce(struct pp_hwmgr *hwmgr) { if (phm_cf_want_vce_power_gating(hwmgr)) return smum_send_msg_to_smc(hwmgr->smumgr, @@ -55,7 +55,7 @@ int polaris10_phm_powerdown_vce(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_phm_powerup_vce(struct pp_hwmgr *hwmgr) +static int polaris10_phm_powerup_vce(struct pp_hwmgr *hwmgr) { if (phm_cf_want_vce_power_gating(hwmgr)) return smum_send_msg_to_smc(hwmgr->smumgr, @@ -63,7 +63,7 @@ int polaris10_phm_powerup_vce(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_phm_powerdown_samu(struct pp_hwmgr *hwmgr) +static int polaris10_phm_powerdown_samu(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SamuPowerGating)) @@ -72,7 +72,7 @@ int polaris10_phm_powerdown_samu(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_phm_powerup_samu(struct pp_hwmgr *hwmgr) +static int polaris10_phm_powerup_samu(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SamuPowerGating)) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c index d7c52be..8b1eb7f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c @@ -109,7 +109,7 @@ enum DPM_EVENT_SRC { static const unsigned long PhwPolaris10_Magic = (unsigned long)(PHM_VIslands_Magic); -struct polaris10_power_state *cast_phw_polaris10_power_state( +static struct polaris10_power_state *cast_phw_polaris10_power_state( struct pp_hw_power_state *hw_ps) { PP_ASSERT_WITH_CODE((PhwPolaris10_Magic == hw_ps->magic), @@ -119,7 +119,8 @@ struct polaris10_power_state *cast_phw_polaris10_power_state( return (struct polaris10_power_state *)hw_ps; } -const struct polaris10_power_state *cast_const_phw_polaris10_power_state( +static const struct polaris10_power_state * +cast_const_phw_polaris10_power_state( const struct pp_hw_power_state *hw_ps) { PP_ASSERT_WITH_CODE((PhwPolaris10_Magic == hw_ps->magic), @@ -142,7 +143,7 @@ static bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr) * @param hwmgr the address of the powerplay hardware manager. * @return always 0 */ -int phm_get_mc_microcode_version (struct pp_hwmgr *hwmgr) +static int phm_get_mc_microcode_version(struct pp_hwmgr *hwmgr) { cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F); @@ -151,7 +152,7 @@ int phm_get_mc_microcode_version (struct pp_hwmgr *hwmgr) return 0; } -uint16_t phm_get_current_pcie_speed(struct pp_hwmgr *hwmgr) +static uint16_t phm_get_current_pcie_speed(struct pp_hwmgr *hwmgr) { uint32_t speedCntl = 0; @@ -162,7 +163,7 @@ uint16_t phm_get_current_pcie_speed(struct pp_hwmgr *hwmgr) PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE)); } -int phm_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) +static int phm_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) { uint32_t link_width; @@ -182,7 +183,7 @@ int phm_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) * @param pHwMgr the address of the powerplay hardware manager. * @return always PP_Result_OK */ -int polaris10_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) +static int polaris10_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) { PP_ASSERT_WITH_CODE( (hwmgr->smumgr->smumgr_funcs->send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Enable) == 0), @@ -662,7 +663,7 @@ static int polaris10_setup_default_pcie_table(struct pp_hwmgr *hwmgr) * on the power policy or external client requests, * such as UVD request, etc. */ -int polaris10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) +static int polaris10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); struct phm_ppt_v1_information *table_info = @@ -836,7 +837,7 @@ static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr, * @return always 0 */ -int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, +static int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, struct SMU74_Discrete_DpmTable *table) { polaris10_populate_smc_vddci_table(hwmgr, table); @@ -1413,7 +1414,7 @@ static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) * @param mclk the MCLK value to be used in the decision if MVDD should be high or low. * @param voltage the SMC VOLTAGE structure to be populated */ -int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr, +static int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, SMIO_Pattern *smio_pat) { const struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -1927,7 +1928,7 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, } -int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) +static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); SMU74_Discrete_DpmTable *table = &(data->smc_state_table); @@ -2556,7 +2557,7 @@ static int polaris10_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) return polaris10_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); } -int polaris10_pcie_performance_request(struct pp_hwmgr *hwmgr) +static int polaris10_pcie_performance_request(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); data->pcie_performance_request = true; @@ -2564,7 +2565,7 @@ int polaris10_pcie_performance_request(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +static int polaris10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) { int tmp_result, result = 0; tmp_result = (!polaris10_is_dpm_running(hwmgr)) ? 0 : -1; @@ -2745,12 +2746,12 @@ int polaris10_reset_asic_tasks(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +static int polaris10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) { return phm_hwmgr_backend_fini(hwmgr); } -int polaris10_set_features_platform_caps(struct pp_hwmgr *hwmgr) +static int polaris10_set_features_platform_caps(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -3105,7 +3106,7 @@ static int polaris10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_patch_voltage_workaround(struct pp_hwmgr *hwmgr) +static int polaris10_patch_voltage_workaround(struct pp_hwmgr *hwmgr) { struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -3149,7 +3150,7 @@ int polaris10_patch_voltage_workaround(struct pp_hwmgr *hwmgr) } -int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +static int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data; struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; @@ -4359,7 +4360,8 @@ static int polaris10_generate_dpm_level_enable_mask( return 0; } -int polaris10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +static int +polaris10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) { return smum_send_msg_to_smc(hwmgr->smumgr, enable ? PPSMC_MSG_UVDDPM_Enable : @@ -4373,7 +4375,8 @@ int polaris10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) PPSMC_MSG_VCEDPM_Disable); } -int polaris10_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable) +static int +polaris10_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable) { return smum_send_msg_to_smc(hwmgr->smumgr, enable? PPSMC_MSG_SAMUDPM_Enable : @@ -4687,14 +4690,16 @@ static int polaris10_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_ } -int polaris10_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) +static int +polaris10_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) { PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ? 0 : -1; } -int polaris10_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) +static int +polaris10_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) { uint32_t num_active_displays = 0; struct cgs_display_info info = {0}; @@ -4717,7 +4722,7 @@ int polaris10_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwm * @param hwmgr the address of the powerplay hardware manager. * @return always OK */ -int polaris10_program_display_gap(struct pp_hwmgr *hwmgr) +static int polaris10_program_display_gap(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); uint32_t num_active_displays = 0; @@ -4762,7 +4767,7 @@ int polaris10_program_display_gap(struct pp_hwmgr *hwmgr) } -int polaris10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +static int polaris10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) { return polaris10_program_display_gap(hwmgr); } @@ -4786,13 +4791,15 @@ static int polaris10_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_ PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm); } -int polaris10_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr, +static int +polaris10_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *thermal_interrupt_info) { return 0; } -bool polaris10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +static bool polaris10_check_smc_update_required_for_display_configuration( + struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); bool is_update_required = false; @@ -4822,7 +4829,9 @@ static inline bool polaris10_are_power_levels_equal(const struct polaris10_perfo (pl1->pcie_lane == pl2->pcie_lane)); } -int polaris10_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal) +static int polaris10_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, bool *equal) { const struct polaris10_power_state *psa = cast_const_phw_polaris10_power_state(pstate1); const struct polaris10_power_state *psb = cast_const_phw_polaris10_power_state(pstate2); @@ -4853,7 +4862,7 @@ int polaris10_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_powe return 0; } -int polaris10_upload_mc_firmware(struct pp_hwmgr *hwmgr) +static int polaris10_upload_mc_firmware(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -4966,7 +4975,7 @@ static int polaris10_init_sclk_threshold(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_setup_asic_task(struct pp_hwmgr *hwmgr) +static int polaris10_setup_asic_task(struct pp_hwmgr *hwmgr) { int tmp_result, result = 0; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c index b206632..41f835a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c @@ -152,7 +152,7 @@ int polaris10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +static int polaris10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) { int result; @@ -425,7 +425,7 @@ int polaris10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) * @param Result the last failure code * @return result from set temperature range routine */ -int tf_polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, +static int tf_polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -537,7 +537,7 @@ int tf_polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, * @param Result the last failure code * @return result from set temperature range routine */ -int tf_polaris10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, +static int tf_polaris10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) { /* If the fantable setup has failed we could have disabled -- cgit v1.1 From a1047777323cc5da8f59d738708f554937be3193 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 12 Sep 2016 23:46:06 -0400 Subject: drm/amdgpu/si/dpm: make a bunch of things static remnants of the port from radeon. Acked-by: Huang Rui Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index e4f7c10..374d92b 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -91,7 +91,7 @@ union pplib_clock_info { struct _ATOM_PPLIB_SI_CLOCK_INFO si; }; -const u32 r600_utc[R600_PM_NUMBER_OF_TC] = +static const u32 r600_utc[R600_PM_NUMBER_OF_TC] = { R600_UTC_DFLT_00, R600_UTC_DFLT_01, @@ -110,7 +110,7 @@ const u32 r600_utc[R600_PM_NUMBER_OF_TC] = R600_UTC_DFLT_14, }; -const u32 r600_dtc[R600_PM_NUMBER_OF_TC] = +static const u32 r600_dtc[R600_PM_NUMBER_OF_TC] = { R600_DTC_DFLT_00, R600_DTC_DFLT_01, @@ -432,7 +432,7 @@ static const struct si_dte_data dte_data_malta = true }; -struct si_cac_config_reg cac_weights_pitcairn[] = +static const struct si_cac_config_reg cac_weights_pitcairn[] = { { 0x0, 0x0000ffff, 0, 0x8a, SISLANDS_CACCONFIG_CGIND }, { 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, @@ -1188,7 +1188,7 @@ static const struct si_dte_data dte_data_venus_pro = true }; -struct si_cac_config_reg cac_weights_oland[] = +static const struct si_cac_config_reg cac_weights_oland[] = { { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, @@ -1825,10 +1825,10 @@ static const struct si_powertune_data powertune_data_hainan = true }; -struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev); -struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev); -struct ni_power_info *ni_get_pi(struct amdgpu_device *adev); -struct si_ps *si_get_ps(struct amdgpu_ps *rps); +static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev); +static struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev); +static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev); +static struct si_ps *si_get_ps(struct amdgpu_ps *rps); static int si_populate_voltage_value(struct amdgpu_device *adev, const struct atom_voltage_table *table, @@ -1850,8 +1850,6 @@ static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev); static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev); static void si_dpm_set_irq_funcs(struct amdgpu_device *adev); -extern u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg); - static struct si_power_info *si_get_pi(struct amdgpu_device *adev) { struct si_power_info *pi = adev->pm.dpm.priv; @@ -1954,21 +1952,21 @@ static void si_update_dte_from_pl2(struct amdgpu_device *adev, } } -struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev) +static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev) { struct rv7xx_power_info *pi = adev->pm.dpm.priv; return pi; } -struct ni_power_info *ni_get_pi(struct amdgpu_device *adev) +static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev) { struct ni_power_info *pi = adev->pm.dpm.priv; return pi; } -struct si_ps *si_get_ps(struct amdgpu_ps *aps) +static struct si_ps *si_get_ps(struct amdgpu_ps *aps) { struct si_ps *ps = aps->ps_priv; @@ -3257,8 +3255,8 @@ static u32 btc_get_valid_sclk(struct amdgpu_device *adev, max_sclk, requested_sclk); } -void btc_get_max_clock_from_voltage_dependency_table(struct amdgpu_clock_voltage_dependency_table *table, - u32 *max_clock) +static void btc_get_max_clock_from_voltage_dependency_table(struct amdgpu_clock_voltage_dependency_table *table, + u32 *max_clock) { u32 i, clock = 0; @@ -4308,7 +4306,7 @@ static void si_clear_vc(struct amdgpu_device *adev) WREG32(CG_FTV, 0); } -u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock) +static u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock) { u8 mc_para_index; @@ -4321,7 +4319,7 @@ u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock) return mc_para_index; } -u8 si_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode) +static u8 si_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode) { u8 mc_para_index; @@ -7561,7 +7559,7 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev, } static int si_dpm_process_interrupt(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, + struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { bool queue_thermal = false; -- cgit v1.1 From 6861c837e28e1b1300a1b24ddab748c8ee50da3b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 13 Sep 2016 00:06:07 -0400 Subject: drm/amdgpu/si/dpm: fix symbol conflicts with radeon Acked-by: Huang Rui Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 287 +++++++++++++++--------------- drivers/gpu/drm/amd/amdgpu/si_smc.c | 37 ++-- drivers/gpu/drm/amd/amdgpu/sislands_smc.h | 30 ++-- 3 files changed, 181 insertions(+), 173 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 374d92b..e2db4a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -2274,12 +2274,12 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev, smc_table->dpm2Params.SafePowerLimit = cpu_to_be32(si_scale_power_for_smc((near_tdp_limit * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000); - ret = si_copy_bytes_to_smc(adev, - (si_pi->state_table_start + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + - offsetof(PP_SIslands_DPM2Parameters, TDPLimit)), - (u8 *)(&(smc_table->dpm2Params.TDPLimit)), - sizeof(u32) * 3, - si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, + (si_pi->state_table_start + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + + offsetof(PP_SIslands_DPM2Parameters, TDPLimit)), + (u8 *)(&(smc_table->dpm2Params.TDPLimit)), + sizeof(u32) * 3, + si_pi->sram_end); if (ret) return ret; @@ -2293,10 +2293,10 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev, papm_parm->PlatformPowerLimit = 0xffffffff; papm_parm->NearTDPLimitPAPM = 0xffffffff; - ret = si_copy_bytes_to_smc(adev, si_pi->papm_cfg_table_start, - (u8 *)papm_parm, - sizeof(PP_SIslands_PAPMParameters), - si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->papm_cfg_table_start, + (u8 *)papm_parm, + sizeof(PP_SIslands_PAPMParameters), + si_pi->sram_end); if (ret) return ret; } @@ -2322,13 +2322,13 @@ static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev, smc_table->dpm2Params.SafePowerLimit = cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000); - ret = si_copy_bytes_to_smc(adev, - (si_pi->state_table_start + - offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + - offsetof(PP_SIslands_DPM2Parameters, NearTDPLimit)), - (u8 *)(&(smc_table->dpm2Params.NearTDPLimit)), - sizeof(u32) * 2, - si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, + (si_pi->state_table_start + + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + + offsetof(PP_SIslands_DPM2Parameters, NearTDPLimit)), + (u8 *)(&(smc_table->dpm2Params.NearTDPLimit)), + sizeof(u32) * 2, + si_pi->sram_end); if (ret) return ret; } @@ -2538,7 +2538,7 @@ static int si_enable_power_containment(struct amdgpu_device *adev, if (ni_pi->enable_power_containment) { if (enable) { if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) { - smc_result = si_send_msg_to_smc(adev, PPSMC_TDPClampingActive); + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingActive); if (smc_result != PPSMC_Result_OK) { ret = -EINVAL; ni_pi->pc_enabled = false; @@ -2547,7 +2547,7 @@ static int si_enable_power_containment(struct amdgpu_device *adev, } } } else { - smc_result = si_send_msg_to_smc(adev, PPSMC_TDPClampingInactive); + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingInactive); if (smc_result != PPSMC_Result_OK) ret = -EINVAL; ni_pi->pc_enabled = false; @@ -2615,8 +2615,10 @@ static int si_initialize_smc_dte_tables(struct amdgpu_device *adev) dte_tables->Tdep_R[i] = cpu_to_be32(dte_data->tdep_r[i]); } - ret = si_copy_bytes_to_smc(adev, si_pi->dte_table_start, (u8 *)dte_tables, - sizeof(Smc_SIslands_DTE_Configuration), si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->dte_table_start, + (u8 *)dte_tables, + sizeof(Smc_SIslands_DTE_Configuration), + si_pi->sram_end); kfree(dte_tables); return ret; @@ -2806,8 +2808,10 @@ static int si_initialize_smc_cac_tables(struct amdgpu_device *adev) cac_tables->lkge_lut_T0 = cpu_to_be32((u32)t0); cac_tables->lkge_lut_Tstep = cpu_to_be32((u32)t_step); - ret = si_copy_bytes_to_smc(adev, si_pi->cac_table_start, (u8 *)cac_tables, - sizeof(PP_SIslands_CacConfig), si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->cac_table_start, + (u8 *)cac_tables, + sizeof(PP_SIslands_CacConfig), + si_pi->sram_end); if (ret) goto done_free; @@ -2900,12 +2904,12 @@ static int si_enable_smc_cac(struct amdgpu_device *adev, if (enable) { if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) { if (ni_pi->support_cac_long_term_average) { - smc_result = si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgEnable); + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgEnable); if (smc_result != PPSMC_Result_OK) ni_pi->support_cac_long_term_average = false; } - smc_result = si_send_msg_to_smc(adev, PPSMC_MSG_EnableCac); + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableCac); if (smc_result != PPSMC_Result_OK) { ret = -EINVAL; ni_pi->cac_enabled = false; @@ -2914,21 +2918,21 @@ static int si_enable_smc_cac(struct amdgpu_device *adev, } if (si_pi->enable_dte) { - smc_result = si_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE); + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE); if (smc_result != PPSMC_Result_OK) ret = -EINVAL; } } } else if (ni_pi->cac_enabled) { if (si_pi->enable_dte) - smc_result = si_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE); + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE); - smc_result = si_send_msg_to_smc(adev, PPSMC_MSG_DisableCac); + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableCac); ni_pi->cac_enabled = false; if (ni_pi->support_cac_long_term_average) - smc_result = si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgDisable); + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgDisable); } } return ret; @@ -2992,9 +2996,10 @@ static int si_init_smc_spll_table(struct amdgpu_device *adev) if (!ret) - ret = si_copy_bytes_to_smc(adev, si_pi->spll_table_start, - (u8 *)spll_table, sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), - si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->spll_table_start, + (u8 *)spll_table, + sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), + si_pi->sram_end); if (ret) ni_pi->enable_power_containment = false; @@ -3664,9 +3669,9 @@ static int si_read_smc_soft_register(struct amdgpu_device *adev, { struct si_power_info *si_pi = si_get_pi(adev); - return si_read_smc_sram_dword(adev, - si_pi->soft_regs_start + reg_offset, value, - si_pi->sram_end); + return amdgpu_si_read_smc_sram_dword(adev, + si_pi->soft_regs_start + reg_offset, value, + si_pi->sram_end); } #endif @@ -3675,9 +3680,9 @@ static int si_write_smc_soft_register(struct amdgpu_device *adev, { struct si_power_info *si_pi = si_get_pi(adev); - return si_write_smc_sram_dword(adev, - si_pi->soft_regs_start + reg_offset, - value, si_pi->sram_end); + return amdgpu_si_write_smc_sram_dword(adev, + si_pi->soft_regs_start + reg_offset, + value, si_pi->sram_end); } static bool si_is_special_1gb_platform(struct amdgpu_device *adev) @@ -3834,7 +3839,7 @@ static int si_notify_hardware_of_thermal_state(struct amdgpu_device *adev, PPSMC_Result ret; if (thermal_level == 0) { - ret = si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); + ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); if (ret == PPSMC_Result_OK) return 0; else @@ -3853,7 +3858,7 @@ static void si_notify_hardware_vpu_recovery_event(struct amdgpu_device *adev) static int si_notify_hw_of_powersource(struct amdgpu_device *adev, bool ac_power) { if (ac_power) - return (si_send_msg_to_smc(adev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ? + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ? 0 : -EINVAL; return 0; @@ -3864,12 +3869,12 @@ static PPSMC_Result si_send_msg_to_smc_with_parameter(struct amdgpu_device *adev PPSMC_Msg msg, u32 parameter) { WREG32(SMC_SCRATCH0, parameter); - return si_send_msg_to_smc(adev, msg); + return amdgpu_si_send_msg_to_smc(adev, msg); } static int si_restrict_performance_levels_before_switch(struct amdgpu_device *adev) { - if (si_send_msg_to_smc(adev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK) + if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK) return -EINVAL; return (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ? @@ -3911,46 +3916,46 @@ static int si_dpm_force_performance_level(struct amdgpu_device *adev, #if 0 static int si_set_boot_state(struct amdgpu_device *adev) { - return (si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ? + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ? 0 : -EINVAL; } #endif static int si_set_sw_state(struct amdgpu_device *adev) { - return (si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ? + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ? 0 : -EINVAL; } static int si_halt_smc(struct amdgpu_device *adev) { - if (si_send_msg_to_smc(adev, PPSMC_MSG_Halt) != PPSMC_Result_OK) + if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Halt) != PPSMC_Result_OK) return -EINVAL; - return (si_wait_for_smc_inactive(adev) == PPSMC_Result_OK) ? + return (amdgpu_si_wait_for_smc_inactive(adev) == PPSMC_Result_OK) ? 0 : -EINVAL; } static int si_resume_smc(struct amdgpu_device *adev) { - if (si_send_msg_to_smc(adev, PPSMC_FlushDataCache) != PPSMC_Result_OK) + if (amdgpu_si_send_msg_to_smc(adev, PPSMC_FlushDataCache) != PPSMC_Result_OK) return -EINVAL; - return (si_send_msg_to_smc(adev, PPSMC_MSG_Resume) == PPSMC_Result_OK) ? + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Resume) == PPSMC_Result_OK) ? 0 : -EINVAL; } static void si_dpm_start_smc(struct amdgpu_device *adev) { - si_program_jump_on_start(adev); - si_start_smc(adev); - si_smc_clock(adev, true); + amdgpu_si_program_jump_on_start(adev); + amdgpu_si_start_smc(adev); + amdgpu_si_smc_clock(adev, true); } static void si_dpm_stop_smc(struct amdgpu_device *adev) { - si_reset_smc(adev); - si_smc_clock(adev, false); + amdgpu_si_reset_smc(adev); + amdgpu_si_smc_clock(adev, false); } static int si_process_firmware_header(struct amdgpu_device *adev) @@ -3959,82 +3964,82 @@ static int si_process_firmware_header(struct amdgpu_device *adev) u32 tmp; int ret; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_stateTable, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_stateTable, + &tmp, si_pi->sram_end); if (ret) return ret; si_pi->state_table_start = tmp; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_softRegisters, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_softRegisters, + &tmp, si_pi->sram_end); if (ret) return ret; si_pi->soft_regs_start = tmp; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable, + &tmp, si_pi->sram_end); if (ret) return ret; si_pi->mc_reg_table_start = tmp; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_fanTable, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_fanTable, + &tmp, si_pi->sram_end); if (ret) return ret; si_pi->fan_table_start = tmp; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable, + &tmp, si_pi->sram_end); if (ret) return ret; si_pi->arb_table_start = tmp; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable, + &tmp, si_pi->sram_end); if (ret) return ret; si_pi->cac_table_start = tmp; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration, + &tmp, si_pi->sram_end); if (ret) return ret; si_pi->dte_table_start = tmp; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_spllTable, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_spllTable, + &tmp, si_pi->sram_end); if (ret) return ret; si_pi->spll_table_start = tmp; - ret = si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters, + &tmp, si_pi->sram_end); if (ret) return ret; @@ -4112,7 +4117,7 @@ static int si_notify_smc_display_change(struct amdgpu_device *adev, PPSMC_Msg msg = has_display ? PPSMC_MSG_HasDisplay : PPSMC_MSG_NoDisplay; - return (si_send_msg_to_smc(adev, msg) == PPSMC_Result_OK) ? + return (amdgpu_si_send_msg_to_smc(adev, msg) == PPSMC_Result_OK) ? 0 : -EINVAL; } @@ -4365,10 +4370,10 @@ static int si_upload_firmware(struct amdgpu_device *adev) { struct si_power_info *si_pi = si_get_pi(adev); - si_reset_smc(adev); - si_smc_clock(adev, false); + amdgpu_si_reset_smc(adev); + amdgpu_si_smc_clock(adev, false); - return si_load_smc_ucode(adev, si_pi->sram_end); + return amdgpu_si_load_smc_ucode(adev, si_pi->sram_end); } static bool si_validate_phase_shedding_tables(struct amdgpu_device *adev, @@ -4712,14 +4717,16 @@ static int si_init_arb_table_index(struct amdgpu_device *adev) u32 tmp; int ret; - ret = si_read_smc_sram_dword(adev, si_pi->arb_table_start, &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start, + &tmp, si_pi->sram_end); if (ret) return ret; tmp &= 0x00FFFFFF; tmp |= MC_CG_ARB_FREQ_F1 << 24; - return si_write_smc_sram_dword(adev, si_pi->arb_table_start, tmp, si_pi->sram_end); + return amdgpu_si_write_smc_sram_dword(adev, si_pi->arb_table_start, + tmp, si_pi->sram_end); } static int si_initial_switch_from_arb_f0_to_f1(struct amdgpu_device *adev) @@ -4729,7 +4736,7 @@ static int si_initial_switch_from_arb_f0_to_f1(struct amdgpu_device *adev) static int si_reset_to_default(struct amdgpu_device *adev) { - return (si_send_msg_to_smc(adev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ? + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ? 0 : -EINVAL; } @@ -4739,8 +4746,8 @@ static int si_force_switch_to_arb_f0(struct amdgpu_device *adev) u32 tmp; int ret; - ret = si_read_smc_sram_dword(adev, si_pi->arb_table_start, - &tmp, si_pi->sram_end); + ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start, + &tmp, si_pi->sram_end); if (ret) return ret; @@ -4810,13 +4817,13 @@ static int si_do_program_memory_timing_parameters(struct amdgpu_device *adev, ret = si_populate_memory_timing_parameters(adev, &state->performance_levels[i], &arb_regs); if (ret) break; - ret = si_copy_bytes_to_smc(adev, - si_pi->arb_table_start + - offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + - sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i), - (u8 *)&arb_regs, - sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), - si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, + si_pi->arb_table_start + + offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i), + (u8 *)&arb_regs, + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), + si_pi->sram_end); if (ret) break; } @@ -5152,13 +5159,13 @@ static int si_program_ulv_memory_timing_parameters(struct amdgpu_device *adev) si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ulv_volt_change_delay, ulv->volt_change_delay); - ret = si_copy_bytes_to_smc(adev, - si_pi->arb_table_start + - offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + - sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * SISLANDS_ULV_STATE_ARB_INDEX, - (u8 *)&arb_regs, - sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), - si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, + si_pi->arb_table_start + + offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * SISLANDS_ULV_STATE_ARB_INDEX, + (u8 *)&arb_regs, + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), + si_pi->sram_end); return ret; } @@ -5252,9 +5259,9 @@ static int si_init_smc_table(struct amdgpu_device *adev) table->ULVState = table->initialState; } - return si_copy_bytes_to_smc(adev, si_pi->state_table_start, - (u8 *)table, sizeof(SISLANDS_SMC_STATETABLE), - si_pi->sram_end); + return amdgpu_si_copy_bytes_to_smc(adev, si_pi->state_table_start, + (u8 *)table, sizeof(SISLANDS_SMC_STATETABLE), + si_pi->sram_end); } static int si_calculate_sclk_params(struct amdgpu_device *adev, @@ -5616,7 +5623,7 @@ static int si_disable_ulv(struct amdgpu_device *adev) struct si_ulv_param *ulv = &si_pi->ulv; if (ulv->supported) - return (si_send_msg_to_smc(adev, PPSMC_MSG_DisableULV) == PPSMC_Result_OK) ? + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableULV) == PPSMC_Result_OK) ? 0 : -EINVAL; return 0; @@ -5658,7 +5665,7 @@ static int si_set_power_state_conditionally_enable_ulv(struct amdgpu_device *ade if (ulv->supported) { if (si_is_state_ulv_compatible(adev, amdgpu_new_state)) - return (si_send_msg_to_smc(adev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ? + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ? 0 : -EINVAL; } return 0; @@ -5763,8 +5770,8 @@ static int si_upload_sw_state(struct amdgpu_device *adev, if (ret) return ret; - return si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, - state_size, si_pi->sram_end); + return amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, + state_size, si_pi->sram_end); } static int si_upload_ulv_state(struct amdgpu_device *adev) @@ -5783,8 +5790,8 @@ static int si_upload_ulv_state(struct amdgpu_device *adev) ret = si_populate_ulv_state(adev, smc_state); if (!ret) - ret = si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, - state_size, si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, + state_size, si_pi->sram_end); } return ret; @@ -6155,9 +6162,9 @@ static int si_populate_mc_reg_table(struct amdgpu_device *adev, si_convert_mc_reg_table_to_smc(adev, amdgpu_boot_state, smc_mc_reg_table); - return si_copy_bytes_to_smc(adev, si_pi->mc_reg_table_start, - (u8 *)smc_mc_reg_table, - sizeof(SMC_SIslands_MCRegisters), si_pi->sram_end); + return amdgpu_si_copy_bytes_to_smc(adev, si_pi->mc_reg_table_start, + (u8 *)smc_mc_reg_table, + sizeof(SMC_SIslands_MCRegisters), si_pi->sram_end); } static int si_upload_mc_reg_table(struct amdgpu_device *adev, @@ -6174,10 +6181,10 @@ static int si_upload_mc_reg_table(struct amdgpu_device *adev, si_convert_mc_reg_table_to_smc(adev, amdgpu_new_state, smc_mc_reg_table); - return si_copy_bytes_to_smc(adev, address, - (u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT], - sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count, - si_pi->sram_end); + return amdgpu_si_copy_bytes_to_smc(adev, address, + (u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT], + sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count, + si_pi->sram_end); } static void si_enable_voltage_control(struct amdgpu_device *adev, bool enable) @@ -6285,11 +6292,11 @@ static int si_ds_request(struct amdgpu_device *adev, if (eg_pi->sclk_deep_sleep) { if (ds_status_on) - return (si_send_msg_to_smc(adev, PPSMC_MSG_CancelThrottleOVRDSCLKDS) == + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_CancelThrottleOVRDSCLKDS) == PPSMC_Result_OK) ? 0 : -EINVAL; else - return (si_send_msg_to_smc(adev, PPSMC_MSG_ThrottleOVRDSCLKDS) == + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ThrottleOVRDSCLKDS) == PPSMC_Result_OK) ? 0 : -EINVAL; } return 0; @@ -6420,7 +6427,7 @@ static int si_thermal_enable_alert(struct amdgpu_device *adev, thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); WREG32(CG_THERMAL_INT, thermal_int); - result = si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); + result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); if (result != PPSMC_Result_OK) { DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); return -EINVAL; @@ -6535,11 +6542,11 @@ static int si_thermal_setup_fan_table(struct amdgpu_device *adev) tmp = (RREG32(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT; fan_table.temp_src = (uint8_t)tmp; - ret = si_copy_bytes_to_smc(adev, - si_pi->fan_table_start, - (u8 *)(&fan_table), - sizeof(fan_table), - si_pi->sram_end); + ret = amdgpu_si_copy_bytes_to_smc(adev, + si_pi->fan_table_start, + (u8 *)(&fan_table), + sizeof(fan_table), + si_pi->sram_end); if (ret) { DRM_ERROR("Failed to load fan table to the SMC."); @@ -6554,7 +6561,7 @@ static int si_fan_ctrl_start_smc_fan_control(struct amdgpu_device *adev) struct si_power_info *si_pi = si_get_pi(adev); PPSMC_Result ret; - ret = si_send_msg_to_smc(adev, PPSMC_StartFanControl); + ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StartFanControl); if (ret == PPSMC_Result_OK) { si_pi->fan_is_controlled_by_smc = true; return 0; @@ -6568,7 +6575,7 @@ static int si_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev) struct si_power_info *si_pi = si_get_pi(adev); PPSMC_Result ret; - ret = si_send_msg_to_smc(adev, PPSMC_StopFanControl); + ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StopFanControl); if (ret == PPSMC_Result_OK) { si_pi->fan_is_controlled_by_smc = false; @@ -6799,7 +6806,7 @@ static int si_dpm_enable(struct amdgpu_device *adev) struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; int ret; - if (si_is_smc_running(adev)) + if (amdgpu_si_is_smc_running(adev)) return -EINVAL; if (pi->voltage_control || si_pi->voltage_control_svi2) si_enable_voltage_control(adev, true); @@ -6930,7 +6937,7 @@ static void si_dpm_disable(struct amdgpu_device *adev) struct rv7xx_power_info *pi = rv770_get_pi(adev); struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; - if (!si_is_smc_running(adev)) + if (!amdgpu_si_is_smc_running(adev)) return; si_thermal_stop_thermal_controller(adev); si_disable_ulv(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/si_smc.c b/drivers/gpu/drm/amd/amdgpu/si_smc.c index 47bbb40..668ba99 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/si_smc.c @@ -44,9 +44,9 @@ static int si_set_smc_sram_address(struct amdgpu_device *adev, return 0; } -int si_copy_bytes_to_smc(struct amdgpu_device *adev, - u32 smc_start_address, - const u8 *src, u32 byte_count, u32 limit) +int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev, + u32 smc_start_address, + const u8 *src, u32 byte_count, u32 limit) { unsigned long flags; int ret = 0; @@ -108,7 +108,7 @@ done: return ret; } -void si_start_smc(struct amdgpu_device *adev) +void amdgpu_si_start_smc(struct amdgpu_device *adev) { u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); @@ -117,7 +117,7 @@ void si_start_smc(struct amdgpu_device *adev) WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); } -void si_reset_smc(struct amdgpu_device *adev) +void amdgpu_si_reset_smc(struct amdgpu_device *adev) { u32 tmp; @@ -131,14 +131,14 @@ void si_reset_smc(struct amdgpu_device *adev) WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); } -int si_program_jump_on_start(struct amdgpu_device *adev) +int amdgpu_si_program_jump_on_start(struct amdgpu_device *adev) { static const u8 data[] = { 0x0E, 0x00, 0x40, 0x40 }; - return si_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1); + return amdgpu_si_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1); } -void si_smc_clock(struct amdgpu_device *adev, bool enable) +void amdgpu_si_smc_clock(struct amdgpu_device *adev, bool enable) { u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); @@ -150,7 +150,7 @@ void si_smc_clock(struct amdgpu_device *adev, bool enable) WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); } -bool si_is_smc_running(struct amdgpu_device *adev) +bool amdgpu_si_is_smc_running(struct amdgpu_device *adev) { u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL); u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); @@ -161,12 +161,13 @@ bool si_is_smc_running(struct amdgpu_device *adev) return false; } -PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg) +PPSMC_Result amdgpu_si_send_msg_to_smc(struct amdgpu_device *adev, + PPSMC_Msg msg) { u32 tmp; int i; - if (!si_is_smc_running(adev)) + if (!amdgpu_si_is_smc_running(adev)) return PPSMC_Result_Failed; WREG32(SMC_MESSAGE_0, msg); @@ -181,12 +182,12 @@ PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg) return (PPSMC_Result)RREG32(SMC_RESP_0); } -PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev) +PPSMC_Result amdgpu_si_wait_for_smc_inactive(struct amdgpu_device *adev) { u32 tmp; int i; - if (!si_is_smc_running(adev)) + if (!amdgpu_si_is_smc_running(adev)) return PPSMC_Result_OK; for (i = 0; i < adev->usec_timeout; i++) { @@ -199,7 +200,7 @@ PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev) return PPSMC_Result_OK; } -int si_load_smc_ucode(struct amdgpu_device *adev, u32 limit) +int amdgpu_si_load_smc_ucode(struct amdgpu_device *adev, u32 limit) { const struct smc_firmware_header_v1_0 *hdr; unsigned long flags; @@ -241,8 +242,8 @@ int si_load_smc_ucode(struct amdgpu_device *adev, u32 limit) return 0; } -int si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 *value, u32 limit) +int amdgpu_si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 *value, u32 limit) { unsigned long flags; int ret; @@ -256,8 +257,8 @@ int si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, return ret; } -int si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 value, u32 limit) +int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 value, u32 limit) { unsigned long flags; int ret; diff --git a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h index c5b3377..ee4b846 100644 --- a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h +++ b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h @@ -402,21 +402,21 @@ typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration; #pragma pack(pop) -int si_copy_bytes_to_smc(struct amdgpu_device *adev, - u32 smc_start_address, - const u8 *src, u32 byte_count, u32 limit); -void si_start_smc(struct amdgpu_device *adev); -void si_reset_smc(struct amdgpu_device *adev); -int si_program_jump_on_start(struct amdgpu_device *adev); -void si_smc_clock(struct amdgpu_device *adev, bool enable); -bool si_is_smc_running(struct amdgpu_device *adev); -PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg); -PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev); -int si_load_smc_ucode(struct amdgpu_device *adev, u32 limit); -int si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 *value, u32 limit); -int si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 value, u32 limit); +int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev, + u32 smc_start_address, + const u8 *src, u32 byte_count, u32 limit); +void amdgpu_si_start_smc(struct amdgpu_device *adev); +void amdgpu_si_reset_smc(struct amdgpu_device *adev); +int amdgpu_si_program_jump_on_start(struct amdgpu_device *adev); +void amdgpu_si_smc_clock(struct amdgpu_device *adev, bool enable); +bool amdgpu_si_is_smc_running(struct amdgpu_device *adev); +PPSMC_Result amdgpu_si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg); +PPSMC_Result amdgpu_si_wait_for_smc_inactive(struct amdgpu_device *adev); +int amdgpu_si_load_smc_ucode(struct amdgpu_device *adev, u32 limit); +int amdgpu_si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 *value, u32 limit); +int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 value, u32 limit); #endif -- cgit v1.1 From 7c1fa1db54549a75250763c68afb150418085db1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 27 Aug 2016 12:37:22 -0400 Subject: drm/amdgpu: handle runtime pm in fbcon (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ported from nouveau. v2: re-enable runtime autosuspend in the error case Acked-by: Edward O'Callaghan Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 9191467..3c527cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -48,8 +49,35 @@ struct amdgpu_fbdev { struct amdgpu_device *adev; }; +static int +amdgpufb_open(struct fb_info *info, int user) +{ + struct amdgpu_fbdev *rfbdev = info->par; + struct amdgpu_device *adev = rfbdev->adev; + int ret = pm_runtime_get_sync(adev->ddev->dev); + if (ret < 0 && ret != -EACCES) { + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + return ret; + } + return 0; +} + +static int +amdgpufb_release(struct fb_info *info, int user) +{ + struct amdgpu_fbdev *rfbdev = info->par; + struct amdgpu_device *adev = rfbdev->adev; + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + return 0; +} + static struct fb_ops amdgpufb_ops = { .owner = THIS_MODULE, + .fb_open = amdgpufb_open, + .fb_release = amdgpufb_release, .fb_check_var = drm_fb_helper_check_var, .fb_set_par = drm_fb_helper_set_par, .fb_fillrect = drm_fb_helper_cfb_fillrect, -- cgit v1.1 From 5756b1558eabdfb087aa9896250c6decd12bf872 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 31 Aug 2016 17:29:51 -0400 Subject: drm/radeon: handle runtime pm in fbcon (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ported from nouveau. v2: re-enable runtime autosuspend in the error case Acked-by: Edward O'Callaghan Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_fb.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 0e3143a..6b2537d 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -47,8 +48,35 @@ struct radeon_fbdev { struct radeon_device *rdev; }; +static int +radeonfb_open(struct fb_info *info, int user) +{ + struct radeon_fbdev *rfbdev = info->par; + struct radeon_device *rdev = rfbdev->rdev; + int ret = pm_runtime_get_sync(rdev->ddev->dev); + if (ret < 0 && ret != -EACCES) { + pm_runtime_mark_last_busy(rdev->ddev->dev); + pm_runtime_put_autosuspend(rdev->ddev->dev); + return ret; + } + return 0; +} + +static int +radeonfb_release(struct fb_info *info, int user) +{ + struct radeon_fbdev *rfbdev = info->par; + struct radeon_device *rdev = rfbdev->rdev; + + pm_runtime_mark_last_busy(rdev->ddev->dev); + pm_runtime_put_autosuspend(rdev->ddev->dev); + return 0; +} + static struct fb_ops radeonfb_ops = { .owner = THIS_MODULE, + .fb_open = radeonfb_open, + .fb_release = radeonfb_release, .fb_check_var = drm_fb_helper_check_var, .fb_set_par = drm_fb_helper_set_par, .fb_fillrect = drm_fb_helper_cfb_fillrect, -- cgit v1.1 From 5d98d0bcff64c9a76d21da9648881e14ed26fff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 12 Sep 2016 13:16:16 +0200 Subject: drm/ttm: use ffs in ttm_mem_type_from_place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A bit pointless to search for the first bit set manually. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_bo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c2a30bd..fc6217d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -57,14 +57,14 @@ static struct attribute ttm_bo_count = { static inline int ttm_mem_type_from_place(const struct ttm_place *place, uint32_t *mem_type) { - int i; + int pos; - for (i = 0; i <= TTM_PL_PRIV5; i++) - if (place->flags & (1 << i)) { - *mem_type = i; - return 0; - } - return -EINVAL; + pos = ffs(place->flags & TTM_PL_MASK_MEM); + if (unlikely(!pos)) + return -EINVAL; + + *mem_type = pos - 1; + return 0; } static void ttm_mem_type_debug(struct ttm_bo_device *bdev, int mem_type) -- cgit v1.1 From 283cde69aa318f7b2eeb02a7c62b16f69e1d422a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 12 Sep 2016 13:34:37 +0200 Subject: drm/ttm: rework handling of private mem types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of keeping a bunch of potentially unused flags, just define the start for private memory types and remove the rest. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 12 ++++++------ drivers/gpu/drm/qxl/qxl_object.c | 8 ++++---- drivers/gpu/drm/qxl/qxl_ttm.c | 12 ++++++------ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 8 ++++---- include/drm/ttm/ttm_placement.h | 16 ++-------------- 5 files changed, 22 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 214bae9..3ee825f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -26,13 +26,13 @@ #include "gpu_scheduler.h" -#define AMDGPU_PL_GDS TTM_PL_PRIV0 -#define AMDGPU_PL_GWS TTM_PL_PRIV1 -#define AMDGPU_PL_OA TTM_PL_PRIV2 +#define AMDGPU_PL_GDS (TTM_PL_PRIV + 0) +#define AMDGPU_PL_GWS (TTM_PL_PRIV + 1) +#define AMDGPU_PL_OA (TTM_PL_PRIV + 2) -#define AMDGPU_PL_FLAG_GDS TTM_PL_FLAG_PRIV0 -#define AMDGPU_PL_FLAG_GWS TTM_PL_FLAG_PRIV1 -#define AMDGPU_PL_FLAG_OA TTM_PL_FLAG_PRIV2 +#define AMDGPU_PL_FLAG_GDS (TTM_PL_FLAG_PRIV << 0) +#define AMDGPU_PL_FLAG_GWS (TTM_PL_FLAG_PRIV << 1) +#define AMDGPU_PL_FLAG_OA (TTM_PL_FLAG_PRIV << 2) #define AMDGPU_TTM_LRU_SIZE 20 diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index 5e1d789..fa5440d 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -61,7 +61,7 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain, bool pinned) if (domain == QXL_GEM_DOMAIN_VRAM) qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_VRAM | pflag; if (domain == QXL_GEM_DOMAIN_SURFACE) - qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_PRIV0 | pflag; + qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_PRIV | pflag; if (domain == QXL_GEM_DOMAIN_CPU) qbo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM | pflag; if (!c) @@ -151,7 +151,7 @@ void *qxl_bo_kmap_atomic_page(struct qxl_device *qdev, if (bo->tbo.mem.mem_type == TTM_PL_VRAM) map = qdev->vram_mapping; - else if (bo->tbo.mem.mem_type == TTM_PL_PRIV0) + else if (bo->tbo.mem.mem_type == TTM_PL_PRIV) map = qdev->surface_mapping; else goto fallback; @@ -191,7 +191,7 @@ void qxl_bo_kunmap_atomic_page(struct qxl_device *qdev, if (bo->tbo.mem.mem_type == TTM_PL_VRAM) map = qdev->vram_mapping; - else if (bo->tbo.mem.mem_type == TTM_PL_PRIV0) + else if (bo->tbo.mem.mem_type == TTM_PL_PRIV) map = qdev->surface_mapping; else goto fallback; @@ -311,7 +311,7 @@ int qxl_bo_check_id(struct qxl_device *qdev, struct qxl_bo *bo) int qxl_surf_evict(struct qxl_device *qdev) { - return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_PRIV0); + return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_PRIV); } int qxl_vram_evict(struct qxl_device *qdev) diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 6a22de0..a257ad2 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -168,7 +168,7 @@ static int qxl_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_VRAM: - case TTM_PL_PRIV0: + case TTM_PL_PRIV: /* "On-card" video ram */ man->func = &ttm_bo_manager_func; man->gpu_offset = 0; @@ -235,7 +235,7 @@ static int qxl_ttm_io_mem_reserve(struct ttm_bo_device *bdev, mem->bus.base = qdev->vram_base; mem->bus.offset = mem->start << PAGE_SHIFT; break; - case TTM_PL_PRIV0: + case TTM_PL_PRIV: mem->bus.is_iomem = true; mem->bus.base = qdev->surfaceram_base; mem->bus.offset = mem->start << PAGE_SHIFT; @@ -376,7 +376,7 @@ static void qxl_bo_move_notify(struct ttm_buffer_object *bo, qbo = to_qxl_bo(bo); qdev = qbo->gem_base.dev->dev_private; - if (bo->mem.mem_type == TTM_PL_PRIV0 && qbo->surface_id) + if (bo->mem.mem_type == TTM_PL_PRIV && qbo->surface_id) qxl_surface_evict(qdev, qbo, new_mem ? true : false); } @@ -422,7 +422,7 @@ int qxl_ttm_init(struct qxl_device *qdev) DRM_ERROR("Failed initializing VRAM heap.\n"); return r; } - r = ttm_bo_init_mm(&qdev->mman.bdev, TTM_PL_PRIV0, + r = ttm_bo_init_mm(&qdev->mman.bdev, TTM_PL_PRIV, qdev->surfaceram_size / PAGE_SIZE); if (r) { DRM_ERROR("Failed initializing Surfaces heap.\n"); @@ -445,7 +445,7 @@ int qxl_ttm_init(struct qxl_device *qdev) void qxl_ttm_fini(struct qxl_device *qdev) { ttm_bo_clean_mm(&qdev->mman.bdev, TTM_PL_VRAM); - ttm_bo_clean_mm(&qdev->mman.bdev, TTM_PL_PRIV0); + ttm_bo_clean_mm(&qdev->mman.bdev, TTM_PL_PRIV); ttm_bo_device_release(&qdev->mman.bdev); qxl_ttm_global_fini(qdev); DRM_INFO("qxl: ttm finalized\n"); @@ -489,7 +489,7 @@ static int qxl_ttm_debugfs_init(struct qxl_device *qdev) if (i == 0) qxl_mem_types_list[i].data = qdev->mman.bdev.man[TTM_PL_VRAM].priv; else - qxl_mem_types_list[i].data = qdev->mman.bdev.man[TTM_PL_PRIV0].priv; + qxl_mem_types_list[i].data = qdev->mman.bdev.man[TTM_PL_PRIV].priv; } return qxl_debugfs_add_files(qdev, qxl_mem_types_list, i); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 74304b0..070d750 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -67,10 +67,10 @@ VMWGFX_NUM_GB_SURFACE +\ VMWGFX_NUM_GB_SCREEN_TARGET) -#define VMW_PL_GMR TTM_PL_PRIV0 -#define VMW_PL_FLAG_GMR TTM_PL_FLAG_PRIV0 -#define VMW_PL_MOB TTM_PL_PRIV1 -#define VMW_PL_FLAG_MOB TTM_PL_FLAG_PRIV1 +#define VMW_PL_GMR (TTM_PL_PRIV + 0) +#define VMW_PL_FLAG_GMR (TTM_PL_FLAG_PRIV << 0) +#define VMW_PL_MOB (TTM_PL_PRIV + 1) +#define VMW_PL_FLAG_MOB (TTM_PL_FLAG_PRIV << 1) #define VMW_RES_CONTEXT ttm_driver_type0 #define VMW_RES_SURFACE ttm_driver_type1 diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h index 8ed44f9..4c579d9 100644 --- a/include/drm/ttm/ttm_placement.h +++ b/include/drm/ttm/ttm_placement.h @@ -37,24 +37,12 @@ #define TTM_PL_SYSTEM 0 #define TTM_PL_TT 1 #define TTM_PL_VRAM 2 -#define TTM_PL_PRIV0 3 -#define TTM_PL_PRIV1 4 -#define TTM_PL_PRIV2 5 -#define TTM_PL_PRIV3 6 -#define TTM_PL_PRIV4 7 -#define TTM_PL_PRIV5 8 -#define TTM_PL_SWAPPED 15 +#define TTM_PL_PRIV 3 #define TTM_PL_FLAG_SYSTEM (1 << TTM_PL_SYSTEM) #define TTM_PL_FLAG_TT (1 << TTM_PL_TT) #define TTM_PL_FLAG_VRAM (1 << TTM_PL_VRAM) -#define TTM_PL_FLAG_PRIV0 (1 << TTM_PL_PRIV0) -#define TTM_PL_FLAG_PRIV1 (1 << TTM_PL_PRIV1) -#define TTM_PL_FLAG_PRIV2 (1 << TTM_PL_PRIV2) -#define TTM_PL_FLAG_PRIV3 (1 << TTM_PL_PRIV3) -#define TTM_PL_FLAG_PRIV4 (1 << TTM_PL_PRIV4) -#define TTM_PL_FLAG_PRIV5 (1 << TTM_PL_PRIV5) -#define TTM_PL_FLAG_SWAPPED (1 << TTM_PL_SWAPPED) +#define TTM_PL_FLAG_PRIV (1 << TTM_PL_PRIV) #define TTM_PL_MASK_MEM 0x0000FFFF /* -- cgit v1.1 From 08614da7041eb59baf729bdcf07c2dbd3d80c63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 8 Sep 2016 15:30:33 +0200 Subject: drm/ttm: remove unused placement flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Either never used or not used in quite a while. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- include/drm/ttm/ttm_placement.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h index 4c579d9..7641582 100644 --- a/include/drm/ttm/ttm_placement.h +++ b/include/drm/ttm/ttm_placement.h @@ -60,7 +60,6 @@ #define TTM_PL_FLAG_CACHED (1 << 16) #define TTM_PL_FLAG_UNCACHED (1 << 17) #define TTM_PL_FLAG_WC (1 << 18) -#define TTM_PL_FLAG_SHARED (1 << 20) #define TTM_PL_FLAG_NO_EVICT (1 << 21) #define TTM_PL_FLAG_TOPDOWN (1 << 22) @@ -70,14 +69,4 @@ #define TTM_PL_MASK_MEMTYPE (TTM_PL_MASK_MEM | TTM_PL_MASK_CACHING) -/* - * Access flags to be used for CPU- and GPU- mappings. - * The idea is that the TTM synchronization mechanism will - * allow concurrent READ access and exclusive write access. - * Currently GPU- and CPU accesses are exclusive. - */ - -#define TTM_ACCESS_READ (1 << 0) -#define TTM_ACCESS_WRITE (1 << 1) - #endif -- cgit v1.1 From 7c732ea64993b9f37daff9bd95b552576304b6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 8 Sep 2016 15:40:38 +0200 Subject: drm/ttm: move placement structures into ttm_placement.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes more sense to keep that together. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- include/drm/ttm/ttm_bo_api.h | 32 +------------------------------- include/drm/ttm/ttm_placement.h | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 6f2c598..9eb940d 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -45,37 +45,7 @@ struct ttm_bo_device; struct drm_mm_node; -/** - * struct ttm_place - * - * @fpfn: first valid page frame number to put the object - * @lpfn: last valid page frame number to put the object - * @flags: memory domain and caching flags for the object - * - * Structure indicating a possible place to put an object. - */ -struct ttm_place { - unsigned fpfn; - unsigned lpfn; - uint32_t flags; -}; - -/** - * struct ttm_placement - * - * @num_placement: number of preferred placements - * @placement: preferred placements - * @num_busy_placement: number of preferred placements when need to evict buffer - * @busy_placement: preferred placements when need to evict buffer - * - * Structure indicating the placement you request for an object. - */ -struct ttm_placement { - unsigned num_placement; - const struct ttm_place *placement; - unsigned num_busy_placement; - const struct ttm_place *busy_placement; -}; +struct ttm_placement; /** * struct ttm_bus_placement diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h index 7641582..932be0c 100644 --- a/include/drm/ttm/ttm_placement.h +++ b/include/drm/ttm/ttm_placement.h @@ -30,6 +30,9 @@ #ifndef _TTM_PLACEMENT_H_ #define _TTM_PLACEMENT_H_ + +#include + /* * Memory regions for data placement. */ @@ -69,4 +72,36 @@ #define TTM_PL_MASK_MEMTYPE (TTM_PL_MASK_MEM | TTM_PL_MASK_CACHING) +/** + * struct ttm_place + * + * @fpfn: first valid page frame number to put the object + * @lpfn: last valid page frame number to put the object + * @flags: memory domain and caching flags for the object + * + * Structure indicating a possible place to put an object. + */ +struct ttm_place { + unsigned fpfn; + unsigned lpfn; + uint32_t flags; +}; + +/** + * struct ttm_placement + * + * @num_placement: number of preferred placements + * @placement: preferred placements + * @num_busy_placement: number of preferred placements when need to evict buffer + * @busy_placement: preferred placements when need to evict buffer + * + * Structure indicating the placement you request for an object. + */ +struct ttm_placement { + unsigned num_placement; + const struct ttm_place *placement; + unsigned num_busy_placement; + const struct ttm_place *busy_placement; +}; + #endif -- cgit v1.1 From aa29040b437be9e4255062aa38bcbe7cb50da8c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 9 Sep 2016 11:21:43 +0200 Subject: drm/amdgpu: validate size and offset of user fence BO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to validate the offset to make sure that we don't write after the BO. Additional to that a page should be enough and can make address space handling much easier. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 9480be4..b8412bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -91,6 +91,7 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, uint32_t *offset) { struct drm_gem_object *gobj; + unsigned long size; gobj = drm_gem_object_lookup(p->filp, data->handle); if (gobj == NULL) @@ -101,6 +102,11 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, p->uf_entry.tv.bo = &p->uf_entry.robj->tbo; p->uf_entry.tv.shared = true; p->uf_entry.user_pages = NULL; + + size = amdgpu_bo_size(p->uf_entry.robj); + if (size != PAGE_SIZE || (data->offset + 8) > size) + return -EINVAL; + *offset = data->offset; drm_gem_object_unreference_unlocked(gobj); -- cgit v1.1 From 9702d40dd3baa90e8f08b42a512fe76e2794f9bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 7 Sep 2016 15:10:44 +0200 Subject: drm/amdgpu: add AMDGPU_BO_INVALID_OFFSET MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An invalid offset to be used by custom VRAM/GGT manager when we don't have an offset for an BO. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index e503ca1..151a706 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -956,6 +956,7 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) !amdgpu_ttm_is_bound(bo->tbo.ttm)); WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) && !bo->pin_count); + WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET); return bo->tbo.offset; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 3032c54..8255034 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -31,6 +31,8 @@ #include #include "amdgpu.h" +#define AMDGPU_BO_INVALID_OFFSET LONG_MAX + /** * amdgpu_mem_type_to_domain - return domain corresponding to mem_type * @mem_type: ttm memory type -- cgit v1.1 From 78ab0a38bfe0e02db6e619185dd4337fc97e3ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 9 Sep 2016 15:39:08 +0200 Subject: drm/amdgpu: unbind GTT only when it is bound MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doesn't make much sense to clear the GTT when it was never filled. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index b50535c..8aa3fe6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -733,6 +733,9 @@ static int amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) { struct amdgpu_ttm_tt *gtt = (void *)ttm; + if (!amdgpu_ttm_is_bound(ttm)) + return 0; + /* unbind shouldn't be done for GDS/GWS/OA in ttm_bo_clean_mm */ if (gtt->adev->gart.ready) amdgpu_gart_unbind(gtt->adev, gtt->offset, ttm->num_pages); -- cgit v1.1 From 08291c5c2ea76af86b6a3d8ef78c60f3ef8a8413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 12 Sep 2016 16:06:18 +0200 Subject: drm/amdgpu: use explicit GTT limit for evictions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way the address space gets allocated immediately. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8aa3fe6..3daf858 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -201,6 +201,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, .lpfn = 0, .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM }; + unsigned i; if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) { placement->placement = &placements; @@ -212,10 +213,25 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, rbo = container_of(bo, struct amdgpu_bo, tbo); switch (bo->mem.mem_type) { case TTM_PL_VRAM: - if (rbo->adev->mman.buffer_funcs_ring->ready == false) + if (rbo->adev->mman.buffer_funcs_ring->ready == false) { amdgpu_ttm_placement_from_domain(rbo, AMDGPU_GEM_DOMAIN_CPU); - else + } else { amdgpu_ttm_placement_from_domain(rbo, AMDGPU_GEM_DOMAIN_GTT); + for (i = 0; i < rbo->placement.num_placement; ++i) { + if (!(rbo->placements[i].flags & + TTM_PL_FLAG_TT)) + continue; + + if (rbo->placements[i].lpfn) + continue; + + /* set an upper limit to force directly + * allocating address space for the BO. + */ + rbo->placements[i].lpfn = + rbo->adev->mc.gtt_size >> PAGE_SHIFT; + } + } break; case TTM_PL_TT: default: -- cgit v1.1 From 056472f1d1f5f63222dc745677829e124bfe7fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 12 Sep 2016 16:08:52 +0200 Subject: drm/amdgpu: use explicit limit for VRAM<->GTT moves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use an explicit limit when moving things around to force address space allocation. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3daf858..dfb1223 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -339,7 +339,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, placement.num_busy_placement = 1; placement.busy_placement = &placements; placements.fpfn = 0; - placements.lpfn = 0; + placements.lpfn = adev->mc.gtt_size >> PAGE_SHIFT; placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait_gpu); @@ -386,7 +386,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, placement.num_busy_placement = 1; placement.busy_placement = &placements; placements.fpfn = 0; - placements.lpfn = 0; + placements.lpfn = adev->mc.gtt_size >> PAGE_SHIFT; placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait_gpu); -- cgit v1.1 From a47c78d9646f3d2543b5b3c2e15ec6d9ee46a303 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Thu, 1 Sep 2016 13:49:33 -0400 Subject: drm/amdgpu/vi: Use correct external_rev_id for stoney Reviewed-by: Alex Deucher Signed-off-by: Jordan Lazare Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index f2e8aa1..b688e2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1650,7 +1650,7 @@ static int vi_common_early_init(void *handle) AMD_PG_SUPPORT_GFX_PIPELINE | AMD_PG_SUPPORT_UVD | AMD_PG_SUPPORT_VCE; - adev->external_rev_id = adev->rev_id + 0x1; + adev->external_rev_id = adev->rev_id + 0x61; break; default: /* FIXME: not supported yet */ -- cgit v1.1 From e1aa5715f6683d486f2e14255f6e42cf0a66c4e8 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 19 Aug 2016 20:52:09 +0800 Subject: drm/amd/powerplay: rename tonga_processpptable* to processpptable_v1_0*. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/Makefile | 2 +- drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c | 10 +- .../gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c | 10 +- drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h | 436 +++++++ .../amd/powerplay/hwmgr/process_pptables_v1_0.c | 1326 ++++++++++++++++++++ .../amd/powerplay/hwmgr/process_pptables_v1_0.h | 35 + drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c | 10 +- .../gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h | 436 ------- .../amd/powerplay/hwmgr/tonga_processpptables.c | 1326 -------------------- .../amd/powerplay/hwmgr/tonga_processpptables.h | 35 - 10 files changed, 1813 insertions(+), 1813 deletions(-) create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile index abbcbc9..6e359c9 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile @@ -5,7 +5,7 @@ HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \ hardwaremanager.o pp_acpi.o cz_hwmgr.o \ cz_clockpowergating.o tonga_powertune.o\ - tonga_processpptables.o ppatomctrl.o \ + process_pptables_v1_0.o ppatomctrl.o \ tonga_hwmgr.o pppcielanes.o tonga_thermal.o\ fiji_powertune.o fiji_hwmgr.o tonga_clockpowergating.o \ fiji_clockpowergating.o fiji_thermal.o \ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c index 560d424..0d4c99b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c @@ -45,8 +45,8 @@ #include "dce/dce_10_0_sh_mask.h" #include "pppcielanes.h" #include "fiji_hwmgr.h" -#include "tonga_processpptables.h" -#include "tonga_pptable.h" +#include "process_pptables_v1_0.h" +#include "pptable_v1_0.h" #include "pp_debug.h" #include "pp_acpi.h" #include "amd_pcie_helpers.h" @@ -4007,7 +4007,7 @@ static int fiji_get_pp_table_entry(struct pp_hwmgr *hwmgr, ps = (struct fiji_power_state *)(&state->hardware); - result = tonga_get_powerplay_table_entry(hwmgr, entry_index, state, + result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, state, fiji_get_pp_table_entry_callback_func); /* This is the earliest time we have all the dependency table and the VBIOS boot state @@ -5553,7 +5553,7 @@ static const struct pp_hwmgr_func fiji_hwmgr_funcs = { .dynamic_state_management_enable = &fiji_enable_dpm_tasks, .dynamic_state_management_disable = &fiji_disable_dpm_tasks, .force_dpm_level = &fiji_dpm_force_dpm_level, - .get_num_of_pp_table_entries = &tonga_get_number_of_powerplay_table_entries, + .get_num_of_pp_table_entries = &get_number_of_powerplay_table_entries_v1_0, .get_power_state_size = &fiji_get_power_state_size, .get_pp_table_entry = &fiji_get_pp_table_entry, .patch_boot_state = &fiji_patch_boot_state, @@ -5595,7 +5595,7 @@ static const struct pp_hwmgr_func fiji_hwmgr_funcs = { int fiji_hwmgr_init(struct pp_hwmgr *hwmgr) { hwmgr->hwmgr_func = &fiji_hwmgr_funcs; - hwmgr->pptable_func = &tonga_pptable_funcs; + hwmgr->pptable_func = &pptable_v1_0_funcs; pp_fiji_thermal_initialize(hwmgr); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c index 8b1eb7f..970e393 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c @@ -34,11 +34,11 @@ #include "pp_debug.h" #include "ppatomctrl.h" #include "atombios.h" -#include "tonga_pptable.h" +#include "pptable_v1_0.h" #include "pppcielanes.h" #include "amd_pcie_helpers.h" #include "hardwaremanager.h" -#include "tonga_processpptables.h" +#include "process_pptables_v1_0.h" #include "cgs_common.h" #include "smu74.h" #include "smu_ucode_xfer_vi.h" @@ -3893,7 +3893,7 @@ static int polaris10_get_pp_table_entry(struct pp_hwmgr *hwmgr, ps = (struct polaris10_power_state *)(&state->hardware); - result = tonga_get_powerplay_table_entry(hwmgr, entry_index, state, + result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, state, polaris10_get_pp_table_entry_callback_func); /* This is the earliest time we have all the dependency table and the VBIOS boot state @@ -5246,7 +5246,7 @@ static const struct pp_hwmgr_func polaris10_hwmgr_funcs = { .get_sclk = polaris10_dpm_get_sclk, .patch_boot_state = polaris10_dpm_patch_boot_state, .get_pp_table_entry = polaris10_get_pp_table_entry, - .get_num_of_pp_table_entries = tonga_get_number_of_powerplay_table_entries, + .get_num_of_pp_table_entries = get_number_of_powerplay_table_entries_v1_0, .print_current_perforce_level = polaris10_print_current_perforce_level, .powerdown_uvd = polaris10_phm_powerdown_uvd, .powergate_uvd = polaris10_phm_powergate_uvd, @@ -5283,7 +5283,7 @@ static const struct pp_hwmgr_func polaris10_hwmgr_funcs = { int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr) { hwmgr->hwmgr_func = &polaris10_hwmgr_funcs; - hwmgr->pptable_func = &tonga_pptable_funcs; + hwmgr->pptable_func = &pptable_v1_0_funcs; pp_polaris10_thermal_initialize(hwmgr); return 0; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h new file mode 100644 index 0000000..1e870f5 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h @@ -0,0 +1,436 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef TONGA_PPTABLE_H +#define TONGA_PPTABLE_H + +/** \file + * This is a PowerPlay table header file + */ +#pragma pack(push, 1) + +#include "hwmgr.h" + +#define ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f +#define ATOM_TONGA_PP_FANPARAMETERS_NOFAN 0x80 /* No fan is connected to this controller. */ + +#define ATOM_TONGA_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_TONGA_PP_THERMALCONTROLLER_LM96163 17 +#define ATOM_TONGA_PP_THERMALCONTROLLER_TONGA 21 +#define ATOM_TONGA_PP_THERMALCONTROLLER_FIJI 22 + +/* + * Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. + * We probably should reserve the bit 0x80 for this use. + * To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). + * The driver can pick the correct internal controller based on the ASIC. + */ + +#define ATOM_TONGA_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 /* ADT7473 Fan Control + Internal Thermal Controller */ +#define ATOM_TONGA_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D /* EMC2103 Fan Control + Internal Thermal Controller */ + +/*/* ATOM_TONGA_POWERPLAYTABLE::ulPlatformCaps */ +#define ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL 0x1 /* This cap indicates whether vddgfx will be a separated power rail. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY 0x2 /* This cap indicates whether this is a mobile part and CCC need to show Powerplay page. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x4 /* This cap indicates whether power source notificaiton is done by SBIOS directly. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND 0x8 /* Enable the option to overwrite voltage island feature to be disabled, regardless of VddGfx power rail support. */ +#define ____RETIRE16____ 0x10 +#define ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC 0x20 /* This cap indicates whether power source notificaiton is done by GPIO directly. */ +#define ____RETIRE64____ 0x40 +#define ____RETIRE128____ 0x80 +#define ____RETIRE256____ 0x100 +#define ____RETIRE512____ 0x200 +#define ____RETIRE1024____ 0x400 +#define ____RETIRE2048____ 0x800 +#define ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL 0x1000 /* This cap indicates dynamic MVDD is required. Uncheck to disable it. */ +#define ____RETIRE2000____ 0x2000 +#define ____RETIRE4000____ 0x4000 +#define ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 /* This cap indicates dynamic VDDCI is required. Uncheck to disable it. */ +#define ____RETIRE10000____ 0x10000 +#define ATOM_TONGA_PP_PLATFORM_CAP_BACO 0x20000 /* Enable to indicate the driver supports BACO state. */ + +#define ATOM_TONGA_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17 0x100000 /* Enable to indicate the driver supports thermal2GPIO17. */ +#define ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x1000000 /* Enable to indicate if thermal and PCC are sharing the same GPIO */ +#define ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE 0x2000000 + +/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */ +#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 +#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 +#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 +#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 +/* 2, 4, 6, 7 are reserved */ + +#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 +#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 +#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 +#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 +#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 +#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 + +/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */ +#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 + +#define ATOM_Tonga_DISALLOW_ON_DC 0x00004000 +#define ATOM_Tonga_ENABLE_VARIBRIGHT 0x00008000 + +#define ATOM_Tonga_TABLE_REVISION_TONGA 7 + +typedef struct _ATOM_Tonga_POWERPLAYTABLE { + ATOM_COMMON_TABLE_HEADER sHeader; + + UCHAR ucTableRevision; + USHORT usTableSize; /*the size of header structure */ + + ULONG ulGoldenPPID; + ULONG ulGoldenRevision; + USHORT usFormatID; + + USHORT usVoltageTime; /*in microseconds */ + ULONG ulPlatformCaps; /*See ATOM_Tonga_CAPS_* */ + + ULONG ulMaxODEngineClock; /*For Overdrive. */ + ULONG ulMaxODMemoryClock; /*For Overdrive. */ + + USHORT usPowerControlLimit; + USHORT usUlvVoltageOffset; /*in mv units */ + + USHORT usStateArrayOffset; /*points to ATOM_Tonga_State_Array */ + USHORT usFanTableOffset; /*points to ATOM_Tonga_Fan_Table */ + USHORT usThermalControllerOffset; /*points to ATOM_Tonga_Thermal_Controller */ + USHORT usReserv; /*CustomThermalPolicy removed for Tonga. Keep this filed as reserved. */ + + USHORT usMclkDependencyTableOffset; /*points to ATOM_Tonga_MCLK_Dependency_Table */ + USHORT usSclkDependencyTableOffset; /*points to ATOM_Tonga_SCLK_Dependency_Table */ + USHORT usVddcLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ + USHORT usVddgfxLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ + + USHORT usMMDependencyTableOffset; /*points to ATOM_Tonga_MM_Dependency_Table */ + + USHORT usVCEStateTableOffset; /*points to ATOM_Tonga_VCE_State_Table; */ + + USHORT usPPMTableOffset; /*points to ATOM_Tonga_PPM_Table */ + USHORT usPowerTuneTableOffset; /*points to ATOM_PowerTune_Table */ + + USHORT usHardLimitTableOffset; /*points to ATOM_Tonga_Hard_Limit_Table */ + + USHORT usPCIETableOffset; /*points to ATOM_Tonga_PCIE_Table */ + + USHORT usGPIOTableOffset; /*points to ATOM_Tonga_GPIO_Table */ + + USHORT usReserved[6]; /*TODO: modify reserved size to fit structure aligning */ +} ATOM_Tonga_POWERPLAYTABLE; + +typedef struct _ATOM_Tonga_State { + UCHAR ucEngineClockIndexHigh; + UCHAR ucEngineClockIndexLow; + + UCHAR ucMemoryClockIndexHigh; + UCHAR ucMemoryClockIndexLow; + + UCHAR ucPCIEGenLow; + UCHAR ucPCIEGenHigh; + + UCHAR ucPCIELaneLow; + UCHAR ucPCIELaneHigh; + + USHORT usClassification; + ULONG ulCapsAndSettings; + USHORT usClassification2; + UCHAR ucUnused[4]; +} ATOM_Tonga_State; + +typedef struct _ATOM_Tonga_State_Array { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_State entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_State_Array; + +typedef struct _ATOM_Tonga_MCLK_Dependency_Record { + UCHAR ucVddcInd; /* Vddc voltage */ + USHORT usVddci; + USHORT usVddgfxOffset; /* Offset relative to Vddc voltage */ + USHORT usMvdd; + ULONG ulMclk; + USHORT usReserved; +} ATOM_Tonga_MCLK_Dependency_Record; + +typedef struct _ATOM_Tonga_MCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_MCLK_Dependency_Table; + +typedef struct _ATOM_Tonga_SCLK_Dependency_Record { + UCHAR ucVddInd; /* Base voltage */ + USHORT usVddcOffset; /* Offset relative to base voltage */ + ULONG ulSclk; + USHORT usEdcCurrent; + UCHAR ucReliabilityTemperature; + UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ +} ATOM_Tonga_SCLK_Dependency_Record; + +typedef struct _ATOM_Tonga_SCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_SCLK_Dependency_Table; + +typedef struct _ATOM_Polaris_SCLK_Dependency_Record { + UCHAR ucVddInd; /* Base voltage */ + USHORT usVddcOffset; /* Offset relative to base voltage */ + ULONG ulSclk; + USHORT usEdcCurrent; + UCHAR ucReliabilityTemperature; + UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ + ULONG ulSclkOffset; +} ATOM_Polaris_SCLK_Dependency_Record; + +typedef struct _ATOM_Polaris_SCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Polaris_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Polaris_SCLK_Dependency_Table; + +typedef struct _ATOM_Tonga_PCIE_Record { + UCHAR ucPCIEGenSpeed; + UCHAR usPCIELaneWidth; + UCHAR ucReserved[2]; +} ATOM_Tonga_PCIE_Record; + +typedef struct _ATOM_Tonga_PCIE_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_PCIE_Table; + +typedef struct _ATOM_Polaris10_PCIE_Record { + UCHAR ucPCIEGenSpeed; + UCHAR usPCIELaneWidth; + UCHAR ucReserved[2]; + ULONG ulPCIE_Sclk; +} ATOM_Polaris10_PCIE_Record; + +typedef struct _ATOM_Polaris10_PCIE_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Polaris10_PCIE_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Polaris10_PCIE_Table; + + +typedef struct _ATOM_Tonga_MM_Dependency_Record { + UCHAR ucVddcInd; /* VDDC voltage */ + USHORT usVddgfxOffset; /* Offset relative to VDDC voltage */ + ULONG ulDClk; /* UVD D-clock */ + ULONG ulVClk; /* UVD V-clock */ + ULONG ulEClk; /* VCE clock */ + ULONG ulAClk; /* ACP clock */ + ULONG ulSAMUClk; /* SAMU clock */ +} ATOM_Tonga_MM_Dependency_Record; + +typedef struct _ATOM_Tonga_MM_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_MM_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_MM_Dependency_Table; + +typedef struct _ATOM_Tonga_Voltage_Lookup_Record { + USHORT usVdd; /* Base voltage */ + USHORT usCACLow; + USHORT usCACMid; + USHORT usCACHigh; +} ATOM_Tonga_Voltage_Lookup_Record; + +typedef struct _ATOM_Tonga_Voltage_Lookup_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_Voltage_Lookup_Table; + +typedef struct _ATOM_Tonga_Fan_Table { + UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ + UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ + USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + USHORT usTMed; /* The middle temperature where we change slopes. */ + USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ + USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ + USHORT usPWMHigh; /* The PWM value at THigh. */ + USHORT usTMax; /* The max temperature */ + UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ + USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ + USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ + USHORT usFanRPMMax; /* The default value in RPM */ + ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ + UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + USHORT usReserved; +} ATOM_Tonga_Fan_Table; + +typedef struct _ATOM_Fiji_Fan_Table { + UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ + UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ + USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + USHORT usTMed; /* The middle temperature where we change slopes. */ + USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ + USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ + USHORT usPWMHigh; /* The PWM value at THigh. */ + USHORT usTMax; /* The max temperature */ + UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ + USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ + USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ + USHORT usFanRPMMax; /* The default value in RPM */ + ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ + UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + USHORT usFanGainEdge; + USHORT usFanGainHotspot; + USHORT usFanGainLiquid; + USHORT usFanGainVrVddc; + USHORT usFanGainVrMvdd; + USHORT usFanGainPlx; + USHORT usFanGainHbm; + USHORT usReserved; +} ATOM_Fiji_Fan_Table; + +typedef struct _ATOM_Tonga_Thermal_Controller { + UCHAR ucRevId; + UCHAR ucType; /* one of ATOM_TONGA_PP_THERMALCONTROLLER_* */ + UCHAR ucI2cLine; /* as interpreted by DAL I2C */ + UCHAR ucI2cAddress; + UCHAR ucFanParameters; /* Fan Control Parameters. */ + UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only. */ + UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only. */ + UCHAR ucReserved; + UCHAR ucFlags; /* to be defined */ +} ATOM_Tonga_Thermal_Controller; + +typedef struct _ATOM_Tonga_VCE_State_Record { + UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Tonga_MM_Dependency_Table' type */ + UCHAR ucFlag; /* 2 bits indicates memory p-states */ + UCHAR ucSCLKIndex; /*index into ATOM_Tonga_SCLK_Dependency_Table */ + UCHAR ucMCLKIndex; /*index into ATOM_Tonga_MCLK_Dependency_Table */ +} ATOM_Tonga_VCE_State_Record; + +typedef struct _ATOM_Tonga_VCE_State_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; + ATOM_Tonga_VCE_State_Record entries[1]; +} ATOM_Tonga_VCE_State_Table; + +typedef struct _ATOM_Tonga_PowerTune_Table { + UCHAR ucRevId; + USHORT usTDP; + USHORT usConfigurableTDP; + USHORT usTDC; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usLowCACLeakage; + USHORT usHighCACLeakage; + USHORT usMaximumPowerDeliveryLimit; + USHORT usTjMax; + USHORT usPowerTuneDataSetID; + USHORT usEDCLimit; + USHORT usSoftwareShutdownTemp; + USHORT usClockStretchAmount; + USHORT usReserve[2]; +} ATOM_Tonga_PowerTune_Table; + +typedef struct _ATOM_Fiji_PowerTune_Table { + UCHAR ucRevId; + USHORT usTDP; + USHORT usConfigurableTDP; + USHORT usTDC; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usLowCACLeakage; + USHORT usHighCACLeakage; + USHORT usMaximumPowerDeliveryLimit; + USHORT usTjMax; /* For Fiji, this is also usTemperatureLimitEdge; */ + USHORT usPowerTuneDataSetID; + USHORT usEDCLimit; + USHORT usSoftwareShutdownTemp; + USHORT usClockStretchAmount; + USHORT usTemperatureLimitHotspot; /*The following are added for Fiji */ + USHORT usTemperatureLimitLiquid1; + USHORT usTemperatureLimitLiquid2; + USHORT usTemperatureLimitVrVddc; + USHORT usTemperatureLimitVrMvdd; + USHORT usTemperatureLimitPlx; + UCHAR ucLiquid1_I2C_address; /*Liquid */ + UCHAR ucLiquid2_I2C_address; + UCHAR ucLiquid_I2C_Line; + UCHAR ucVr_I2C_address; /*VR */ + UCHAR ucVr_I2C_Line; + UCHAR ucPlx_I2C_address; /*PLX */ + UCHAR ucPlx_I2C_Line; + USHORT usReserved; +} ATOM_Fiji_PowerTune_Table; + +#define ATOM_PPM_A_A 1 +#define ATOM_PPM_A_I 2 +typedef struct _ATOM_Tonga_PPM_Table { + UCHAR ucRevId; + UCHAR ucPpmDesign; /*A+I or A+A */ + USHORT usCpuCoreNumber; + ULONG ulPlatformTDP; + ULONG ulSmallACPlatformTDP; + ULONG ulPlatformTDC; + ULONG ulSmallACPlatformTDC; + ULONG ulApuTDP; + ULONG ulDGpuTDP; + ULONG ulDGpuUlvPower; + ULONG ulTjmax; +} ATOM_Tonga_PPM_Table; + +typedef struct _ATOM_Tonga_Hard_Limit_Record { + ULONG ulSCLKLimit; + ULONG ulMCLKLimit; + USHORT usVddcLimit; + USHORT usVddciLimit; + USHORT usVddgfxLimit; +} ATOM_Tonga_Hard_Limit_Record; + +typedef struct _ATOM_Tonga_Hard_Limit_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; + ATOM_Tonga_Hard_Limit_Record entries[1]; +} ATOM_Tonga_Hard_Limit_Table; + +typedef struct _ATOM_Tonga_GPIO_Table { + UCHAR ucRevId; + UCHAR ucVRHotTriggeredSclkDpmIndex; /* If VRHot signal is triggered SCLK will be limited to this DPM level */ + UCHAR ucReserve[5]; +} ATOM_Tonga_GPIO_Table; + +typedef struct _PPTable_Generic_SubTable_Header { + UCHAR ucRevId; +} PPTable_Generic_SubTable_Header; + + +#pragma pack(pop) + + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c new file mode 100644 index 0000000..3373c32 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c @@ -0,0 +1,1326 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +#include +#include + +#include "process_pptables_v1_0.h" +#include "ppatomctrl.h" +#include "atombios.h" +#include "pp_debug.h" +#include "hwmgr.h" +#include "cgs_common.h" +#include "pptable_v1_0.h" + +/** + * Private Function used during initialization. + * @param hwmgr Pointer to the hardware manager. + * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE). + * @param cap Which capability to set/reset. + */ +static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap) +{ + if (setIt) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); +} + + +/** + * Private Function used during initialization. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_caps the bit array (from BIOS) of capability bits. + * @exception the current implementation always returns 1. + */ +static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) +{ + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____), + "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____), + "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____), + "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____), + "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____), + "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY), + PHM_PlatformCaps_PowerPlaySupport + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), + PHM_PlatformCaps_BiosPowerSourceControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC), + PHM_PlatformCaps_AutomaticDCTransition + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL), + PHM_PlatformCaps_EnableMVDDControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL), + PHM_PlatformCaps_ControlVDDCI + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL), + PHM_PlatformCaps_ControlVDDGFX + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND), + PHM_PlatformCaps_DisableVoltageIsland + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), + PHM_PlatformCaps_CombinePCCWithThermalSignal + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), + PHM_PlatformCaps_LoadPostProductionFirmware + ); + + return 0; +} + +/** + * Private Function to get the PowerPlay Table Address. + */ +const void *get_powerplay_table(struct pp_hwmgr *hwmgr) +{ + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + + u16 size; + u8 frev, crev; + void *table_address = (void *)hwmgr->soft_pp_table; + + if (!table_address) { + table_address = (ATOM_Tonga_POWERPLAYTABLE *) + cgs_atom_get_data_table(hwmgr->device, + index, &size, &frev, &crev); + hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ + hwmgr->soft_pp_table_size = size; + } + + return table_address; +} + +static int get_vddc_lookup_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table **lookup_table, + const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables, + uint32_t max_levels + ) +{ + uint32_t table_size, i; + phm_ppt_v1_voltage_lookup_table *table; + phm_ppt_v1_voltage_lookup_record *record; + ATOM_Tonga_Voltage_Lookup_Record *atom_record; + + PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries), + "Invalid CAC Leakage PowerPlay Table!", return 1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; + + table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + memset(table, 0x00, table_size); + + table->count = vddc_lookup_pp_tables->ucNumEntries; + + for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) { + record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_voltage_lookup_record, + entries, table, i); + atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_Voltage_Lookup_Record, + entries, vddc_lookup_pp_tables, i); + record->us_calculated = 0; + record->us_vdd = atom_record->usVdd; + record->us_cac_low = atom_record->usCACLow; + record->us_cac_mid = atom_record->usCACMid; + record->us_cac_high = atom_record->usCACHigh; + } + + *lookup_table = table; + + return 0; +} + +/** + * Private Function used during initialization. + * Initialize Platform Power Management Parameter table + * @param hwmgr Pointer to the hardware manager. + * @param atom_ppm_table Pointer to PPM table in VBIOS + */ +static int get_platform_power_management_table( + struct pp_hwmgr *hwmgr, + ATOM_Tonga_PPM_Table *atom_ppm_table) +{ + struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL); + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (NULL == ptr) + return -ENOMEM; + + ptr->ppm_design + = atom_ppm_table->ucPpmDesign; + ptr->cpu_core_number + = atom_ppm_table->usCpuCoreNumber; + ptr->platform_tdp + = atom_ppm_table->ulPlatformTDP; + ptr->small_ac_platform_tdp + = atom_ppm_table->ulSmallACPlatformTDP; + ptr->platform_tdc + = atom_ppm_table->ulPlatformTDC; + ptr->small_ac_platform_tdc + = atom_ppm_table->ulSmallACPlatformTDC; + ptr->apu_tdp + = atom_ppm_table->ulApuTDP; + ptr->dgpu_tdp + = atom_ppm_table->ulDGpuTDP; + ptr->dgpu_ulv_power + = atom_ppm_table->ulDGpuUlvPower; + ptr->tj_max + = atom_ppm_table->ulTjmax; + + pp_table_information->ppm_parameter_table = ptr; + + return 0; +} + +/** + * Private Function used during initialization. + * Initialize TDP limits for DPM2 + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + */ +static int init_dpm_2_parameters( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + int result = 0; + struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); + ATOM_Tonga_PPM_Table *atom_ppm_table; + uint32_t disable_ppm = 0; + uint32_t disable_power_control = 0; + + pp_table_information->us_ulv_voltage_offset = + le16_to_cpu(powerplay_table->usUlvVoltageOffset); + + pp_table_information->ppm_parameter_table = NULL; + pp_table_information->vddc_lookup_table = NULL; + pp_table_information->vddgfx_lookup_table = NULL; + /* TDP limits */ + hwmgr->platform_descriptor.TDPODLimit = + le16_to_cpu(powerplay_table->usPowerControlLimit); + hwmgr->platform_descriptor.TDPAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; + hwmgr->platform_descriptor.VidMinLimit = 0; + hwmgr->platform_descriptor.VidMaxLimit = 1500000; + hwmgr->platform_descriptor.VidStep = 6250; + + disable_power_control = 0; + if (0 == disable_power_control) { + /* enable TDP overdrive (PowerControl) feature as well if supported */ + if (hwmgr->platform_descriptor.TDPODLimit != 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerControl); + } + + if (0 != powerplay_table->usVddcLookupTableOffset) { + const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable = + (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); + + result = get_vddc_lookup_table(hwmgr, + &pp_table_information->vddc_lookup_table, pVddcCACTable, 16); + } + + if (0 != powerplay_table->usVddgfxLookupTableOffset) { + const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable = + (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset)); + + result = get_vddc_lookup_table(hwmgr, + &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16); + } + + disable_ppm = 0; + if (0 == disable_ppm) { + atom_ppm_table = (ATOM_Tonga_PPM_Table *) + (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset)); + + if (0 != powerplay_table->usPPMTableOffset) { + if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnablePlatformPowerManagement); + } + } + } + + return result; +} + +static int get_valid_clk( + struct pp_hwmgr *hwmgr, + struct phm_clock_array **clk_table, + phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table + ) +{ + uint32_t table_size, i; + struct phm_clock_array *table; + phm_ppt_v1_clock_voltage_dependency_record *dep_record; + + PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(uint32_t) * clk_volt_pp_table->count; + + table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + memset(table, 0x00, table_size); + + table->count = (uint32_t)clk_volt_pp_table->count; + + for (i = 0; i < table->count; i++) { + dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, clk_volt_pp_table, i); + table->values[i] = (uint32_t)dep_record->clk; + } + *clk_table = table; + + return 0; +} + +static int get_hard_limits( + struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *limits, + ATOM_Tonga_Hard_Limit_Table const *limitable + ) +{ + PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1); + + /* currently we always take entries[0] parameters */ + limits->sclk = (uint32_t)limitable->entries[0].ulSCLKLimit; + limits->mclk = (uint32_t)limitable->entries[0].ulMCLKLimit; + limits->vddc = (uint16_t)limitable->entries[0].usVddcLimit; + limits->vddci = (uint16_t)limitable->entries[0].usVddciLimit; + limits->vddgfx = (uint16_t)limitable->entries[0].usVddgfxLimit; + + return 0; +} + +static int get_mclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table, + ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table + ) +{ + uint32_t table_size, i; + phm_ppt_v1_clock_voltage_dependency_table *mclk_table; + phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record; + ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; + + PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) + * mclk_dep_table->ucNumEntries; + + mclk_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == mclk_table) + return -ENOMEM; + + memset(mclk_table, 0x00, table_size); + + mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; + + for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { + mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, mclk_table, i); + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, i); + mclk_table_record->vddInd = mclk_dep_record->ucVddcInd; + mclk_table_record->vdd_offset = mclk_dep_record->usVddgfxOffset; + mclk_table_record->vddci = mclk_dep_record->usVddci; + mclk_table_record->mvdd = mclk_dep_record->usMvdd; + mclk_table_record->clk = mclk_dep_record->ulMclk; + } + + *pp_tonga_mclk_dep_table = mclk_table; + + return 0; +} + +static int get_sclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table, + PPTable_Generic_SubTable_Header const *sclk_dep_table + ) +{ + uint32_t table_size, i; + phm_ppt_v1_clock_voltage_dependency_table *sclk_table; + phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record; + + if (sclk_dep_table->ucRevId < 1) { + const ATOM_Tonga_SCLK_Dependency_Table *tonga_table = + (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table; + ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; + + PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) + * tonga_table->ucNumEntries; + + sclk_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == sclk_table) + return -ENOMEM; + + memset(sclk_table, 0x00, table_size); + + sclk_table->count = (uint32_t)tonga_table->ucNumEntries; + + for (i = 0; i < tonga_table->ucNumEntries; i++) { + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_SCLK_Dependency_Record, + entries, tonga_table, i); + sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, sclk_table, i); + sclk_table_record->vddInd = sclk_dep_record->ucVddInd; + sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset; + sclk_table_record->clk = sclk_dep_record->ulSclk; + sclk_table_record->cks_enable = + (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; + sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); + } + } else { + const ATOM_Polaris_SCLK_Dependency_Table *polaris_table = + (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table; + ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record; + + PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) + * polaris_table->ucNumEntries; + + sclk_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == sclk_table) + return -ENOMEM; + + memset(sclk_table, 0x00, table_size); + + sclk_table->count = (uint32_t)polaris_table->ucNumEntries; + + for (i = 0; i < polaris_table->ucNumEntries; i++) { + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Polaris_SCLK_Dependency_Record, + entries, polaris_table, i); + sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, sclk_table, i); + sclk_table_record->vddInd = sclk_dep_record->ucVddInd; + sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset; + sclk_table_record->clk = sclk_dep_record->ulSclk; + sclk_table_record->cks_enable = + (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; + sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); + sclk_table_record->sclk_offset = sclk_dep_record->ulSclkOffset; + } + } + *pp_tonga_sclk_dep_table = sclk_table; + + return 0; +} + +static int get_pcie_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_pcie_table **pp_tonga_pcie_table, + PPTable_Generic_SubTable_Header const *ptable + ) +{ + uint32_t table_size, i, pcie_count; + phm_ppt_v1_pcie_table *pcie_table; + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_pcie_record *pcie_record; + + if (ptable->ucRevId < 1) { + const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable; + ATOM_Tonga_PCIE_Record *atom_pcie_record; + + PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; + + pcie_table = kzalloc(table_size, GFP_KERNEL); + + if (pcie_table == NULL) + return -ENOMEM; + + memset(pcie_table, 0x00, table_size); + + /* + * Make sure the number of pcie entries are less than or equal to sclk dpm levels. + * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. + */ + pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; + if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) + pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; + else + printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \ + Disregarding the excess entries... \n"); + + pcie_table->count = pcie_count; + for (i = 0; i < pcie_count; i++) { + pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_pcie_record, + entries, pcie_table, i); + atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_PCIE_Record, + entries, atom_pcie_table, i); + pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; + pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth; + } + + *pp_tonga_pcie_table = pcie_table; + } else { + /* Polaris10/Polaris11 and newer. */ + const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable; + ATOM_Polaris10_PCIE_Record *atom_pcie_record; + + PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; + + pcie_table = kzalloc(table_size, GFP_KERNEL); + + if (pcie_table == NULL) + return -ENOMEM; + + memset(pcie_table, 0x00, table_size); + + /* + * Make sure the number of pcie entries are less than or equal to sclk dpm levels. + * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. + */ + pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; + if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) + pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; + else + printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \ + Disregarding the excess entries... \n"); + + pcie_table->count = pcie_count; + + for (i = 0; i < pcie_count; i++) { + pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_pcie_record, + entries, pcie_table, i); + atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Polaris10_PCIE_Record, + entries, atom_pcie_table, i); + pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; + pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth; + pcie_record->pcie_sclk = atom_pcie_record->ulPCIE_Sclk; + } + + *pp_tonga_pcie_table = pcie_table; + } + + return 0; +} + +static int get_cac_tdp_table( + struct pp_hwmgr *hwmgr, + struct phm_cac_tdp_table **cac_tdp_table, + const PPTable_Generic_SubTable_Header * table + ) +{ + uint32_t table_size; + struct phm_cac_tdp_table *tdp_table; + + table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table); + tdp_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == tdp_table) + return -ENOMEM; + + memset(tdp_table, 0x00, table_size); + + hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == hwmgr->dyn_state.cac_dtp_table) { + kfree(tdp_table); + return -ENOMEM; + } + + memset(hwmgr->dyn_state.cac_dtp_table, 0x00, table_size); + + if (table->ucRevId < 3) { + const ATOM_Tonga_PowerTune_Table *tonga_table = + (ATOM_Tonga_PowerTune_Table *)table; + tdp_table->usTDP = tonga_table->usTDP; + tdp_table->usConfigurableTDP = + tonga_table->usConfigurableTDP; + tdp_table->usTDC = tonga_table->usTDC; + tdp_table->usBatteryPowerLimit = + tonga_table->usBatteryPowerLimit; + tdp_table->usSmallPowerLimit = + tonga_table->usSmallPowerLimit; + tdp_table->usLowCACLeakage = + tonga_table->usLowCACLeakage; + tdp_table->usHighCACLeakage = + tonga_table->usHighCACLeakage; + tdp_table->usMaximumPowerDeliveryLimit = + tonga_table->usMaximumPowerDeliveryLimit; + tdp_table->usDefaultTargetOperatingTemp = + tonga_table->usTjMax; + tdp_table->usTargetOperatingTemp = + tonga_table->usTjMax; /*Set the initial temp to the same as default */ + tdp_table->usPowerTuneDataSetID = + tonga_table->usPowerTuneDataSetID; + tdp_table->usSoftwareShutdownTemp = + tonga_table->usSoftwareShutdownTemp; + tdp_table->usClockStretchAmount = + tonga_table->usClockStretchAmount; + } else { /* Fiji and newer */ + const ATOM_Fiji_PowerTune_Table *fijitable = + (ATOM_Fiji_PowerTune_Table *)table; + tdp_table->usTDP = fijitable->usTDP; + tdp_table->usConfigurableTDP = fijitable->usConfigurableTDP; + tdp_table->usTDC = fijitable->usTDC; + tdp_table->usBatteryPowerLimit = fijitable->usBatteryPowerLimit; + tdp_table->usSmallPowerLimit = fijitable->usSmallPowerLimit; + tdp_table->usLowCACLeakage = fijitable->usLowCACLeakage; + tdp_table->usHighCACLeakage = fijitable->usHighCACLeakage; + tdp_table->usMaximumPowerDeliveryLimit = + fijitable->usMaximumPowerDeliveryLimit; + tdp_table->usDefaultTargetOperatingTemp = + fijitable->usTjMax; + tdp_table->usTargetOperatingTemp = + fijitable->usTjMax; /*Set the initial temp to the same as default */ + tdp_table->usPowerTuneDataSetID = + fijitable->usPowerTuneDataSetID; + tdp_table->usSoftwareShutdownTemp = + fijitable->usSoftwareShutdownTemp; + tdp_table->usClockStretchAmount = + fijitable->usClockStretchAmount; + tdp_table->usTemperatureLimitHotspot = + fijitable->usTemperatureLimitHotspot; + tdp_table->usTemperatureLimitLiquid1 = + fijitable->usTemperatureLimitLiquid1; + tdp_table->usTemperatureLimitLiquid2 = + fijitable->usTemperatureLimitLiquid2; + tdp_table->usTemperatureLimitVrVddc = + fijitable->usTemperatureLimitVrVddc; + tdp_table->usTemperatureLimitVrMvdd = + fijitable->usTemperatureLimitVrMvdd; + tdp_table->usTemperatureLimitPlx = + fijitable->usTemperatureLimitPlx; + tdp_table->ucLiquid1_I2C_address = + fijitable->ucLiquid1_I2C_address; + tdp_table->ucLiquid2_I2C_address = + fijitable->ucLiquid2_I2C_address; + tdp_table->ucLiquid_I2C_Line = + fijitable->ucLiquid_I2C_Line; + tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address; + tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line; + tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address; + tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line; + } + + *cac_tdp_table = tdp_table; + + return 0; +} + +static int get_mm_clock_voltage_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table, + const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table + ) +{ + uint32_t table_size, i; + const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record; + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; + phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record; + + PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) + * mm_dependency_table->ucNumEntries; + mm_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == mm_table) + return -ENOMEM; + + memset(mm_table, 0x00, table_size); + + mm_table->count = mm_dependency_table->ucNumEntries; + + for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { + mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MM_Dependency_Record, + entries, mm_dependency_table, i); + mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_mm_clock_voltage_dependency_record, + entries, mm_table, i); + mm_table_record->vddcInd = mm_dependency_record->ucVddcInd; + mm_table_record->vddgfx_offset = mm_dependency_record->usVddgfxOffset; + mm_table_record->aclk = mm_dependency_record->ulAClk; + mm_table_record->samclock = mm_dependency_record->ulSAMUClk; + mm_table_record->eclk = mm_dependency_record->ulEClk; + mm_table_record->vclk = mm_dependency_record->ulVClk; + mm_table_record->dclk = mm_dependency_record->ulDClk; + } + + *tonga_mm_table = mm_table; + + return 0; +} + +/** + * Private Function used during initialization. + * Initialize clock voltage dependency + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + */ +static int init_clock_voltage_dependency( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + int result = 0; + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table = + (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); + const PPTable_Generic_SubTable_Header *pPowerTuneTable = + (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); + const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = + (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); + const PPTable_Generic_SubTable_Header *sclk_dep_table = + (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); + const ATOM_Tonga_Hard_Limit_Table *pHardLimits = + (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usHardLimitTableOffset)); + const PPTable_Generic_SubTable_Header *pcie_table = + (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPCIETableOffset)); + + pp_table_information->vdd_dep_on_sclk = NULL; + pp_table_information->vdd_dep_on_mclk = NULL; + pp_table_information->mm_dep_table = NULL; + pp_table_information->pcie_table = NULL; + + if (powerplay_table->usMMDependencyTableOffset != 0) + result = get_mm_clock_voltage_table(hwmgr, + &pp_table_information->mm_dep_table, mm_dependency_table); + + if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0) + result = get_cac_tdp_table(hwmgr, + &pp_table_information->cac_dtp_table, pPowerTuneTable); + + if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0) + result = get_sclk_voltage_dependency_table(hwmgr, + &pp_table_information->vdd_dep_on_sclk, sclk_dep_table); + + if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0) + result = get_mclk_voltage_dependency_table(hwmgr, + &pp_table_information->vdd_dep_on_mclk, mclk_dep_table); + + if (result == 0 && powerplay_table->usPCIETableOffset != 0) + result = get_pcie_table(hwmgr, + &pp_table_information->pcie_table, pcie_table); + + if (result == 0 && powerplay_table->usHardLimitTableOffset != 0) + result = get_hard_limits(hwmgr, + &pp_table_information->max_clock_voltage_on_dc, pHardLimits); + + hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = + pp_table_information->max_clock_voltage_on_dc.sclk; + hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = + pp_table_information->max_clock_voltage_on_dc.mclk; + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = + pp_table_information->max_clock_voltage_on_dc.vddc; + hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = + pp_table_information->max_clock_voltage_on_dc.vddci; + + if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk) + && (0 != pp_table_information->vdd_dep_on_mclk->count)) + result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values, + pp_table_information->vdd_dep_on_mclk); + + if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk) + && (0 != pp_table_information->vdd_dep_on_sclk->count)) + result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values, + pp_table_information->vdd_dep_on_sclk); + + return result; +} + +/** Retrieves the (signed) Overdrive limits from VBIOS. + * The max engine clock, memory clock and max temperature come from the firmware info table. + * + * The information is placed into the platform descriptor. + * + * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated. + * @param powerplay_table the address of the PowerPlay table. + * + * @return 1 as long as the firmware info table was present and of a supported version. + */ +static int init_over_drive_limits( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table) +{ + hwmgr->platform_descriptor.overdriveLimit.engineClock = + le16_to_cpu(powerplay_table->ulMaxODEngineClock); + hwmgr->platform_descriptor.overdriveLimit.memoryClock = + le16_to_cpu(powerplay_table->ulMaxODMemoryClock); + + hwmgr->platform_descriptor.minOverdriveVDDC = 0; + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + + if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 \ + && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ACOverdriveSupport); + } + + return 0; +} + +/** + * Private Function used during initialization. + * Inspect the PowerPlay table for obvious signs of corruption. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + * @exception This implementation always returns 1. + */ +static int init_thermal_controller( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + const PPTable_Generic_SubTable_Header *fan_table; + ATOM_Tonga_Thermal_Controller *thermal_controller; + + thermal_controller = (ATOM_Tonga_Thermal_Controller *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usThermalControllerOffset)); + PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset), + "Thermal controller table not set!", return -1); + + hwmgr->thermal_controller.ucType = thermal_controller->ucType; + hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; + hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; + + hwmgr->thermal_controller.fanInfo.bNoFan = + (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN)); + + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = + thermal_controller->ucFanParameters & + ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + + hwmgr->thermal_controller.fanInfo.ulMinRPM + = thermal_controller->ucFanMinRPM * 100UL; + hwmgr->thermal_controller.fanInfo.ulMaxRPM + = thermal_controller->ucFanMaxRPM * 100UL; + + set_hw_cap( + hwmgr, + ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, + PHM_PlatformCaps_ThermalController + ); + + if (0 == powerplay_table->usFanTableOffset) + return 0; + + fan_table = (const PPTable_Generic_SubTable_Header *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usFanTableOffset)); + + PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset), + "Fan table not set!", return -1); + PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId), + "Unsupported fan table format!", return -1); + + hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay + = 100000; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + if (fan_table->ucRevId < 8) { + const ATOM_Tonga_Fan_Table *tonga_fan_table = + (ATOM_Tonga_Fan_Table *)fan_table; + hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst + = tonga_fan_table->ucTHyst; + hwmgr->thermal_controller.advanceFanControlParameters.usTMin + = tonga_fan_table->usTMin; + hwmgr->thermal_controller.advanceFanControlParameters.usTMed + = tonga_fan_table->usTMed; + hwmgr->thermal_controller.advanceFanControlParameters.usTHigh + = tonga_fan_table->usTHigh; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin + = tonga_fan_table->usPWMMin; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed + = tonga_fan_table->usPWMMed; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh + = tonga_fan_table->usPWMHigh; + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = 10900; /* hard coded */ + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = tonga_fan_table->usTMax; + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode + = tonga_fan_table->ucFanControlMode; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM + = tonga_fan_table->usFanPWMMax; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity + = 4836; + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity + = tonga_fan_table->usFanOutputSensitivity; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM + = tonga_fan_table->usFanRPMMax; + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit + = (tonga_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature + = tonga_fan_table->ucTargetTemperature; + hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit + = tonga_fan_table->ucMinimumPWMLimit; + } else { + const ATOM_Fiji_Fan_Table *fiji_fan_table = + (ATOM_Fiji_Fan_Table *)fan_table; + hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst + = fiji_fan_table->ucTHyst; + hwmgr->thermal_controller.advanceFanControlParameters.usTMin + = fiji_fan_table->usTMin; + hwmgr->thermal_controller.advanceFanControlParameters.usTMed + = fiji_fan_table->usTMed; + hwmgr->thermal_controller.advanceFanControlParameters.usTHigh + = fiji_fan_table->usTHigh; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin + = fiji_fan_table->usPWMMin; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed + = fiji_fan_table->usPWMMed; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh + = fiji_fan_table->usPWMHigh; + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = fiji_fan_table->usTMax; + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode + = fiji_fan_table->ucFanControlMode; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM + = fiji_fan_table->usFanPWMMax; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity + = 4836; + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity + = fiji_fan_table->usFanOutputSensitivity; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM + = fiji_fan_table->usFanRPMMax; + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit + = (fiji_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature + = fiji_fan_table->ucTargetTemperature; + hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit + = fiji_fan_table->ucMinimumPWMLimit; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge + = fiji_fan_table->usFanGainEdge; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot + = fiji_fan_table->usFanGainHotspot; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid + = fiji_fan_table->usFanGainLiquid; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc + = fiji_fan_table->usFanGainVrVddc; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd + = fiji_fan_table->usFanGainVrMvdd; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx + = fiji_fan_table->usFanGainPlx; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm + = fiji_fan_table->usFanGainHbm; + } + + return 0; +} + +/** + * Private Function used during initialization. + * Inspect the PowerPlay table for obvious signs of corruption. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + * @exception 2 if the powerplay table is incorrect. + */ +static int check_powerplay_tables( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + const ATOM_Tonga_State_Array *state_arrays; + + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <= + powerplay_table->sHeader.ucTableFormatRevision), + "Unsupported PPTable format!", return -1); + PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset), + "State table is not set!", return -1); + PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize), + "Invalid PowerPlay Table!", return -1); + PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + return 0; +} + +int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr) +{ + int result = 0; + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table; + + hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL); + + PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable), + "Failed to allocate hwmgr->pptable!", return -ENOMEM); + + memset(hwmgr->pptable, 0x00, sizeof(struct phm_ppt_v1_information)); + + powerplay_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((NULL != powerplay_table), + "Missing PowerPlay Table!", return -1); + + result = check_powerplay_tables(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "check_powerplay_tables failed", return result); + + result = set_platform_caps(hwmgr, + le32_to_cpu(powerplay_table->ulPlatformCaps)); + + PP_ASSERT_WITH_CODE((result == 0), + "set_platform_caps failed", return result); + + result = init_thermal_controller(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_thermal_controller failed", return result); + + result = init_over_drive_limits(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_over_drive_limits failed", return result); + + result = init_clock_voltage_dependency(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_clock_voltage_dependency failed", return result); + + result = init_dpm_2_parameters(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_dpm_2_parameters failed", return result); + + return result; +} + +int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + kfree(pp_table_information->vdd_dep_on_sclk); + pp_table_information->vdd_dep_on_sclk = NULL; + + kfree(pp_table_information->vdd_dep_on_mclk); + pp_table_information->vdd_dep_on_mclk = NULL; + + kfree(pp_table_information->valid_mclk_values); + pp_table_information->valid_mclk_values = NULL; + + kfree(pp_table_information->valid_sclk_values); + pp_table_information->valid_sclk_values = NULL; + + kfree(pp_table_information->vddc_lookup_table); + pp_table_information->vddc_lookup_table = NULL; + + kfree(pp_table_information->vddgfx_lookup_table); + pp_table_information->vddgfx_lookup_table = NULL; + + kfree(pp_table_information->mm_dep_table); + pp_table_information->mm_dep_table = NULL; + + kfree(pp_table_information->cac_dtp_table); + pp_table_information->cac_dtp_table = NULL; + + kfree(hwmgr->dyn_state.cac_dtp_table); + hwmgr->dyn_state.cac_dtp_table = NULL; + + kfree(pp_table_information->ppm_parameter_table); + pp_table_information->ppm_parameter_table = NULL; + + kfree(pp_table_information->pcie_table); + pp_table_information->pcie_table = NULL; + + kfree(hwmgr->pptable); + hwmgr->pptable = NULL; + + return 0; +} + +const struct pp_table_func pptable_v1_0_funcs = { + .pptable_init = pp_tables_v1_0_initialize, + .pptable_fini = pp_tables_v1_0_uninitialize, +}; + +int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr) +{ + ATOM_Tonga_State_Array const *state_arrays; + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((NULL != pp_table), + "Missing PowerPlay Table!", return -1); + PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >= + ATOM_Tonga_TABLE_REVISION_TONGA), + "Incorrect PowerPlay table revision!", return -1); + + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + return (uint32_t)(state_arrays->ucNumEntries); +} + +/** +* Private function to convert flags stored in the BIOS to software flags in PowerPlay. +*/ +static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, + uint16_t classification, uint16_t classification2) +{ + uint32_t result = 0; + + if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) + result |= PP_StateClassificationFlag_Boot; + + if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) + result |= PP_StateClassificationFlag_Thermal; + + if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + result |= PP_StateClassificationFlag_LimitedPowerSource; + + if (classification & ATOM_PPLIB_CLASSIFICATION_REST) + result |= PP_StateClassificationFlag_Rest; + + if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) + result |= PP_StateClassificationFlag_Forced; + + if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) + result |= PP_StateClassificationFlag_ACPI; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + result |= PP_StateClassificationFlag_LimitedPowerSource_2; + + return result; +} + +static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr) +{ + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + const ATOM_Tonga_VCE_State_Table *vce_state_table = + (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pp_table) + le16_to_cpu(pp_table->usVCEStateTableOffset)); + + if (vce_state_table == NULL) + return 0; + + return vce_state_table->ucNumEntries; +} + +static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i, + struct pp_vce_state *vce_state, void **clock_info, uint32_t *flag) +{ + const ATOM_Tonga_VCE_State_Record *vce_state_record; + ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; + ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; + ATOM_Tonga_MM_Dependency_Record *mm_dep_record; + const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr); + const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usVCEStateTableOffset)); + const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usSclkDependencyTableOffset)); + const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usMclkDependencyTableOffset)); + const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usMMDependencyTableOffset)); + + PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries), + "Requested state entry ID is out of range!", + return -EINVAL); + + vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_VCE_State_Record, + entries, vce_state_table, i); + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_SCLK_Dependency_Record, + entries, sclk_dep_table, + vce_state_record->ucSCLKIndex); + mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MM_Dependency_Record, + entries, mm_dep_table, + vce_state_record->ucVCEClockIndex); + *flag = vce_state_record->ucFlag; + + vce_state->evclk = mm_dep_record->ulEClk; + vce_state->ecclk = mm_dep_record->ulEClk; + vce_state->sclk = sclk_dep_record->ulSclk; + + if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries) + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, + mclk_dep_table->ucNumEntries - 1); + else + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, + vce_state_record->ucMCLKIndex); + + vce_state->mclk = mclk_dep_record->ulMclk; + return 0; +} + +/** +* Create a Power State out of an entry in the PowerPlay table. +* This function is called by the hardware back-end. +* @param hwmgr Pointer to the hardware manager. +* @param entry_index The index of the entry to be extracted from the table. +* @param power_state The address of the PowerState instance being created. +* @return -1 if the entry cannot be retrieved. +*/ +int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, + uint32_t entry_index, struct pp_power_state *power_state, + int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)) +{ + int result = 0; + const ATOM_Tonga_State_Array *state_arrays; + const ATOM_Tonga_State *state_entry; + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + int i, j; + uint32_t flags = 0; + + PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;); + power_state->classification.bios_index = entry_index; + + if (pp_table->sHeader.ucTableFormatRevision >= + ATOM_Tonga_TABLE_REVISION_TONGA) { + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset), + "Invalid PowerPlay Table State Array Offset.", return -1); + PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), + "Invalid PowerPlay Table State Array.", return -1); + PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), + "Invalid PowerPlay Table State Array Entry.", return -1); + + state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_State, entries, + state_arrays, entry_index); + + result = call_back_func(hwmgr, (void *)state_entry, power_state, + (void *)pp_table, + make_classification_flags(hwmgr, + le16_to_cpu(state_entry->usClassification), + le16_to_cpu(state_entry->usClassification2))); + } + + if (!result && (power_state->classification.flags & + PP_StateClassificationFlag_Boot)) + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); + + hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr); + + if ((i != 0) && (i <= PP_MAX_VCE_LEVELS)) { + for (j = 0; j < i; j++) + ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags); + } + + return result; +} + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h new file mode 100644 index 0000000..b9710ab --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _PROCESSPPTABLES_V1_0_H +#define _PROCESSPPTABLES_V1_0_H + +#include "hwmgr.h" + +extern const struct pp_table_func pptable_v1_0_funcs; +extern int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr); +extern int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t entry_index, + struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)); + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c index cf58f22..42783bf 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -30,8 +30,8 @@ #include "tonga_hwmgr.h" #include "pptable.h" #include "processpptables.h" -#include "tonga_processpptables.h" -#include "tonga_pptable.h" +#include "process_pptables_v1_0.h" +#include "pptable_v1_0.h" #include "pp_debug.h" #include "tonga_ppsmc.h" #include "cgs_common.h" @@ -5164,7 +5164,7 @@ static int tonga_get_pp_table_entry(struct pp_hwmgr *hwmgr, tonga_ps = cast_phw_tonga_power_state(&(ps->hardware)); - result = tonga_get_powerplay_table_entry(hwmgr, entry_index, ps, + result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, ps, tonga_get_pp_table_entry_callback_func); /* This is the earliest time we have all the dependency table and the VBIOS boot state @@ -6328,7 +6328,7 @@ static const struct pp_hwmgr_func tonga_hwmgr_funcs = { .get_sclk = tonga_dpm_get_sclk, .patch_boot_state = tonga_dpm_patch_boot_state, .get_pp_table_entry = tonga_get_pp_table_entry, - .get_num_of_pp_table_entries = tonga_get_number_of_powerplay_table_entries, + .get_num_of_pp_table_entries = get_number_of_powerplay_table_entries_v1_0, .print_current_perforce_level = tonga_print_current_perforce_level, .powerdown_uvd = tonga_phm_powerdown_uvd, .powergate_uvd = tonga_phm_powergate_uvd, @@ -6364,7 +6364,7 @@ static const struct pp_hwmgr_func tonga_hwmgr_funcs = { int tonga_hwmgr_init(struct pp_hwmgr *hwmgr) { hwmgr->hwmgr_func = &tonga_hwmgr_funcs; - hwmgr->pptable_func = &tonga_pptable_funcs; + hwmgr->pptable_func = &pptable_v1_0_funcs; pp_tonga_thermal_initialize(hwmgr); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h deleted file mode 100644 index 1e870f5..0000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef TONGA_PPTABLE_H -#define TONGA_PPTABLE_H - -/** \file - * This is a PowerPlay table header file - */ -#pragma pack(push, 1) - -#include "hwmgr.h" - -#define ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f -#define ATOM_TONGA_PP_FANPARAMETERS_NOFAN 0x80 /* No fan is connected to this controller. */ - -#define ATOM_TONGA_PP_THERMALCONTROLLER_NONE 0 -#define ATOM_TONGA_PP_THERMALCONTROLLER_LM96163 17 -#define ATOM_TONGA_PP_THERMALCONTROLLER_TONGA 21 -#define ATOM_TONGA_PP_THERMALCONTROLLER_FIJI 22 - -/* - * Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. - * We probably should reserve the bit 0x80 for this use. - * To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). - * The driver can pick the correct internal controller based on the ASIC. - */ - -#define ATOM_TONGA_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 /* ADT7473 Fan Control + Internal Thermal Controller */ -#define ATOM_TONGA_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D /* EMC2103 Fan Control + Internal Thermal Controller */ - -/*/* ATOM_TONGA_POWERPLAYTABLE::ulPlatformCaps */ -#define ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL 0x1 /* This cap indicates whether vddgfx will be a separated power rail. */ -#define ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY 0x2 /* This cap indicates whether this is a mobile part and CCC need to show Powerplay page. */ -#define ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x4 /* This cap indicates whether power source notificaiton is done by SBIOS directly. */ -#define ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND 0x8 /* Enable the option to overwrite voltage island feature to be disabled, regardless of VddGfx power rail support. */ -#define ____RETIRE16____ 0x10 -#define ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC 0x20 /* This cap indicates whether power source notificaiton is done by GPIO directly. */ -#define ____RETIRE64____ 0x40 -#define ____RETIRE128____ 0x80 -#define ____RETIRE256____ 0x100 -#define ____RETIRE512____ 0x200 -#define ____RETIRE1024____ 0x400 -#define ____RETIRE2048____ 0x800 -#define ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL 0x1000 /* This cap indicates dynamic MVDD is required. Uncheck to disable it. */ -#define ____RETIRE2000____ 0x2000 -#define ____RETIRE4000____ 0x4000 -#define ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 /* This cap indicates dynamic VDDCI is required. Uncheck to disable it. */ -#define ____RETIRE10000____ 0x10000 -#define ATOM_TONGA_PP_PLATFORM_CAP_BACO 0x20000 /* Enable to indicate the driver supports BACO state. */ - -#define ATOM_TONGA_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17 0x100000 /* Enable to indicate the driver supports thermal2GPIO17. */ -#define ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x1000000 /* Enable to indicate if thermal and PCC are sharing the same GPIO */ -#define ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE 0x2000000 - -/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */ -#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 -#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 -#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 -#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 -#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 -#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 -/* 2, 4, 6, 7 are reserved */ - -#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 -#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 -#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 -#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 -#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 -#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 - -/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */ -#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 - -#define ATOM_Tonga_DISALLOW_ON_DC 0x00004000 -#define ATOM_Tonga_ENABLE_VARIBRIGHT 0x00008000 - -#define ATOM_Tonga_TABLE_REVISION_TONGA 7 - -typedef struct _ATOM_Tonga_POWERPLAYTABLE { - ATOM_COMMON_TABLE_HEADER sHeader; - - UCHAR ucTableRevision; - USHORT usTableSize; /*the size of header structure */ - - ULONG ulGoldenPPID; - ULONG ulGoldenRevision; - USHORT usFormatID; - - USHORT usVoltageTime; /*in microseconds */ - ULONG ulPlatformCaps; /*See ATOM_Tonga_CAPS_* */ - - ULONG ulMaxODEngineClock; /*For Overdrive. */ - ULONG ulMaxODMemoryClock; /*For Overdrive. */ - - USHORT usPowerControlLimit; - USHORT usUlvVoltageOffset; /*in mv units */ - - USHORT usStateArrayOffset; /*points to ATOM_Tonga_State_Array */ - USHORT usFanTableOffset; /*points to ATOM_Tonga_Fan_Table */ - USHORT usThermalControllerOffset; /*points to ATOM_Tonga_Thermal_Controller */ - USHORT usReserv; /*CustomThermalPolicy removed for Tonga. Keep this filed as reserved. */ - - USHORT usMclkDependencyTableOffset; /*points to ATOM_Tonga_MCLK_Dependency_Table */ - USHORT usSclkDependencyTableOffset; /*points to ATOM_Tonga_SCLK_Dependency_Table */ - USHORT usVddcLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ - USHORT usVddgfxLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ - - USHORT usMMDependencyTableOffset; /*points to ATOM_Tonga_MM_Dependency_Table */ - - USHORT usVCEStateTableOffset; /*points to ATOM_Tonga_VCE_State_Table; */ - - USHORT usPPMTableOffset; /*points to ATOM_Tonga_PPM_Table */ - USHORT usPowerTuneTableOffset; /*points to ATOM_PowerTune_Table */ - - USHORT usHardLimitTableOffset; /*points to ATOM_Tonga_Hard_Limit_Table */ - - USHORT usPCIETableOffset; /*points to ATOM_Tonga_PCIE_Table */ - - USHORT usGPIOTableOffset; /*points to ATOM_Tonga_GPIO_Table */ - - USHORT usReserved[6]; /*TODO: modify reserved size to fit structure aligning */ -} ATOM_Tonga_POWERPLAYTABLE; - -typedef struct _ATOM_Tonga_State { - UCHAR ucEngineClockIndexHigh; - UCHAR ucEngineClockIndexLow; - - UCHAR ucMemoryClockIndexHigh; - UCHAR ucMemoryClockIndexLow; - - UCHAR ucPCIEGenLow; - UCHAR ucPCIEGenHigh; - - UCHAR ucPCIELaneLow; - UCHAR ucPCIELaneHigh; - - USHORT usClassification; - ULONG ulCapsAndSettings; - USHORT usClassification2; - UCHAR ucUnused[4]; -} ATOM_Tonga_State; - -typedef struct _ATOM_Tonga_State_Array { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_State entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_State_Array; - -typedef struct _ATOM_Tonga_MCLK_Dependency_Record { - UCHAR ucVddcInd; /* Vddc voltage */ - USHORT usVddci; - USHORT usVddgfxOffset; /* Offset relative to Vddc voltage */ - USHORT usMvdd; - ULONG ulMclk; - USHORT usReserved; -} ATOM_Tonga_MCLK_Dependency_Record; - -typedef struct _ATOM_Tonga_MCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_MCLK_Dependency_Table; - -typedef struct _ATOM_Tonga_SCLK_Dependency_Record { - UCHAR ucVddInd; /* Base voltage */ - USHORT usVddcOffset; /* Offset relative to base voltage */ - ULONG ulSclk; - USHORT usEdcCurrent; - UCHAR ucReliabilityTemperature; - UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ -} ATOM_Tonga_SCLK_Dependency_Record; - -typedef struct _ATOM_Tonga_SCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_SCLK_Dependency_Table; - -typedef struct _ATOM_Polaris_SCLK_Dependency_Record { - UCHAR ucVddInd; /* Base voltage */ - USHORT usVddcOffset; /* Offset relative to base voltage */ - ULONG ulSclk; - USHORT usEdcCurrent; - UCHAR ucReliabilityTemperature; - UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ - ULONG ulSclkOffset; -} ATOM_Polaris_SCLK_Dependency_Record; - -typedef struct _ATOM_Polaris_SCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Polaris_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Polaris_SCLK_Dependency_Table; - -typedef struct _ATOM_Tonga_PCIE_Record { - UCHAR ucPCIEGenSpeed; - UCHAR usPCIELaneWidth; - UCHAR ucReserved[2]; -} ATOM_Tonga_PCIE_Record; - -typedef struct _ATOM_Tonga_PCIE_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_PCIE_Table; - -typedef struct _ATOM_Polaris10_PCIE_Record { - UCHAR ucPCIEGenSpeed; - UCHAR usPCIELaneWidth; - UCHAR ucReserved[2]; - ULONG ulPCIE_Sclk; -} ATOM_Polaris10_PCIE_Record; - -typedef struct _ATOM_Polaris10_PCIE_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Polaris10_PCIE_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Polaris10_PCIE_Table; - - -typedef struct _ATOM_Tonga_MM_Dependency_Record { - UCHAR ucVddcInd; /* VDDC voltage */ - USHORT usVddgfxOffset; /* Offset relative to VDDC voltage */ - ULONG ulDClk; /* UVD D-clock */ - ULONG ulVClk; /* UVD V-clock */ - ULONG ulEClk; /* VCE clock */ - ULONG ulAClk; /* ACP clock */ - ULONG ulSAMUClk; /* SAMU clock */ -} ATOM_Tonga_MM_Dependency_Record; - -typedef struct _ATOM_Tonga_MM_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_MM_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_MM_Dependency_Table; - -typedef struct _ATOM_Tonga_Voltage_Lookup_Record { - USHORT usVdd; /* Base voltage */ - USHORT usCACLow; - USHORT usCACMid; - USHORT usCACHigh; -} ATOM_Tonga_Voltage_Lookup_Record; - -typedef struct _ATOM_Tonga_Voltage_Lookup_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_Voltage_Lookup_Table; - -typedef struct _ATOM_Tonga_Fan_Table { - UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ - UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ - USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ - USHORT usTMed; /* The middle temperature where we change slopes. */ - USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ - USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ - USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ - USHORT usPWMHigh; /* The PWM value at THigh. */ - USHORT usTMax; /* The max temperature */ - UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ - USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ - USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ - USHORT usFanRPMMax; /* The default value in RPM */ - ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ - UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ - UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ - USHORT usReserved; -} ATOM_Tonga_Fan_Table; - -typedef struct _ATOM_Fiji_Fan_Table { - UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ - UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ - USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ - USHORT usTMed; /* The middle temperature where we change slopes. */ - USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ - USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ - USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ - USHORT usPWMHigh; /* The PWM value at THigh. */ - USHORT usTMax; /* The max temperature */ - UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ - USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ - USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ - USHORT usFanRPMMax; /* The default value in RPM */ - ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ - UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ - UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ - USHORT usFanGainEdge; - USHORT usFanGainHotspot; - USHORT usFanGainLiquid; - USHORT usFanGainVrVddc; - USHORT usFanGainVrMvdd; - USHORT usFanGainPlx; - USHORT usFanGainHbm; - USHORT usReserved; -} ATOM_Fiji_Fan_Table; - -typedef struct _ATOM_Tonga_Thermal_Controller { - UCHAR ucRevId; - UCHAR ucType; /* one of ATOM_TONGA_PP_THERMALCONTROLLER_* */ - UCHAR ucI2cLine; /* as interpreted by DAL I2C */ - UCHAR ucI2cAddress; - UCHAR ucFanParameters; /* Fan Control Parameters. */ - UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only. */ - UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only. */ - UCHAR ucReserved; - UCHAR ucFlags; /* to be defined */ -} ATOM_Tonga_Thermal_Controller; - -typedef struct _ATOM_Tonga_VCE_State_Record { - UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Tonga_MM_Dependency_Table' type */ - UCHAR ucFlag; /* 2 bits indicates memory p-states */ - UCHAR ucSCLKIndex; /*index into ATOM_Tonga_SCLK_Dependency_Table */ - UCHAR ucMCLKIndex; /*index into ATOM_Tonga_MCLK_Dependency_Table */ -} ATOM_Tonga_VCE_State_Record; - -typedef struct _ATOM_Tonga_VCE_State_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; - ATOM_Tonga_VCE_State_Record entries[1]; -} ATOM_Tonga_VCE_State_Table; - -typedef struct _ATOM_Tonga_PowerTune_Table { - UCHAR ucRevId; - USHORT usTDP; - USHORT usConfigurableTDP; - USHORT usTDC; - USHORT usBatteryPowerLimit; - USHORT usSmallPowerLimit; - USHORT usLowCACLeakage; - USHORT usHighCACLeakage; - USHORT usMaximumPowerDeliveryLimit; - USHORT usTjMax; - USHORT usPowerTuneDataSetID; - USHORT usEDCLimit; - USHORT usSoftwareShutdownTemp; - USHORT usClockStretchAmount; - USHORT usReserve[2]; -} ATOM_Tonga_PowerTune_Table; - -typedef struct _ATOM_Fiji_PowerTune_Table { - UCHAR ucRevId; - USHORT usTDP; - USHORT usConfigurableTDP; - USHORT usTDC; - USHORT usBatteryPowerLimit; - USHORT usSmallPowerLimit; - USHORT usLowCACLeakage; - USHORT usHighCACLeakage; - USHORT usMaximumPowerDeliveryLimit; - USHORT usTjMax; /* For Fiji, this is also usTemperatureLimitEdge; */ - USHORT usPowerTuneDataSetID; - USHORT usEDCLimit; - USHORT usSoftwareShutdownTemp; - USHORT usClockStretchAmount; - USHORT usTemperatureLimitHotspot; /*The following are added for Fiji */ - USHORT usTemperatureLimitLiquid1; - USHORT usTemperatureLimitLiquid2; - USHORT usTemperatureLimitVrVddc; - USHORT usTemperatureLimitVrMvdd; - USHORT usTemperatureLimitPlx; - UCHAR ucLiquid1_I2C_address; /*Liquid */ - UCHAR ucLiquid2_I2C_address; - UCHAR ucLiquid_I2C_Line; - UCHAR ucVr_I2C_address; /*VR */ - UCHAR ucVr_I2C_Line; - UCHAR ucPlx_I2C_address; /*PLX */ - UCHAR ucPlx_I2C_Line; - USHORT usReserved; -} ATOM_Fiji_PowerTune_Table; - -#define ATOM_PPM_A_A 1 -#define ATOM_PPM_A_I 2 -typedef struct _ATOM_Tonga_PPM_Table { - UCHAR ucRevId; - UCHAR ucPpmDesign; /*A+I or A+A */ - USHORT usCpuCoreNumber; - ULONG ulPlatformTDP; - ULONG ulSmallACPlatformTDP; - ULONG ulPlatformTDC; - ULONG ulSmallACPlatformTDC; - ULONG ulApuTDP; - ULONG ulDGpuTDP; - ULONG ulDGpuUlvPower; - ULONG ulTjmax; -} ATOM_Tonga_PPM_Table; - -typedef struct _ATOM_Tonga_Hard_Limit_Record { - ULONG ulSCLKLimit; - ULONG ulMCLKLimit; - USHORT usVddcLimit; - USHORT usVddciLimit; - USHORT usVddgfxLimit; -} ATOM_Tonga_Hard_Limit_Record; - -typedef struct _ATOM_Tonga_Hard_Limit_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; - ATOM_Tonga_Hard_Limit_Record entries[1]; -} ATOM_Tonga_Hard_Limit_Table; - -typedef struct _ATOM_Tonga_GPIO_Table { - UCHAR ucRevId; - UCHAR ucVRHotTriggeredSclkDpmIndex; /* If VRHot signal is triggered SCLK will be limited to this DPM level */ - UCHAR ucReserve[5]; -} ATOM_Tonga_GPIO_Table; - -typedef struct _PPTable_Generic_SubTable_Header { - UCHAR ucRevId; -} PPTable_Generic_SubTable_Header; - - -#pragma pack(pop) - - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c deleted file mode 100644 index 0f3dad3..0000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c +++ /dev/null @@ -1,1326 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include -#include -#include - -#include "tonga_processpptables.h" -#include "ppatomctrl.h" -#include "atombios.h" -#include "pp_debug.h" -#include "hwmgr.h" -#include "cgs_common.h" -#include "tonga_pptable.h" - -/** - * Private Function used during initialization. - * @param hwmgr Pointer to the hardware manager. - * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE). - * @param cap Which capability to set/reset. - */ -static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap) -{ - if (setIt) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); -} - - -/** - * Private Function used during initialization. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_caps the bit array (from BIOS) of capability bits. - * @exception the current implementation always returns 1. - */ -static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) -{ - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____), - "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue); - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____), - "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue); - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____), - "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue); - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____), - "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue); - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____), - "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY), - PHM_PlatformCaps_PowerPlaySupport - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), - PHM_PlatformCaps_BiosPowerSourceControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC), - PHM_PlatformCaps_AutomaticDCTransition - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL), - PHM_PlatformCaps_EnableMVDDControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL), - PHM_PlatformCaps_ControlVDDCI - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL), - PHM_PlatformCaps_ControlVDDGFX - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO), - PHM_PlatformCaps_BACO - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND), - PHM_PlatformCaps_DisableVoltageIsland - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), - PHM_PlatformCaps_CombinePCCWithThermalSignal - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), - PHM_PlatformCaps_LoadPostProductionFirmware - ); - - return 0; -} - -/** - * Private Function to get the PowerPlay Table Address. - */ -const void *get_powerplay_table(struct pp_hwmgr *hwmgr) -{ - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - - u16 size; - u8 frev, crev; - void *table_address = (void *)hwmgr->soft_pp_table; - - if (!table_address) { - table_address = (ATOM_Tonga_POWERPLAYTABLE *) - cgs_atom_get_data_table(hwmgr->device, - index, &size, &frev, &crev); - hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ - hwmgr->soft_pp_table_size = size; - } - - return table_address; -} - -static int get_vddc_lookup_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_voltage_lookup_table **lookup_table, - const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables, - uint32_t max_levels - ) -{ - uint32_t table_size, i; - phm_ppt_v1_voltage_lookup_table *table; - phm_ppt_v1_voltage_lookup_record *record; - ATOM_Tonga_Voltage_Lookup_Record *atom_record; - - PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries), - "Invalid CAC Leakage PowerPlay Table!", return 1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; - - table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == table) - return -ENOMEM; - - memset(table, 0x00, table_size); - - table->count = vddc_lookup_pp_tables->ucNumEntries; - - for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) { - record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_voltage_lookup_record, - entries, table, i); - atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_Voltage_Lookup_Record, - entries, vddc_lookup_pp_tables, i); - record->us_calculated = 0; - record->us_vdd = atom_record->usVdd; - record->us_cac_low = atom_record->usCACLow; - record->us_cac_mid = atom_record->usCACMid; - record->us_cac_high = atom_record->usCACHigh; - } - - *lookup_table = table; - - return 0; -} - -/** - * Private Function used during initialization. - * Initialize Platform Power Management Parameter table - * @param hwmgr Pointer to the hardware manager. - * @param atom_ppm_table Pointer to PPM table in VBIOS - */ -static int get_platform_power_management_table( - struct pp_hwmgr *hwmgr, - ATOM_Tonga_PPM_Table *atom_ppm_table) -{ - struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL); - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (NULL == ptr) - return -ENOMEM; - - ptr->ppm_design - = atom_ppm_table->ucPpmDesign; - ptr->cpu_core_number - = atom_ppm_table->usCpuCoreNumber; - ptr->platform_tdp - = atom_ppm_table->ulPlatformTDP; - ptr->small_ac_platform_tdp - = atom_ppm_table->ulSmallACPlatformTDP; - ptr->platform_tdc - = atom_ppm_table->ulPlatformTDC; - ptr->small_ac_platform_tdc - = atom_ppm_table->ulSmallACPlatformTDC; - ptr->apu_tdp - = atom_ppm_table->ulApuTDP; - ptr->dgpu_tdp - = atom_ppm_table->ulDGpuTDP; - ptr->dgpu_ulv_power - = atom_ppm_table->ulDGpuUlvPower; - ptr->tj_max - = atom_ppm_table->ulTjmax; - - pp_table_information->ppm_parameter_table = ptr; - - return 0; -} - -/** - * Private Function used during initialization. - * Initialize TDP limits for DPM2 - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - */ -static int init_dpm_2_parameters( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table - ) -{ - int result = 0; - struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); - ATOM_Tonga_PPM_Table *atom_ppm_table; - uint32_t disable_ppm = 0; - uint32_t disable_power_control = 0; - - pp_table_information->us_ulv_voltage_offset = - le16_to_cpu(powerplay_table->usUlvVoltageOffset); - - pp_table_information->ppm_parameter_table = NULL; - pp_table_information->vddc_lookup_table = NULL; - pp_table_information->vddgfx_lookup_table = NULL; - /* TDP limits */ - hwmgr->platform_descriptor.TDPODLimit = - le16_to_cpu(powerplay_table->usPowerControlLimit); - hwmgr->platform_descriptor.TDPAdjustment = 0; - hwmgr->platform_descriptor.VidAdjustment = 0; - hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; - hwmgr->platform_descriptor.VidMinLimit = 0; - hwmgr->platform_descriptor.VidMaxLimit = 1500000; - hwmgr->platform_descriptor.VidStep = 6250; - - disable_power_control = 0; - if (0 == disable_power_control) { - /* enable TDP overdrive (PowerControl) feature as well if supported */ - if (hwmgr->platform_descriptor.TDPODLimit != 0) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerControl); - } - - if (0 != powerplay_table->usVddcLookupTableOffset) { - const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable = - (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); - - result = get_vddc_lookup_table(hwmgr, - &pp_table_information->vddc_lookup_table, pVddcCACTable, 16); - } - - if (0 != powerplay_table->usVddgfxLookupTableOffset) { - const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable = - (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset)); - - result = get_vddc_lookup_table(hwmgr, - &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16); - } - - disable_ppm = 0; - if (0 == disable_ppm) { - atom_ppm_table = (ATOM_Tonga_PPM_Table *) - (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset)); - - if (0 != powerplay_table->usPPMTableOffset) { - if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnablePlatformPowerManagement); - } - } - } - - return result; -} - -static int get_valid_clk( - struct pp_hwmgr *hwmgr, - struct phm_clock_array **clk_table, - phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table - ) -{ - uint32_t table_size, i; - struct phm_clock_array *table; - phm_ppt_v1_clock_voltage_dependency_record *dep_record; - - PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(uint32_t) * clk_volt_pp_table->count; - - table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == table) - return -ENOMEM; - - memset(table, 0x00, table_size); - - table->count = (uint32_t)clk_volt_pp_table->count; - - for (i = 0; i < table->count; i++) { - dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_clock_voltage_dependency_record, - entries, clk_volt_pp_table, i); - table->values[i] = (uint32_t)dep_record->clk; - } - *clk_table = table; - - return 0; -} - -static int get_hard_limits( - struct pp_hwmgr *hwmgr, - struct phm_clock_and_voltage_limits *limits, - ATOM_Tonga_Hard_Limit_Table const *limitable - ) -{ - PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1); - - /* currently we always take entries[0] parameters */ - limits->sclk = (uint32_t)limitable->entries[0].ulSCLKLimit; - limits->mclk = (uint32_t)limitable->entries[0].ulMCLKLimit; - limits->vddc = (uint16_t)limitable->entries[0].usVddcLimit; - limits->vddci = (uint16_t)limitable->entries[0].usVddciLimit; - limits->vddgfx = (uint16_t)limitable->entries[0].usVddgfxLimit; - - return 0; -} - -static int get_mclk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table, - ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table - ) -{ - uint32_t table_size, i; - phm_ppt_v1_clock_voltage_dependency_table *mclk_table; - phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record; - ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; - - PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * mclk_dep_table->ucNumEntries; - - mclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == mclk_table) - return -ENOMEM; - - memset(mclk_table, 0x00, table_size); - - mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; - - for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { - mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_clock_voltage_dependency_record, - entries, mclk_table, i); - mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MCLK_Dependency_Record, - entries, mclk_dep_table, i); - mclk_table_record->vddInd = mclk_dep_record->ucVddcInd; - mclk_table_record->vdd_offset = mclk_dep_record->usVddgfxOffset; - mclk_table_record->vddci = mclk_dep_record->usVddci; - mclk_table_record->mvdd = mclk_dep_record->usMvdd; - mclk_table_record->clk = mclk_dep_record->ulMclk; - } - - *pp_tonga_mclk_dep_table = mclk_table; - - return 0; -} - -static int get_sclk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table, - const PPTable_Generic_SubTable_Header *sclk_dep_table - ) -{ - uint32_t table_size, i; - phm_ppt_v1_clock_voltage_dependency_table *sclk_table; - phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record; - - if (sclk_dep_table->ucRevId < 1) { - const ATOM_Tonga_SCLK_Dependency_Table *tonga_table = - (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table; - ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; - - PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * tonga_table->ucNumEntries; - - sclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == sclk_table) - return -ENOMEM; - - memset(sclk_table, 0x00, table_size); - - sclk_table->count = (uint32_t)tonga_table->ucNumEntries; - - for (i = 0; i < tonga_table->ucNumEntries; i++) { - sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_SCLK_Dependency_Record, - entries, tonga_table, i); - sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_clock_voltage_dependency_record, - entries, sclk_table, i); - sclk_table_record->vddInd = sclk_dep_record->ucVddInd; - sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset; - sclk_table_record->clk = sclk_dep_record->ulSclk; - sclk_table_record->cks_enable = - (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; - sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); - } - } else { - const ATOM_Polaris_SCLK_Dependency_Table *polaris_table = - (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table; - ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record; - - PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * polaris_table->ucNumEntries; - - sclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == sclk_table) - return -ENOMEM; - - memset(sclk_table, 0x00, table_size); - - sclk_table->count = (uint32_t)polaris_table->ucNumEntries; - - for (i = 0; i < polaris_table->ucNumEntries; i++) { - sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Polaris_SCLK_Dependency_Record, - entries, polaris_table, i); - sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_clock_voltage_dependency_record, - entries, sclk_table, i); - sclk_table_record->vddInd = sclk_dep_record->ucVddInd; - sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset; - sclk_table_record->clk = sclk_dep_record->ulSclk; - sclk_table_record->cks_enable = - (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; - sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); - sclk_table_record->sclk_offset = sclk_dep_record->ulSclkOffset; - } - } - *pp_tonga_sclk_dep_table = sclk_table; - - return 0; -} - -static int get_pcie_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_pcie_table **pp_tonga_pcie_table, - PPTable_Generic_SubTable_Header const *ptable - ) -{ - uint32_t table_size, i, pcie_count; - phm_ppt_v1_pcie_table *pcie_table; - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_pcie_record *pcie_record; - - if (ptable->ucRevId < 1) { - const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable; - ATOM_Tonga_PCIE_Record *atom_pcie_record; - - PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; - - pcie_table = kzalloc(table_size, GFP_KERNEL); - - if (pcie_table == NULL) - return -ENOMEM; - - memset(pcie_table, 0x00, table_size); - - /* - * Make sure the number of pcie entries are less than or equal to sclk dpm levels. - * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. - */ - pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; - if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) - pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; - else - printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \ - Disregarding the excess entries... \n"); - - pcie_table->count = pcie_count; - for (i = 0; i < pcie_count; i++) { - pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_pcie_record, - entries, pcie_table, i); - atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_PCIE_Record, - entries, atom_pcie_table, i); - pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; - pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth; - } - - *pp_tonga_pcie_table = pcie_table; - } else { - /* Polaris10/Polaris11 and newer. */ - const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable; - ATOM_Polaris10_PCIE_Record *atom_pcie_record; - - PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; - - pcie_table = kzalloc(table_size, GFP_KERNEL); - - if (pcie_table == NULL) - return -ENOMEM; - - memset(pcie_table, 0x00, table_size); - - /* - * Make sure the number of pcie entries are less than or equal to sclk dpm levels. - * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. - */ - pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; - if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) - pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; - else - printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \ - Disregarding the excess entries... \n"); - - pcie_table->count = pcie_count; - - for (i = 0; i < pcie_count; i++) { - pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_pcie_record, - entries, pcie_table, i); - atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Polaris10_PCIE_Record, - entries, atom_pcie_table, i); - pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; - pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth; - pcie_record->pcie_sclk = atom_pcie_record->ulPCIE_Sclk; - } - - *pp_tonga_pcie_table = pcie_table; - } - - return 0; -} - -static int get_cac_tdp_table( - struct pp_hwmgr *hwmgr, - struct phm_cac_tdp_table **cac_tdp_table, - const PPTable_Generic_SubTable_Header * table - ) -{ - uint32_t table_size; - struct phm_cac_tdp_table *tdp_table; - - table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table); - tdp_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == tdp_table) - return -ENOMEM; - - memset(tdp_table, 0x00, table_size); - - hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == hwmgr->dyn_state.cac_dtp_table) { - kfree(tdp_table); - return -ENOMEM; - } - - memset(hwmgr->dyn_state.cac_dtp_table, 0x00, table_size); - - if (table->ucRevId < 3) { - const ATOM_Tonga_PowerTune_Table *tonga_table = - (ATOM_Tonga_PowerTune_Table *)table; - tdp_table->usTDP = tonga_table->usTDP; - tdp_table->usConfigurableTDP = - tonga_table->usConfigurableTDP; - tdp_table->usTDC = tonga_table->usTDC; - tdp_table->usBatteryPowerLimit = - tonga_table->usBatteryPowerLimit; - tdp_table->usSmallPowerLimit = - tonga_table->usSmallPowerLimit; - tdp_table->usLowCACLeakage = - tonga_table->usLowCACLeakage; - tdp_table->usHighCACLeakage = - tonga_table->usHighCACLeakage; - tdp_table->usMaximumPowerDeliveryLimit = - tonga_table->usMaximumPowerDeliveryLimit; - tdp_table->usDefaultTargetOperatingTemp = - tonga_table->usTjMax; - tdp_table->usTargetOperatingTemp = - tonga_table->usTjMax; /*Set the initial temp to the same as default */ - tdp_table->usPowerTuneDataSetID = - tonga_table->usPowerTuneDataSetID; - tdp_table->usSoftwareShutdownTemp = - tonga_table->usSoftwareShutdownTemp; - tdp_table->usClockStretchAmount = - tonga_table->usClockStretchAmount; - } else { /* Fiji and newer */ - const ATOM_Fiji_PowerTune_Table *fijitable = - (ATOM_Fiji_PowerTune_Table *)table; - tdp_table->usTDP = fijitable->usTDP; - tdp_table->usConfigurableTDP = fijitable->usConfigurableTDP; - tdp_table->usTDC = fijitable->usTDC; - tdp_table->usBatteryPowerLimit = fijitable->usBatteryPowerLimit; - tdp_table->usSmallPowerLimit = fijitable->usSmallPowerLimit; - tdp_table->usLowCACLeakage = fijitable->usLowCACLeakage; - tdp_table->usHighCACLeakage = fijitable->usHighCACLeakage; - tdp_table->usMaximumPowerDeliveryLimit = - fijitable->usMaximumPowerDeliveryLimit; - tdp_table->usDefaultTargetOperatingTemp = - fijitable->usTjMax; - tdp_table->usTargetOperatingTemp = - fijitable->usTjMax; /*Set the initial temp to the same as default */ - tdp_table->usPowerTuneDataSetID = - fijitable->usPowerTuneDataSetID; - tdp_table->usSoftwareShutdownTemp = - fijitable->usSoftwareShutdownTemp; - tdp_table->usClockStretchAmount = - fijitable->usClockStretchAmount; - tdp_table->usTemperatureLimitHotspot = - fijitable->usTemperatureLimitHotspot; - tdp_table->usTemperatureLimitLiquid1 = - fijitable->usTemperatureLimitLiquid1; - tdp_table->usTemperatureLimitLiquid2 = - fijitable->usTemperatureLimitLiquid2; - tdp_table->usTemperatureLimitVrVddc = - fijitable->usTemperatureLimitVrVddc; - tdp_table->usTemperatureLimitVrMvdd = - fijitable->usTemperatureLimitVrMvdd; - tdp_table->usTemperatureLimitPlx = - fijitable->usTemperatureLimitPlx; - tdp_table->ucLiquid1_I2C_address = - fijitable->ucLiquid1_I2C_address; - tdp_table->ucLiquid2_I2C_address = - fijitable->ucLiquid2_I2C_address; - tdp_table->ucLiquid_I2C_Line = - fijitable->ucLiquid_I2C_Line; - tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address; - tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line; - tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address; - tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line; - } - - *cac_tdp_table = tdp_table; - - return 0; -} - -static int get_mm_clock_voltage_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table, - const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table - ) -{ - uint32_t table_size, i; - const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record; - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; - phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record; - - PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) - * mm_dependency_table->ucNumEntries; - mm_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == mm_table) - return -ENOMEM; - - memset(mm_table, 0x00, table_size); - - mm_table->count = mm_dependency_table->ucNumEntries; - - for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { - mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MM_Dependency_Record, - entries, mm_dependency_table, i); - mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_mm_clock_voltage_dependency_record, - entries, mm_table, i); - mm_table_record->vddcInd = mm_dependency_record->ucVddcInd; - mm_table_record->vddgfx_offset = mm_dependency_record->usVddgfxOffset; - mm_table_record->aclk = mm_dependency_record->ulAClk; - mm_table_record->samclock = mm_dependency_record->ulSAMUClk; - mm_table_record->eclk = mm_dependency_record->ulEClk; - mm_table_record->vclk = mm_dependency_record->ulVClk; - mm_table_record->dclk = mm_dependency_record->ulDClk; - } - - *tonga_mm_table = mm_table; - - return 0; -} - -/** - * Private Function used during initialization. - * Initialize clock voltage dependency - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - */ -static int init_clock_voltage_dependency( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table - ) -{ - int result = 0; - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table = - (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); - const PPTable_Generic_SubTable_Header *pPowerTuneTable = - (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); - const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = - (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); - const PPTable_Generic_SubTable_Header *sclk_dep_table = - (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); - const ATOM_Tonga_Hard_Limit_Table *pHardLimits = - (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usHardLimitTableOffset)); - const PPTable_Generic_SubTable_Header *pcie_table = - (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usPCIETableOffset)); - - pp_table_information->vdd_dep_on_sclk = NULL; - pp_table_information->vdd_dep_on_mclk = NULL; - pp_table_information->mm_dep_table = NULL; - pp_table_information->pcie_table = NULL; - - if (powerplay_table->usMMDependencyTableOffset != 0) - result = get_mm_clock_voltage_table(hwmgr, - &pp_table_information->mm_dep_table, mm_dependency_table); - - if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0) - result = get_cac_tdp_table(hwmgr, - &pp_table_information->cac_dtp_table, pPowerTuneTable); - - if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0) - result = get_sclk_voltage_dependency_table(hwmgr, - &pp_table_information->vdd_dep_on_sclk, sclk_dep_table); - - if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0) - result = get_mclk_voltage_dependency_table(hwmgr, - &pp_table_information->vdd_dep_on_mclk, mclk_dep_table); - - if (result == 0 && powerplay_table->usPCIETableOffset != 0) - result = get_pcie_table(hwmgr, - &pp_table_information->pcie_table, pcie_table); - - if (result == 0 && powerplay_table->usHardLimitTableOffset != 0) - result = get_hard_limits(hwmgr, - &pp_table_information->max_clock_voltage_on_dc, pHardLimits); - - hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = - pp_table_information->max_clock_voltage_on_dc.sclk; - hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = - pp_table_information->max_clock_voltage_on_dc.mclk; - hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = - pp_table_information->max_clock_voltage_on_dc.vddc; - hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = - pp_table_information->max_clock_voltage_on_dc.vddci; - - if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk) - && (0 != pp_table_information->vdd_dep_on_mclk->count)) - result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values, - pp_table_information->vdd_dep_on_mclk); - - if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk) - && (0 != pp_table_information->vdd_dep_on_sclk->count)) - result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values, - pp_table_information->vdd_dep_on_sclk); - - return result; -} - -/** Retrieves the (signed) Overdrive limits from VBIOS. - * The max engine clock, memory clock and max temperature come from the firmware info table. - * - * The information is placed into the platform descriptor. - * - * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated. - * @param powerplay_table the address of the PowerPlay table. - * - * @return 1 as long as the firmware info table was present and of a supported version. - */ -static int init_over_drive_limits( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table) -{ - hwmgr->platform_descriptor.overdriveLimit.engineClock = - le16_to_cpu(powerplay_table->ulMaxODEngineClock); - hwmgr->platform_descriptor.overdriveLimit.memoryClock = - le16_to_cpu(powerplay_table->ulMaxODMemoryClock); - - hwmgr->platform_descriptor.minOverdriveVDDC = 0; - hwmgr->platform_descriptor.maxOverdriveVDDC = 0; - hwmgr->platform_descriptor.overdriveVDDCStep = 0; - - if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 \ - && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ACOverdriveSupport); - } - - return 0; -} - -/** - * Private Function used during initialization. - * Inspect the PowerPlay table for obvious signs of corruption. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - * @exception This implementation always returns 1. - */ -static int init_thermal_controller( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table - ) -{ - const PPTable_Generic_SubTable_Header *fan_table; - ATOM_Tonga_Thermal_Controller *thermal_controller; - - thermal_controller = (ATOM_Tonga_Thermal_Controller *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usThermalControllerOffset)); - PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset), - "Thermal controller table not set!", return -1); - - hwmgr->thermal_controller.ucType = thermal_controller->ucType; - hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; - hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; - - hwmgr->thermal_controller.fanInfo.bNoFan = - (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN)); - - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = - thermal_controller->ucFanParameters & - ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; - - hwmgr->thermal_controller.fanInfo.ulMinRPM - = thermal_controller->ucFanMinRPM * 100UL; - hwmgr->thermal_controller.fanInfo.ulMaxRPM - = thermal_controller->ucFanMaxRPM * 100UL; - - set_hw_cap( - hwmgr, - ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, - PHM_PlatformCaps_ThermalController - ); - - if (0 == powerplay_table->usFanTableOffset) - return 0; - - fan_table = (const PPTable_Generic_SubTable_Header *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usFanTableOffset)); - - PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset), - "Fan table not set!", return -1); - PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId), - "Unsupported fan table format!", return -1); - - hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay - = 100000; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - - if (fan_table->ucRevId < 8) { - const ATOM_Tonga_Fan_Table *tonga_fan_table = - (ATOM_Tonga_Fan_Table *)fan_table; - hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst - = tonga_fan_table->ucTHyst; - hwmgr->thermal_controller.advanceFanControlParameters.usTMin - = tonga_fan_table->usTMin; - hwmgr->thermal_controller.advanceFanControlParameters.usTMed - = tonga_fan_table->usTMed; - hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - = tonga_fan_table->usTHigh; - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin - = tonga_fan_table->usPWMMin; - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - = tonga_fan_table->usPWMMed; - hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - = tonga_fan_table->usPWMHigh; - hwmgr->thermal_controller.advanceFanControlParameters.usTMax - = 10900; /* hard coded */ - hwmgr->thermal_controller.advanceFanControlParameters.usTMax - = tonga_fan_table->usTMax; - hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode - = tonga_fan_table->ucFanControlMode; - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM - = tonga_fan_table->usFanPWMMax; - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity - = 4836; - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity - = tonga_fan_table->usFanOutputSensitivity; - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM - = tonga_fan_table->usFanRPMMax; - hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit - = (tonga_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ - hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature - = tonga_fan_table->ucTargetTemperature; - hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit - = tonga_fan_table->ucMinimumPWMLimit; - } else { - const ATOM_Fiji_Fan_Table *fiji_fan_table = - (ATOM_Fiji_Fan_Table *)fan_table; - hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst - = fiji_fan_table->ucTHyst; - hwmgr->thermal_controller.advanceFanControlParameters.usTMin - = fiji_fan_table->usTMin; - hwmgr->thermal_controller.advanceFanControlParameters.usTMed - = fiji_fan_table->usTMed; - hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - = fiji_fan_table->usTHigh; - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin - = fiji_fan_table->usPWMMin; - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - = fiji_fan_table->usPWMMed; - hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - = fiji_fan_table->usPWMHigh; - hwmgr->thermal_controller.advanceFanControlParameters.usTMax - = fiji_fan_table->usTMax; - hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode - = fiji_fan_table->ucFanControlMode; - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM - = fiji_fan_table->usFanPWMMax; - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity - = 4836; - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity - = fiji_fan_table->usFanOutputSensitivity; - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM - = fiji_fan_table->usFanRPMMax; - hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit - = (fiji_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ - hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature - = fiji_fan_table->ucTargetTemperature; - hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit - = fiji_fan_table->ucMinimumPWMLimit; - - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge - = fiji_fan_table->usFanGainEdge; - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot - = fiji_fan_table->usFanGainHotspot; - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid - = fiji_fan_table->usFanGainLiquid; - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc - = fiji_fan_table->usFanGainVrVddc; - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd - = fiji_fan_table->usFanGainVrMvdd; - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx - = fiji_fan_table->usFanGainPlx; - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm - = fiji_fan_table->usFanGainHbm; - } - - return 0; -} - -/** - * Private Function used during initialization. - * Inspect the PowerPlay table for obvious signs of corruption. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - * @exception 2 if the powerplay table is incorrect. - */ -static int check_powerplay_tables( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table - ) -{ - const ATOM_Tonga_State_Array *state_arrays; - - state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usStateArrayOffset)); - - PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <= - powerplay_table->sHeader.ucTableFormatRevision), - "Unsupported PPTable format!", return -1); - PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset), - "State table is not set!", return -1); - PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize), - "Invalid PowerPlay Table!", return -1); - PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - - return 0; -} - -int tonga_pp_tables_initialize(struct pp_hwmgr *hwmgr) -{ - int result = 0; - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table; - - hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL); - - PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable), - "Failed to allocate hwmgr->pptable!", return -ENOMEM); - - memset(hwmgr->pptable, 0x00, sizeof(struct phm_ppt_v1_information)); - - powerplay_table = get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE((NULL != powerplay_table), - "Missing PowerPlay Table!", return -1); - - result = check_powerplay_tables(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "check_powerplay_tables failed", return result); - - result = set_platform_caps(hwmgr, - le32_to_cpu(powerplay_table->ulPlatformCaps)); - - PP_ASSERT_WITH_CODE((result == 0), - "set_platform_caps failed", return result); - - result = init_thermal_controller(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_thermal_controller failed", return result); - - result = init_over_drive_limits(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_over_drive_limits failed", return result); - - result = init_clock_voltage_dependency(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_clock_voltage_dependency failed", return result); - - result = init_dpm_2_parameters(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_dpm_2_parameters failed", return result); - - return result; -} - -int tonga_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - kfree(pp_table_information->vdd_dep_on_sclk); - pp_table_information->vdd_dep_on_sclk = NULL; - - kfree(pp_table_information->vdd_dep_on_mclk); - pp_table_information->vdd_dep_on_mclk = NULL; - - kfree(pp_table_information->valid_mclk_values); - pp_table_information->valid_mclk_values = NULL; - - kfree(pp_table_information->valid_sclk_values); - pp_table_information->valid_sclk_values = NULL; - - kfree(pp_table_information->vddc_lookup_table); - pp_table_information->vddc_lookup_table = NULL; - - kfree(pp_table_information->vddgfx_lookup_table); - pp_table_information->vddgfx_lookup_table = NULL; - - kfree(pp_table_information->mm_dep_table); - pp_table_information->mm_dep_table = NULL; - - kfree(pp_table_information->cac_dtp_table); - pp_table_information->cac_dtp_table = NULL; - - kfree(hwmgr->dyn_state.cac_dtp_table); - hwmgr->dyn_state.cac_dtp_table = NULL; - - kfree(pp_table_information->ppm_parameter_table); - pp_table_information->ppm_parameter_table = NULL; - - kfree(pp_table_information->pcie_table); - pp_table_information->pcie_table = NULL; - - kfree(hwmgr->pptable); - hwmgr->pptable = NULL; - - return 0; -} - -const struct pp_table_func tonga_pptable_funcs = { - .pptable_init = tonga_pp_tables_initialize, - .pptable_fini = tonga_pp_tables_uninitialize, -}; - -int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) -{ - const ATOM_Tonga_State_Array * state_arrays; - const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE((NULL != pp_table), - "Missing PowerPlay Table!", return -1); - PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >= - ATOM_Tonga_TABLE_REVISION_TONGA), - "Incorrect PowerPlay table revision!", return -1); - - state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + - le16_to_cpu(pp_table->usStateArrayOffset)); - - return (uint32_t)(state_arrays->ucNumEntries); -} - -/** -* Private function to convert flags stored in the BIOS to software flags in PowerPlay. -*/ -static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, - uint16_t classification, uint16_t classification2) -{ - uint32_t result = 0; - - if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) - result |= PP_StateClassificationFlag_Boot; - - if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) - result |= PP_StateClassificationFlag_Thermal; - - if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) - result |= PP_StateClassificationFlag_LimitedPowerSource; - - if (classification & ATOM_PPLIB_CLASSIFICATION_REST) - result |= PP_StateClassificationFlag_Rest; - - if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) - result |= PP_StateClassificationFlag_Forced; - - if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) - result |= PP_StateClassificationFlag_ACPI; - - if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) - result |= PP_StateClassificationFlag_LimitedPowerSource_2; - - return result; -} - -static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr) -{ - const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); - const ATOM_Tonga_VCE_State_Table *vce_state_table = - (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pp_table) + le16_to_cpu(pp_table->usVCEStateTableOffset)); - - if (vce_state_table == NULL) - return 0; - - return vce_state_table->ucNumEntries; -} - -static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i, - struct pp_vce_state *vce_state, void **clock_info, uint32_t *flag) -{ - const ATOM_Tonga_VCE_State_Record *vce_state_record; - ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; - ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; - ATOM_Tonga_MM_Dependency_Record *mm_dep_record; - const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr); - const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable) - + le16_to_cpu(pptable->usVCEStateTableOffset)); - const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable) - + le16_to_cpu(pptable->usSclkDependencyTableOffset)); - const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable) - + le16_to_cpu(pptable->usMclkDependencyTableOffset)); - const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable) - + le16_to_cpu(pptable->usMMDependencyTableOffset)); - - PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries), - "Requested state entry ID is out of range!", - return -EINVAL); - - vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_VCE_State_Record, - entries, vce_state_table, i); - sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_SCLK_Dependency_Record, - entries, sclk_dep_table, - vce_state_record->ucSCLKIndex); - mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MM_Dependency_Record, - entries, mm_dep_table, - vce_state_record->ucVCEClockIndex); - *flag = vce_state_record->ucFlag; - - vce_state->evclk = mm_dep_record->ulEClk; - vce_state->ecclk = mm_dep_record->ulEClk; - vce_state->sclk = sclk_dep_record->ulSclk; - - if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries) - mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MCLK_Dependency_Record, - entries, mclk_dep_table, - mclk_dep_table->ucNumEntries - 1); - else - mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MCLK_Dependency_Record, - entries, mclk_dep_table, - vce_state_record->ucMCLKIndex); - - vce_state->mclk = mclk_dep_record->ulMclk; - return 0; -} - -/** -* Create a Power State out of an entry in the PowerPlay table. -* This function is called by the hardware back-end. -* @param hwmgr Pointer to the hardware manager. -* @param entry_index The index of the entry to be extracted from the table. -* @param power_state The address of the PowerState instance being created. -* @return -1 if the entry cannot be retrieved. -*/ -int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, - uint32_t entry_index, struct pp_power_state *power_state, - int (*call_back_func)(struct pp_hwmgr *, void *, - struct pp_power_state *, void *, uint32_t)) -{ - int result = 0; - const ATOM_Tonga_State_Array *state_arrays; - const ATOM_Tonga_State *state_entry; - const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); - int i, j; - uint32_t flags = 0; - - PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;); - power_state->classification.bios_index = entry_index; - - if (pp_table->sHeader.ucTableFormatRevision >= - ATOM_Tonga_TABLE_REVISION_TONGA) { - state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + - le16_to_cpu(pp_table->usStateArrayOffset)); - - PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset), - "Invalid PowerPlay Table State Array Offset.", return -1); - PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), - "Invalid PowerPlay Table State Array.", return -1); - PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), - "Invalid PowerPlay Table State Array Entry.", return -1); - - state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_State, entries, - state_arrays, entry_index); - - result = call_back_func(hwmgr, (void *)state_entry, power_state, - (void *)pp_table, - make_classification_flags(hwmgr, - le16_to_cpu(state_entry->usClassification), - le16_to_cpu(state_entry->usClassification2))); - } - - if (!result && (power_state->classification.flags & - PP_StateClassificationFlag_Boot)) - result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); - - hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr); - - if ((i != 0) && (i <= PP_MAX_VCE_LEVELS)) { - for (j = 0; j < i; j++) - ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags); - } - - return result; -} - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h deleted file mode 100644 index d24b888..0000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef TONGA_PROCESSPPTABLES_H -#define TONGA_PROCESSPPTABLES_H - -#include "hwmgr.h" - -extern const struct pp_table_func tonga_pptable_funcs; -extern int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr); -extern int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, uint32_t entry_index, - struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *, - struct pp_power_state *, void *, uint32_t)); - -#endif - -- cgit v1.1 From b1c8e1e21f421653971c18fdafa22f2553899ca9 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 24 Aug 2016 11:28:41 +0800 Subject: drm/amd/powerplay: add pp_table_version in hwmgr. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 1 + drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 2d72e06..82427fb 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -67,6 +67,7 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) hwmgr->chip_id = pp_init->chip_id; hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; hwmgr->power_source = PP_PowerSource_AC; + hwmgr->pp_table_version = PP_TABLE_V1; hwmgr_init_default_caps(hwmgr); hwmgr_set_user_specify_caps(hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 7caf8d0..e987483 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -599,6 +599,13 @@ enum PP_VCE_LEVEL { }; +enum PP_TABLE_VERSION { + PP_TABLE_V0 = 0, + PP_TABLE_V1, + PP_TABLE_V2, + PP_TABLE_MAX +}; + /** * The main hardware manager structure. */ @@ -606,6 +613,7 @@ struct pp_hwmgr { uint32_t chip_family; uint32_t chip_id; + uint32_t pp_table_version; void *device; struct pp_smumgr *smumgr; const void *soft_pp_table; -- cgit v1.1 From aa0ef3ccd6410c14d3de586bd83ce532cad2e67e Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 25 Aug 2016 20:00:28 +0800 Subject: drm/amd/powerplay: add pptable point check before use it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 82427fb..1b3151c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -555,7 +555,8 @@ int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr table_clk_vlt->entries[2].v = 810; table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE; table_clk_vlt->entries[3].v = 900; - pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt; + if (pptable_info != NULL) + pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt; hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; } -- cgit v1.1 From d932f37c4aa8b380f8ed529d1472a2ff49b95727 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 13 Sep 2016 19:38:38 +0800 Subject: drm/amdgpu: not set cg for vce/uvd in late init. no need to set cg for uvd/vce in late init. As when ring test, uvd/vce's dpm will be enabled/disabled. the cg will be set. fix issue suspend when play video or encode, then resume back, the clock will be bypassed on Polaris/Fiji. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d324a07..3ddae5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1367,6 +1367,9 @@ static int amdgpu_late_init(struct amdgpu_device *adev) for (i = 0; i < adev->num_ip_blocks; i++) { if (!adev->ip_block_status[i].valid) continue; + if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_UVD || + adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_VCE) + continue; /* enable clockgating to save power */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, AMD_CG_STATE_GATE); -- cgit v1.1 From 72f417a2e0b1bdb0e2accc36fd4d3b64769dce0f Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 14 Sep 2016 16:28:01 +0800 Subject: drm/amd/powerplay: Partially revert change initialize platform caps partially revert commit I36f3c9e3a28cbf290652edfb6e19109da660c4f1 this will lead APU can't work. Signed-off-by: Rex Zhu Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 1b3151c..524d0dd 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -658,18 +658,12 @@ void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_DynamicPatchPowerState); phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EnableSMU7ThermalManagement); phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPowerManagement); phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UnTabledHardwareInterface); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SMC); phm_cap_set(hwmgr->platform_descriptor.platformCaps, -- cgit v1.1 From 2255e8c1092fedbd3db9940e37ef44524f86a3d9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Sep 2016 12:04:45 -0400 Subject: drm/amdgpu/si: fix ring size for compute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We switched the other asics, but missed this. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index a1484b8..9697994 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -2779,7 +2779,7 @@ static int gfx_v6_0_sw_init(void *handle) ring->queue = i; sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue); irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; - r = amdgpu_ring_init(adev, ring, 1024 * 1024, + r = amdgpu_ring_init(adev, ring, 1024, 0x80000000, 0xf, &adev->gfx.eop_irq, irq_type, AMDGPU_RING_TYPE_COMPUTE); -- cgit v1.1 From 668f52c3039049cd293851599581c5eca745ec4e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Sep 2016 15:28:46 -0400 Subject: drm/amdgpu/gfx6: drop duplicate code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compute functions just called the gfx functions, drop the wrapper. Reviewed-by: Edward O'Callaghan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 9697994..3cf4e9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -1324,8 +1324,8 @@ static void gfx_v6_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring) amdgpu_ring_write(ring, 0x1); } -static void gfx_v6_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, - u64 seq, unsigned flags) +static void gfx_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, + u64 seq, unsigned flags) { bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT; bool int_sel = flags & AMDGPU_FENCE_FLAG_INT; @@ -1351,17 +1351,9 @@ static void gfx_v6_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, amdgpu_ring_write(ring, upper_32_bits(seq)); } -static void gfx_v6_0_ring_emit_fence_compute(struct amdgpu_ring *ring, - u64 addr, u64 seq, - unsigned flags) -{ - gfx_v6_0_ring_emit_fence_gfx(ring, addr, seq, flags); -} - - -static void gfx_v6_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, - struct amdgpu_ib *ib, - unsigned vm_id, bool ctx_switch) +static void gfx_v6_0_ring_emit_ib(struct amdgpu_ring *ring, + struct amdgpu_ib *ib, + unsigned vm_id, bool ctx_switch) { u32 header, control = 0; @@ -1388,13 +1380,6 @@ static void gfx_v6_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, amdgpu_ring_write(ring, control); } -static void gfx_v6_0_ring_emit_ib_compute(struct amdgpu_ring *ring, - struct amdgpu_ib *ib, - unsigned vm_id, bool ctx_switch) -{ - gfx_v6_0_ring_emit_ib_gfx(ring, ib, vm_id, ctx_switch); -} - /** * gfx_v6_0_ring_test_ib - basic ring IB test * @@ -3119,8 +3104,8 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_gfx, .parse_cs = NULL, - .emit_ib = gfx_v6_0_ring_emit_ib_gfx, - .emit_fence = gfx_v6_0_ring_emit_fence_gfx, + .emit_ib = gfx_v6_0_ring_emit_ib, + .emit_fence = gfx_v6_0_ring_emit_fence, .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, .emit_vm_flush = gfx_v6_0_ring_emit_vm_flush, .emit_gds_switch = gfx_v6_0_ring_emit_gds_switch, @@ -3136,8 +3121,8 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { .get_wptr = gfx_v6_0_ring_get_wptr, .set_wptr = gfx_v6_0_ring_set_wptr_compute, .parse_cs = NULL, - .emit_ib = gfx_v6_0_ring_emit_ib_compute, - .emit_fence = gfx_v6_0_ring_emit_fence_compute, + .emit_ib = gfx_v6_0_ring_emit_ib, + .emit_fence = gfx_v6_0_ring_emit_fence, .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, .emit_vm_flush = gfx_v6_0_ring_emit_vm_flush, .emit_gds_switch = gfx_v6_0_ring_emit_gds_switch, -- cgit v1.1 From 0f444c24dd00ba562483d5825f9757e0f933d813 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Sep 2016 15:40:06 -0400 Subject: drm/amdgpu/gfx6: add ring_emit_cntxcntl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missing for gfx6. Reviewed-by: Edward O'Callaghan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 3cf4e9e..d33d321 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -2686,6 +2686,13 @@ static void gfx_v6_0_ring_emit_gds_switch(struct amdgpu_ring *ring, { } +static void gfx_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) +{ + amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1)); + amdgpu_ring_write(ring, 0x80000000); + amdgpu_ring_write(ring, 0); +} + static const struct amdgpu_gfx_funcs gfx_v6_0_gfx_funcs = { .get_gpu_clock_counter = &gfx_v6_0_get_gpu_clock_counter, .select_se_sh = &gfx_v6_0_select_se_sh, @@ -3114,6 +3121,7 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .test_ring = gfx_v6_0_ring_test_ring, .test_ib = gfx_v6_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, + .emit_cntxcntl = gfx_v6_ring_emit_cntxcntl, }; static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { -- cgit v1.1 From 95e588a01424cb4d6f38bc02f84c8dfe05e0e55f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Sep 2016 15:42:09 -0400 Subject: drm/amdgpu/gfx6: drop gds_switch callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GDS works differently on GFX6, plus the callback was empty. Reviewed-by: Edward O'Callaghan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index d33d321..e7293f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -2678,14 +2678,6 @@ static uint64_t gfx_v6_0_get_gpu_clock_counter(struct amdgpu_device *adev) return clock; } -static void gfx_v6_0_ring_emit_gds_switch(struct amdgpu_ring *ring, - uint32_t vmid, - uint32_t gds_base, uint32_t gds_size, - uint32_t gws_base, uint32_t gws_size, - uint32_t oa_base, uint32_t oa_size) -{ -} - static void gfx_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) { amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1)); @@ -3115,7 +3107,6 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .emit_fence = gfx_v6_0_ring_emit_fence, .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, .emit_vm_flush = gfx_v6_0_ring_emit_vm_flush, - .emit_gds_switch = gfx_v6_0_ring_emit_gds_switch, .emit_hdp_flush = gfx_v6_0_ring_emit_hdp_flush, .emit_hdp_invalidate = gfx_v6_0_ring_emit_hdp_invalidate, .test_ring = gfx_v6_0_ring_test_ring, @@ -3133,7 +3124,6 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { .emit_fence = gfx_v6_0_ring_emit_fence, .emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync, .emit_vm_flush = gfx_v6_0_ring_emit_vm_flush, - .emit_gds_switch = gfx_v6_0_ring_emit_gds_switch, .emit_hdp_flush = gfx_v6_0_ring_emit_hdp_flush, .emit_hdp_invalidate = gfx_v6_0_ring_emit_hdp_invalidate, .test_ring = gfx_v6_0_ring_test_ring, -- cgit v1.1 From e75a887162073de9017d220abc12b6e99cfff0d7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Sep 2016 16:30:01 -0400 Subject: drm/amdgpu/sdma3: drop unused functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are not used yet. Reviewed-by: Edward O'Callaghan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index bee4978..cabb9fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -499,31 +499,6 @@ static void sdma_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se amdgpu_ring_write(ring, SDMA_PKT_TRAP_INT_CONTEXT_INT_CONTEXT(0)); } -unsigned init_cond_exec(struct amdgpu_ring *ring) -{ - unsigned ret; - amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_COND_EXE)); - amdgpu_ring_write(ring, lower_32_bits(ring->cond_exe_gpu_addr)); - amdgpu_ring_write(ring, upper_32_bits(ring->cond_exe_gpu_addr)); - amdgpu_ring_write(ring, 1); - ret = ring->wptr;/* this is the offset we need patch later */ - amdgpu_ring_write(ring, 0x55aa55aa);/* insert dummy here and patch it later */ - return ret; -} - -void patch_cond_exec(struct amdgpu_ring *ring, unsigned offset) -{ - unsigned cur; - BUG_ON(ring->ring[offset] != 0x55aa55aa); - - cur = ring->wptr - 1; - if (likely(cur > offset)) - ring->ring[offset] = cur - offset; - else - ring->ring[offset] = (ring->ring_size>>2) - offset + cur; -} - - /** * sdma_v3_0_gfx_stop - stop the gfx async dma engines * -- cgit v1.1 From b6384ff5375ad28763bc99558a1022070ca5954c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 10:55:50 -0400 Subject: drm/amdgpu/ring: add an interface to get dma frame and ib size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Used to properly calculate space on the ring for ib submissions. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e69fd33..064172e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -322,6 +322,8 @@ struct amdgpu_ring_funcs { void (*end_use)(struct amdgpu_ring *ring); void (*emit_switch_buffer) (struct amdgpu_ring *ring); void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags); + unsigned (*get_emit_ib_size) (struct amdgpu_ring *ring); + unsigned (*get_dma_frame_size) (struct amdgpu_ring *ring); }; /* @@ -2288,6 +2290,8 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib))) #define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r)) #define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o)) +#define amdgpu_ring_get_emit_ib_size(r) (r)->funcs->get_emit_ib_size((r)) +#define amdgpu_ring_get_dma_frame_size(r) (r)->funcs->get_dma_frame_size((r)) #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) -- cgit v1.1 From a851d0f4ca60416e0e969b5f752536bc28484823 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 10:56:33 -0400 Subject: drm/amdgpu/gfx6: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index e7293f6..410b29c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -2685,6 +2685,33 @@ static void gfx_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) amdgpu_ring_write(ring, 0); } +static unsigned gfx_v6_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 6; /* gfx_v6_0_ring_emit_ib */ +} + +static unsigned gfx_v6_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring) +{ + return + 5 + /* gfx_v6_0_ring_emit_hdp_flush */ + 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */ + 14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */ + 7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */ + 17 + 6 + /* gfx_v6_0_ring_emit_vm_flush */ + 3; /* gfx_v6_ring_emit_cntxcntl */ +} + +static unsigned gfx_v6_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring) +{ + return + 5 + /* gfx_v6_0_ring_emit_hdp_flush */ + 5 + /* gfx_v6_0_ring_emit_hdp_invalidate */ + 7 + /* gfx_v6_0_ring_emit_pipeline_sync */ + 17 + /* gfx_v6_0_ring_emit_vm_flush */ + 14 + 14 + 14; /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */ +} + static const struct amdgpu_gfx_funcs gfx_v6_0_gfx_funcs = { .get_gpu_clock_counter = &gfx_v6_0_get_gpu_clock_counter, .select_se_sh = &gfx_v6_0_select_se_sh, @@ -3113,6 +3140,8 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { .test_ib = gfx_v6_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .emit_cntxcntl = gfx_v6_ring_emit_cntxcntl, + .get_emit_ib_size = gfx_v6_0_ring_get_emit_ib_size, + .get_dma_frame_size = gfx_v6_0_ring_get_dma_frame_size_gfx, }; static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { @@ -3129,6 +3158,8 @@ static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = { .test_ring = gfx_v6_0_ring_test_ring, .test_ib = gfx_v6_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, + .get_emit_ib_size = gfx_v6_0_ring_get_emit_ib_size, + .get_dma_frame_size = gfx_v6_0_ring_get_dma_frame_size_compute, }; static void gfx_v6_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From b04e26b3c7a74c8bf8f4a7568de1e7d69b1dbee2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 10:57:20 -0400 Subject: drm/amdgpu/gfx7: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 8c780f6..90102f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4190,6 +4190,41 @@ static void gfx_v7_0_ring_emit_gds_switch(struct amdgpu_ring *ring, amdgpu_ring_write(ring, (1 << (oa_size + oa_base)) - (1 << oa_base)); } +static unsigned gfx_v7_0_ring_get_emit_ib_size_gfx(struct amdgpu_ring *ring) +{ + return + 4; /* gfx_v7_0_ring_emit_ib_gfx */ +} + +static unsigned gfx_v7_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring) +{ + return + 20 + /* gfx_v7_0_ring_emit_gds_switch */ + 7 + /* gfx_v7_0_ring_emit_hdp_flush */ + 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */ + 12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */ + 7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */ + 17 + 6 + /* gfx_v7_0_ring_emit_vm_flush */ + 3; /* gfx_v7_ring_emit_cntxcntl */ +} + +static unsigned gfx_v7_0_ring_get_emit_ib_size_compute(struct amdgpu_ring *ring) +{ + return + 4; /* gfx_v7_0_ring_emit_ib_compute */ +} + +static unsigned gfx_v7_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring) +{ + return + 20 + /* gfx_v7_0_ring_emit_gds_switch */ + 7 + /* gfx_v7_0_ring_emit_hdp_flush */ + 5 + /* gfx_v7_0_ring_emit_hdp_invalidate */ + 7 + /* gfx_v7_0_ring_emit_pipeline_sync */ + 17 + /* gfx_v7_0_ring_emit_vm_flush */ + 7 + 7 + 7; /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */ +} + static const struct amdgpu_gfx_funcs gfx_v7_0_gfx_funcs = { .get_gpu_clock_counter = &gfx_v7_0_get_gpu_clock_counter, .select_se_sh = &gfx_v7_0_select_se_sh, @@ -4958,6 +4993,8 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, .emit_cntxcntl = gfx_v7_ring_emit_cntxcntl, + .get_emit_ib_size = gfx_v7_0_ring_get_emit_ib_size_gfx, + .get_dma_frame_size = gfx_v7_0_ring_get_dma_frame_size_gfx, }; static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { @@ -4976,6 +5013,8 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { .test_ib = gfx_v7_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, + .get_emit_ib_size = gfx_v7_0_ring_get_emit_ib_size_compute, + .get_dma_frame_size = gfx_v7_0_ring_get_dma_frame_size_compute, }; static void gfx_v7_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From 7512ad16b532eee288a85a55a41ebf7d0eb8080d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 10:57:39 -0400 Subject: drm/amdgpu/gfx8: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index e2ed71d..1e7c615 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6105,6 +6105,42 @@ static void gfx_v8_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) amdgpu_ring_write(ring, 0); } +static unsigned gfx_v8_0_ring_get_emit_ib_size_gfx(struct amdgpu_ring *ring) +{ + return + 4; /* gfx_v8_0_ring_emit_ib_gfx */ +} + +static unsigned gfx_v8_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring) +{ + return + 20 + /* gfx_v8_0_ring_emit_gds_switch */ + 7 + /* gfx_v8_0_ring_emit_hdp_flush */ + 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */ + 6 + 6 + 6 +/* gfx_v8_0_ring_emit_fence_gfx x3 for user fence, vm fence */ + 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ + 256 + 19 + /* gfx_v8_0_ring_emit_vm_flush */ + 2 + /* gfx_v8_ring_emit_sb */ + 3; /* gfx_v8_ring_emit_cntxcntl */ +} + +static unsigned gfx_v8_0_ring_get_emit_ib_size_compute(struct amdgpu_ring *ring) +{ + return + 4; /* gfx_v8_0_ring_emit_ib_compute */ +} + +static unsigned gfx_v8_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring) +{ + return + 20 + /* gfx_v8_0_ring_emit_gds_switch */ + 7 + /* gfx_v8_0_ring_emit_hdp_flush */ + 5 + /* gfx_v8_0_ring_emit_hdp_invalidate */ + 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ + 17 + /* gfx_v8_0_ring_emit_vm_flush */ + 7 + 7 + 7; /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */ +} + static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev, enum amdgpu_interrupt_state state) { @@ -6288,6 +6324,8 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .pad_ib = amdgpu_ring_generic_pad_ib, .emit_switch_buffer = gfx_v8_ring_emit_sb, .emit_cntxcntl = gfx_v8_ring_emit_cntxcntl, + .get_emit_ib_size = gfx_v8_0_ring_get_emit_ib_size_gfx, + .get_dma_frame_size = gfx_v8_0_ring_get_dma_frame_size_gfx, }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { @@ -6306,6 +6344,8 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { .test_ib = gfx_v8_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, + .get_emit_ib_size = gfx_v8_0_ring_get_emit_ib_size_compute, + .get_dma_frame_size = gfx_v8_0_ring_get_dma_frame_size_compute, }; static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From 229e2d46da4f5ec7ca7845ccbbdf04bf445c048e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 10:58:12 -0400 Subject: drm/amdgpu/si_dma: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si_dma.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 4cbd408..de35819 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -495,6 +495,22 @@ static void si_dma_ring_emit_vm_flush(struct amdgpu_ring *ring, amdgpu_ring_write(ring, (0 << 28) | 0x20); /* func(always) | poll interval */ } +static unsigned si_dma_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 7 + 3; /* si_dma_ring_emit_ib */ +} + +static unsigned si_dma_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 3 + /* si_dma_ring_emit_hdp_flush */ + 3 + /* si_dma_ring_emit_hdp_invalidate */ + 6 + /* si_dma_ring_emit_pipeline_sync */ + 12 + /* si_dma_ring_emit_vm_flush */ + 9 + 9 + 9; /* si_dma_ring_emit_fence x3 for user fence, vm fence */ +} + static int si_dma_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -778,6 +794,8 @@ static const struct amdgpu_ring_funcs si_dma_ring_funcs = { .test_ib = si_dma_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = si_dma_ring_pad_ib, + .get_emit_ib_size = si_dma_ring_get_emit_ib_size, + .get_dma_frame_size = si_dma_ring_get_dma_frame_size, }; static void si_dma_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From 77b52a5bc66916c34a443563f070e65449feb683 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 10:58:52 -0400 Subject: drm/amdgpu/cik_sdma: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index e71cd12..e6d7bf9 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -847,6 +847,22 @@ static void cik_sdma_ring_emit_vm_flush(struct amdgpu_ring *ring, amdgpu_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */ } +static unsigned cik_sdma_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 7 + 4; /* cik_sdma_ring_emit_ib */ +} + +static unsigned cik_sdma_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 6 + /* cik_sdma_ring_emit_hdp_flush */ + 3 + /* cik_sdma_ring_emit_hdp_invalidate */ + 6 + /* cik_sdma_ring_emit_pipeline_sync */ + 12 + /* cik_sdma_ring_emit_vm_flush */ + 9 + 9 + 9; /* cik_sdma_ring_emit_fence x3 for user fence, vm fence */ +} + static void cik_enable_sdma_mgcg(struct amdgpu_device *adev, bool enable) { @@ -1220,6 +1236,8 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = { .test_ib = cik_sdma_ring_test_ib, .insert_nop = cik_sdma_ring_insert_nop, .pad_ib = cik_sdma_ring_pad_ib, + .get_emit_ib_size = cik_sdma_ring_get_emit_ib_size, + .get_dma_frame_size = cik_sdma_ring_get_dma_frame_size, }; static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From fe7c0f26daa615e3cc4b817f657e86d6e75c261d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 10:59:12 -0400 Subject: drm/amdgpu/sdma2.4: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index e822296..82c731b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -906,6 +906,22 @@ static void sdma_v2_4_ring_emit_vm_flush(struct amdgpu_ring *ring, SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */ } +static unsigned sdma_v2_4_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 7 + 6; /* sdma_v2_4_ring_emit_ib */ +} + +static unsigned sdma_v2_4_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 6 + /* sdma_v2_4_ring_emit_hdp_flush */ + 3 + /* sdma_v2_4_ring_emit_hdp_invalidate */ + 6 + /* sdma_v2_4_ring_emit_pipeline_sync */ + 12 + /* sdma_v2_4_ring_emit_vm_flush */ + 10 + 10 + 10; /* sdma_v2_4_ring_emit_fence x3 for user fence, vm fence */ +} + static int sdma_v2_4_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1224,6 +1240,8 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { .test_ib = sdma_v2_4_ring_test_ib, .insert_nop = sdma_v2_4_ring_insert_nop, .pad_ib = sdma_v2_4_ring_pad_ib, + .get_emit_ib_size = sdma_v2_4_ring_get_emit_ib_size, + .get_dma_frame_size = sdma_v2_4_ring_get_dma_frame_size, }; static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From 928d467448596228af2d4fe3f13251e4fa8de656 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 10:59:31 -0400 Subject: drm/amdgpu/sdma3: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index cabb9fe..62e2f4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1108,6 +1108,22 @@ static void sdma_v3_0_ring_emit_vm_flush(struct amdgpu_ring *ring, SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */ } +static unsigned sdma_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 7 + 6; /* sdma_v3_0_ring_emit_ib */ +} + +static unsigned sdma_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 6 + /* sdma_v3_0_ring_emit_hdp_flush */ + 3 + /* sdma_v3_0_ring_emit_hdp_invalidate */ + 6 + /* sdma_v3_0_ring_emit_pipeline_sync */ + 12 + /* sdma_v3_0_ring_emit_vm_flush */ + 10 + 10 + 10; /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */ +} + static int sdma_v3_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1569,6 +1585,8 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { .test_ib = sdma_v3_0_ring_test_ib, .insert_nop = sdma_v3_0_ring_insert_nop, .pad_ib = sdma_v3_0_ring_pad_ib, + .get_emit_ib_size = sdma_v3_0_ring_get_emit_ib_size, + .get_dma_frame_size = sdma_v3_0_ring_get_dma_frame_size, }; static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From 23f8f8006a5fd1ec2888a814d70064a84a0e4815 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 11:00:11 -0400 Subject: drm/amdgpu/uvd4.2: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 10c0407..f6c9415 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -526,6 +526,20 @@ static void uvd_v4_2_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, ib->length_dw); } +static unsigned uvd_v4_2_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 4; /* uvd_v4_2_ring_emit_ib */ +} + +static unsigned uvd_v4_2_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 2 + /* uvd_v4_2_ring_emit_hdp_flush */ + 2 + /* uvd_v4_2_ring_emit_hdp_invalidate */ + 14; /* uvd_v4_2_ring_emit_fence x1 no user fence */ +} + /** * uvd_v4_2_mc_resume - memory controller programming * @@ -756,6 +770,8 @@ static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_uvd_ring_begin_use, .end_use = amdgpu_uvd_ring_end_use, + .get_emit_ib_size = uvd_v4_2_ring_get_emit_ib_size, + .get_dma_frame_size = uvd_v4_2_ring_get_dma_frame_size, }; static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From cdbbb7846ce055c4e6ebf6c08560a6e9c8819ba9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 11:00:42 -0400 Subject: drm/amdgpu/uvd5: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index 8513376..400c16f 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -577,6 +577,20 @@ static void uvd_v5_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, ib->length_dw); } +static unsigned uvd_v5_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 6; /* uvd_v5_0_ring_emit_ib */ +} + +static unsigned uvd_v5_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 2 + /* uvd_v5_0_ring_emit_hdp_flush */ + 2 + /* uvd_v5_0_ring_emit_hdp_invalidate */ + 14; /* uvd_v5_0_ring_emit_fence x1 no user fence */ +} + static bool uvd_v5_0_is_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -807,6 +821,8 @@ static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_uvd_ring_begin_use, .end_use = amdgpu_uvd_ring_end_use, + .get_emit_ib_size = uvd_v5_0_ring_get_emit_ib_size, + .get_dma_frame_size = uvd_v5_0_ring_get_dma_frame_size, }; static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From c3f5875888cc4a65f16eb2298a5b4ba3a39fb1a6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 11:00:58 -0400 Subject: drm/amdgpu/uvd6: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 2abe8a9..e0fd9f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -725,6 +725,31 @@ static void uvd_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, 0xE); } +static unsigned uvd_v6_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 8; /* uvd_v6_0_ring_emit_ib */ +} + +static unsigned uvd_v6_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 2 + /* uvd_v6_0_ring_emit_hdp_flush */ + 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */ + 10 + /* uvd_v6_0_ring_emit_pipeline_sync */ + 14; /* uvd_v6_0_ring_emit_fence x1 no user fence */ +} + +static unsigned uvd_v6_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring) +{ + return + 2 + /* uvd_v6_0_ring_emit_hdp_flush */ + 2 + /* uvd_v6_0_ring_emit_hdp_invalidate */ + 10 + /* uvd_v6_0_ring_emit_pipeline_sync */ + 20 + /* uvd_v6_0_ring_emit_vm_flush */ + 14 + 14; /* uvd_v6_0_ring_emit_fence x2 vm fence */ +} + static bool uvd_v6_0_is_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1037,6 +1062,8 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_uvd_ring_begin_use, .end_use = amdgpu_uvd_ring_end_use, + .get_emit_ib_size = uvd_v6_0_ring_get_emit_ib_size, + .get_dma_frame_size = uvd_v6_0_ring_get_dma_frame_size, }; static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = { @@ -1056,6 +1083,8 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_uvd_ring_begin_use, .end_use = amdgpu_uvd_ring_end_use, + .get_emit_ib_size = uvd_v6_0_ring_get_emit_ib_size, + .get_dma_frame_size = uvd_v6_0_ring_get_dma_frame_size_vm, }; static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From a6f8d7286714363e615561e8aafdf78807fe079d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 11:01:26 -0400 Subject: drm/amdgpu/vce: add common ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 12 ++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index b0c6702..2c9ea9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -803,6 +803,18 @@ void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq, amdgpu_ring_write(ring, VCE_CMD_END); } +unsigned amdgpu_vce_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 4; /* amdgpu_vce_ring_emit_ib */ +} + +unsigned amdgpu_vce_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 6; /* amdgpu_vce_ring_emit_fence x1 no user fence */ +} + /** * amdgpu_vce_ring_test_ring - test if VCE ring is working * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h index 63f83d0..12729d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h @@ -42,5 +42,7 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring); int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout); void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring); void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring); +unsigned amdgpu_vce_ring_get_emit_ib_size(struct amdgpu_ring *ring); +unsigned amdgpu_vce_ring_get_dma_frame_size(struct amdgpu_ring *ring); #endif -- cgit v1.1 From 9d6b7a6447e8f5905c94782d3bd4b88a33846918 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 11:01:52 -0400 Subject: drm/amdgpu/vce2: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index 58af0da..76e64ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -622,6 +622,8 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_vce_ring_begin_use, .end_use = amdgpu_vce_ring_end_use, + .get_emit_ib_size = amdgpu_vce_ring_get_emit_ib_size, + .get_dma_frame_size = amdgpu_vce_ring_get_dma_frame_size, }; static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From 58fafbaf166673f1a5724b42360d6b35610727aa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 11:02:16 -0400 Subject: drm/amdgpu/vce3: add ring callbacks for ib and dma frame size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index a55ddc0..a6b4e27 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -808,6 +808,27 @@ static void vce_v3_0_emit_pipeline_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, seq); } +static unsigned vce_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 5; /* vce_v3_0_ring_emit_ib */ +} + +static unsigned vce_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 4 + /* vce_v3_0_emit_pipeline_sync */ + 6; /* amdgpu_vce_ring_emit_fence x1 no user fence */ +} + +static unsigned vce_v3_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring) +{ + return + 6 + /* vce_v3_0_emit_vm_flush */ + 4 + /* vce_v3_0_emit_pipeline_sync */ + 6 + 6; /* amdgpu_vce_ring_emit_fence x2 vm fence */ +} + const struct amd_ip_funcs vce_v3_0_ip_funcs = { .name = "vce_v3_0", .early_init = vce_v3_0_early_init, @@ -841,6 +862,8 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_vce_ring_begin_use, .end_use = amdgpu_vce_ring_end_use, + .get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size, + .get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size, }; static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { @@ -858,6 +881,8 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_vce_ring_begin_use, .end_use = amdgpu_vce_ring_end_use, + .get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size, + .get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size_vm, }; static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev) -- cgit v1.1 From 9a9db6ef7cf486f4849fe6bb8619009b5fd66399 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 16 Sep 2016 11:02:34 -0400 Subject: drm/amdgpu: use the new ring ib and dma frame size callbacks (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use them to more accurately determine the ring size required for ib submission. v2: drop extra alignment Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 2aa741c..4127e7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -125,7 +125,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, unsigned patch_offset = ~0; struct amdgpu_vm *vm; uint64_t fence_ctx; - uint32_t status = 0; + uint32_t status = 0, alloc_size; unsigned i; int r = 0; @@ -152,7 +152,10 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, return -EINVAL; } - r = amdgpu_ring_alloc(ring, 256 * num_ibs); + alloc_size = amdgpu_ring_get_dma_frame_size(ring) + + num_ibs * amdgpu_ring_get_emit_ib_size(ring); + + r = amdgpu_ring_alloc(ring, alloc_size); if (r) { dev_err(adev->dev, "scheduling IB failed (%d).\n", r); return r; -- cgit v1.1 From 9f31a0b0328cb70b9ea1058579710fb1439ee332 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Thu, 15 Sep 2016 21:43:26 +0800 Subject: drm/amdgpu: clean function declarations in amdgpu_ttm.c up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get 2 warnings when building kernel with W=1: drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c:985:5: warning: no previous prototype for 'amdgpu_ttm_init' [-Wmissing-prototypes] drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c:1092:6: warning: no previous prototype for 'amdgpu_ttm_fini' [-Wmissing-prototypes] In fact, both functions are declared in drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c, but should be declared in a header file, thus can be recognized in other file. So this patch moves the declarations into drivers/gpu/drm/amd/amdgpu/amdgpu.h. Reviewed-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 064172e..ee45d9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -2447,6 +2447,8 @@ void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc); void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size); u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev); int amdgpu_ttm_global_init(struct amdgpu_device *adev); +int amdgpu_ttm_init(struct amdgpu_device *adev); +void amdgpu_ttm_fini(struct amdgpu_device *adev); void amdgpu_program_register_sequence(struct amdgpu_device *adev, const u32 *registers, const u32 array_size); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 151a706..428aa00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -38,8 +38,6 @@ #include "amdgpu_trace.h" -int amdgpu_ttm_init(struct amdgpu_device *adev); -void amdgpu_ttm_fini(struct amdgpu_device *adev); static u64 amdgpu_get_vis_part_size(struct amdgpu_device *adev, struct ttm_mem_reg *mem) -- cgit v1.1 From 0aa3e2d0cbff4c42997d75f35bb660fd382544e6 Mon Sep 17 00:00:00 2001 From: Baoyou Xie Date: Thu, 15 Sep 2016 22:13:51 +0800 Subject: drm/radeon/radeon_device: remove unused function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get 2 warnings when building kernel with W=1: drivers/gpu/drm/radeon/radeon_device.c:1961:5: warning: no previous prototype for 'radeon_debugfs_init' [-Wmissing-prototypes] drivers/gpu/drm/radeon/radeon_device.c:1966:6: warning: no previous prototype for 'radeon_debugfs_cleanup' [-Wmissing-prototypes] In fact, these functions are dummy, but can be removed, so this patch removes them. Reviewed-by: Christian König Signed-off-by: Baoyou Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 11 ----------- drivers/gpu/drm/radeon/radeon_drv.c | 9 --------- 2 files changed, 20 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 8425b12..b423c01 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1958,14 +1958,3 @@ static void radeon_debugfs_remove_files(struct radeon_device *rdev) } #endif } - -#if defined(CONFIG_DEBUG_FS) -int radeon_debugfs_init(struct drm_minor *minor) -{ - return 0; -} - -void radeon_debugfs_cleanup(struct drm_minor *minor) -{ -} -#endif diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 5fdd48c..8f779e4 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -155,11 +155,6 @@ void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); extern long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#if defined(CONFIG_DEBUG_FS) -int radeon_debugfs_init(struct drm_minor *minor); -void radeon_debugfs_cleanup(struct drm_minor *minor); -#endif - /* atpx handler */ #if defined(CONFIG_VGA_SWITCHEROO) void radeon_register_atpx_handler(void); @@ -550,10 +545,6 @@ static struct drm_driver kms_driver = { .disable_vblank = radeon_disable_vblank_kms, .get_vblank_timestamp = radeon_get_vblank_timestamp_kms, .get_scanout_position = radeon_get_crtc_scanoutpos, -#if defined(CONFIG_DEBUG_FS) - .debugfs_init = radeon_debugfs_init, - .debugfs_cleanup = radeon_debugfs_cleanup, -#endif .irq_preinstall = radeon_driver_irq_preinstall_kms, .irq_postinstall = radeon_driver_irq_postinstall_kms, .irq_uninstall = radeon_driver_irq_uninstall_kms, -- cgit v1.1 From af1f85ddecfa341e684db950c34a1813d36750db Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 16 Sep 2016 18:32:26 +0900 Subject: drm/ttm: remove cpu_address member from ttm_tt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch 3d50d4dcb0 exposed the CPU address of DMA-allocated pages as returned by dma_alloc_coherent because Nouveau on Tegra needed it. This is not required anymore - as there were no other users for it, remove it and save some memory for everyone. Reviewed-by: Christian König Signed-off-by: Alexandre Courbot Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 2 -- drivers/gpu/drm/ttm/ttm_tt.c | 7 ++----- include/drm/ttm/ttm_bo_driver.h | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index bef9f6f..cec4b4b 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -858,7 +858,6 @@ static int ttm_dma_pool_get_pages(struct dma_pool *pool, if (count) { d_page = list_first_entry(&pool->free_list, struct dma_page, page_list); ttm->pages[index] = d_page->p; - ttm_dma->cpu_address[index] = d_page->vaddr; ttm_dma->dma_address[index] = d_page->dma; list_move_tail(&d_page->page_list, &ttm_dma->pages_list); r = 0; @@ -989,7 +988,6 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) INIT_LIST_HEAD(&ttm_dma->pages_list); for (i = 0; i < ttm->num_pages; i++) { ttm->pages[i] = NULL; - ttm_dma->cpu_address[i] = 0; ttm_dma->dma_address[i] = 0; } diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index bc5aa57..aee3c00 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -57,10 +57,8 @@ static void ttm_dma_tt_alloc_page_directory(struct ttm_dma_tt *ttm) { ttm->ttm.pages = drm_calloc_large(ttm->ttm.num_pages, sizeof(*ttm->ttm.pages) + - sizeof(*ttm->dma_address) + - sizeof(*ttm->cpu_address)); - ttm->cpu_address = (void *) (ttm->ttm.pages + ttm->ttm.num_pages); - ttm->dma_address = (void *) (ttm->cpu_address + ttm->ttm.num_pages); + sizeof(*ttm->dma_address)); + ttm->dma_address = (void *) (ttm->ttm.pages + ttm->ttm.num_pages); } #ifdef CONFIG_X86 @@ -244,7 +242,6 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma) drm_free_large(ttm->pages); ttm->pages = NULL; - ttm_dma->cpu_address = NULL; ttm_dma->dma_address = NULL; } EXPORT_SYMBOL(ttm_dma_tt_fini); diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index c986fa7..4f0a921 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -133,7 +133,6 @@ struct ttm_tt { * struct ttm_dma_tt * * @ttm: Base ttm_tt struct. - * @cpu_address: The CPU address of the pages * @dma_address: The DMA (bus) addresses of the pages * @pages_list: used by some page allocation backend * @@ -143,7 +142,6 @@ struct ttm_tt { */ struct ttm_dma_tt { struct ttm_tt ttm; - void **cpu_address; dma_addr_t *dma_address; struct list_head pages_list; }; -- cgit v1.1