From c9da4a4b3820782753c1c455242eca7e5a69eedb Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Fri, 10 Oct 2014 12:28:36 +0900 Subject: drm/radeon: Try placing NO_CPU_ACCESS BOs outside of CPU accessible VRAM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids them getting in the way of BOs which might be accessed by the CPU. They can still go to the CPU accessible part of VRAM though if there's no space outside of it. Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_object.c | 42 ++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index a9717b3fbf1b..73288c6077e5 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -474,7 +474,7 @@ struct radeon_bo { struct list_head list; /* Protected by tbo.reserved */ u32 initial_domain; - struct ttm_place placements[3]; + struct ttm_place placements[4]; struct ttm_placement placement; struct ttm_buffer_object tbo; struct ttm_bo_kmap_obj kmap; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 99a960a4f302..7f3b1e1b05b0 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -99,22 +99,39 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) rbo->placement.placement = rbo->placements; rbo->placement.busy_placement = rbo->placements; - if (domain & RADEON_GEM_DOMAIN_VRAM) + if (domain & RADEON_GEM_DOMAIN_VRAM) { + /* Try placing BOs which don't need CPU access outside of the + * CPU accessible part of VRAM + */ + if ((rbo->flags & RADEON_GEM_NO_CPU_ACCESS) && + rbo->rdev->mc.visible_vram_size < rbo->rdev->mc.real_vram_size) { + rbo->placements[c].fpfn = + rbo->rdev->mc.visible_vram_size >> PAGE_SHIFT; + rbo->placements[c++].flags = TTM_PL_FLAG_WC | + TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_VRAM; + } + + rbo->placements[c].fpfn = 0; rbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; + } if (domain & RADEON_GEM_DOMAIN_GTT) { if (rbo->flags & RADEON_GEM_GTT_UC) { + rbo->placements[c].fpfn = 0; rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_TT; } else if ((rbo->flags & RADEON_GEM_GTT_WC) || (rbo->rdev->flags & RADEON_IS_AGP)) { + rbo->placements[c].fpfn = 0; rbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_TT; } else { + rbo->placements[c].fpfn = 0; rbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; } @@ -122,30 +139,35 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) if (domain & RADEON_GEM_DOMAIN_CPU) { if (rbo->flags & RADEON_GEM_GTT_UC) { + rbo->placements[c].fpfn = 0; rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_SYSTEM; } else if ((rbo->flags & RADEON_GEM_GTT_WC) || rbo->rdev->flags & RADEON_IS_AGP) { + rbo->placements[c].fpfn = 0; rbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_SYSTEM; } else { + rbo->placements[c].fpfn = 0; rbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM; } } - if (!c) + if (!c) { + rbo->placements[c].fpfn = 0; rbo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; + } rbo->placement.num_placement = c; rbo->placement.num_busy_placement = c; for (i = 0; i < c; ++i) { - rbo->placements[i].fpfn = 0; if ((rbo->flags & RADEON_GEM_CPU_ACCESS) && - (rbo->placements[i].flags & TTM_PL_FLAG_VRAM)) + (rbo->placements[i].flags & TTM_PL_FLAG_VRAM) && + !rbo->placements[i].fpfn) rbo->placements[i].lpfn = rbo->rdev->mc.visible_vram_size >> PAGE_SHIFT; else @@ -743,8 +765,8 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { struct radeon_device *rdev; struct radeon_bo *rbo; - unsigned long offset, size; - int r; + unsigned long offset, size, lpfn; + int i, r; if (!radeon_ttm_bo_is_radeon_bo(bo)) return 0; @@ -761,7 +783,13 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) /* hurrah the memory is not visible ! */ radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); - rbo->placements[0].lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; + lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; + for (i = 0; i < rbo->placement.num_placement; i++) { + /* Force into visible VRAM */ + if ((rbo->placements[i].flags & TTM_PL_FLAG_VRAM) && + (!rbo->placements[i].lpfn || rbo->placements[i].lpfn > lpfn)) + rbo->placements[i].lpfn = lpfn; + } r = ttm_bo_validate(bo, &rbo->placement, false, false); if (unlikely(r == -ENOMEM)) { radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); -- cgit v1.2.3 From 2a85aedd117cab38fd29c2c1a15b4c7338850d53 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 9 Oct 2014 18:55:04 +0900 Subject: drm/radeon: Try evicting from CPU accessible to inaccessible VRAM first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_ttm.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 8624979afb65..cbe7b32d181c 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -198,7 +198,30 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, case TTM_PL_VRAM: if (rbo->rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready == false) radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); - else + else if (rbo->rdev->mc.visible_vram_size < rbo->rdev->mc.real_vram_size && + bo->mem.start < (rbo->rdev->mc.visible_vram_size >> PAGE_SHIFT)) { + unsigned fpfn = rbo->rdev->mc.visible_vram_size >> PAGE_SHIFT; + int i; + + /* Try evicting to the CPU inaccessible part of VRAM + * first, but only set GTT as busy placement, so this + * BO will be evicted to GTT rather than causing other + * BOs to be evicted from VRAM + */ + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM | + RADEON_GEM_DOMAIN_GTT); + rbo->placement.num_busy_placement = 0; + for (i = 0; i < rbo->placement.num_placement; i++) { + if (rbo->placements[i].flags & TTM_PL_FLAG_VRAM) { + if (rbo->placements[0].fpfn < fpfn) + rbo->placements[0].fpfn = fpfn; + } else { + rbo->placement.busy_placement = + &rbo->placements[i]; + rbo->placement.num_busy_placement = 1; + } + } + } else radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); break; case TTM_PL_TT: -- cgit v1.2.3 From a8b5ebe6b56cca0f12f0f53cdae2f03950f4100f Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 28 Oct 2014 18:35:02 +0900 Subject: drm/radeon: Set TTM_PL_FLAG_TOPDOWN also for RADEON_GEM_CPU_ACCESS BOs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I wasn't sure if TTM_PL_FLAG_TOPDOWN works correctly with non-0 lpfn, but AFAICT it does. Reviewed-by: Lauri Kasanen Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_object.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 7f3b1e1b05b0..33e6c7a89c32 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -179,9 +179,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) * improve fragmentation quality. * 512kb was measured as the most optimal number. */ - if (!((rbo->flags & RADEON_GEM_CPU_ACCESS) && - (rbo->placements[i].flags & TTM_PL_FLAG_VRAM)) && - rbo->tbo.mem.size > 512 * 1024) { + if (rbo->tbo.mem.size > 512 * 1024) { for (i = 0; i < c; i++) { rbo->placements[i].flags |= TTM_PL_FLAG_TOPDOWN; } -- cgit v1.2.3 From c165812cbf6cf4bdd62f174115c01017f55f0933 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 28 Oct 2014 18:35:03 +0900 Subject: drm/ttm: Add DRM_MM_SEARCH_BELOW for TTM_PL_FLAG_TOPDOWN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the BO should be placed at the top of the area, we should start looking for holes from the top. Reviewed-by: Lauri Kasanen Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_bo_manager.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index 964387fc5c8f..1e93f6c198a2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -55,6 +55,7 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; struct drm_mm *mm = &rman->mm; struct drm_mm_node *node = NULL; + enum drm_mm_search_flags sflags = DRM_MM_SEARCH_BEST; enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT; unsigned long lpfn; int ret; @@ -67,15 +68,16 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, if (!node) return -ENOMEM; - if (place->flags & TTM_PL_FLAG_TOPDOWN) + if (place->flags & TTM_PL_FLAG_TOPDOWN) { + sflags |= DRM_MM_SEARCH_BELOW; aflags = DRM_MM_CREATE_TOP; + } spin_lock(&rman->lock); ret = drm_mm_insert_node_in_range_generic(mm, node, mem->num_pages, mem->page_alignment, 0, place->fpfn, lpfn, - DRM_MM_SEARCH_BEST, - aflags); + sflags, aflags); spin_unlock(&rman->lock); if (unlikely(ret)) { -- cgit v1.2.3 From 507d0ca71bcbefd8623eb20f4de1b5f4e103a48b Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 28 Oct 2014 18:35:04 +0900 Subject: drm/ttm: Use only DRM_MM_SEARCH_BELOW for TTM_PL_FLAG_TOPDOWN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRM_MM_SEARCH_BEST gets the smallest hole which can fit the BO. That seems against the idea of TTM_PL_FLAG_TOPDOWN: * The smallest hole may be in the overall bottom of the area * If the hole isn't much larger than the BO, it doesn't make much difference whether the BO is placed at the bottom or at the top of the hole Reviewed-by: Lauri Kasanen Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_bo_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index 1e93f6c198a2..aa0bd054d3e9 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -69,7 +69,7 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, return -ENOMEM; if (place->flags & TTM_PL_FLAG_TOPDOWN) { - sflags |= DRM_MM_SEARCH_BELOW; + sflags = DRM_MM_SEARCH_BELOW; aflags = DRM_MM_CREATE_TOP; } -- cgit v1.2.3 From 9b92d1ec62d515c28bb579466e2397ab20c1735a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 8 Sep 2014 02:51:49 -0400 Subject: drm/radeon/dpm: grab fan info from vbios Required for fan control support. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 5 +++++ drivers/gpu/drm/radeon/radeon_atombios.c | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 73288c6077e5..908f349a6362 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1623,6 +1623,11 @@ struct radeon_pm { /* internal thermal controller on rv6xx+ */ enum radeon_int_thermal_type int_thermal_type; struct device *int_hwmon_dev; + /* fan control parameters */ + bool no_fan; + u8 fan_pulses_per_revolution; + u8 fan_min_rpm; + u8 fan_max_rpm; /* dpm */ bool dpm_enabled; struct radeon_dpm dpm; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index df69b92ba164..9beadf87056e 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2248,6 +2248,14 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r /* add the i2c bus for thermal/fan chip */ if (controller->ucType > 0) { + if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) + rdev->pm.no_fan = true; + rdev->pm.fan_pulses_per_revolution = + controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + if (rdev->pm.fan_pulses_per_revolution) { + rdev->pm.fan_min_rpm = controller->ucFanMinRPM; + rdev->pm.fan_max_rpm = controller->ucFanMaxRPM; + } if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { DRM_INFO("Internal thermal controller %s fan control\n", (controller->ucFanParameters & -- cgit v1.2.3 From 2271e2e2a2525f826549f1aa19db36e0b80082fe Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 8 Sep 2014 03:35:17 -0400 Subject: drm/radeon: rework SI dpm thermal setup In preparation for fan control. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si_dpm.c | 63 ++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 676e6c2ba90a..b59e1d6b27ab 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -5817,8 +5817,33 @@ void si_dpm_setup_asic(struct radeon_device *rdev) si_enable_acpi_power_management(rdev); } -static int si_set_thermal_temperature_range(struct radeon_device *rdev, - int min_temp, int max_temp) +static int si_thermal_enable_alert(struct radeon_device *rdev, + bool enable) +{ + u32 thermal_int = RREG32(CG_THERMAL_INT); + + if (enable) { + PPSMC_Result result; + + thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; + rdev->irq.dpm_thermal = true; + result = si_send_msg_to_smc(rdev, 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); + rdev->irq.dpm_thermal = false; + } + + WREG32(CG_THERMAL_INT, thermal_int); + + return 0; +} + +static int si_thermal_set_temperature_range(struct radeon_device *rdev, + int min_temp, int max_temp) { int low_temp = 0 * 1000; int high_temp = 255 * 1000; @@ -5959,26 +5984,32 @@ int si_dpm_enable(struct radeon_device *rdev) return 0; } -int si_dpm_late_enable(struct radeon_device *rdev) +static int si_set_temperature_range(struct radeon_device *rdev) { int ret; - if (rdev->irq.installed && - r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { - PPSMC_Result result; + ret = si_thermal_enable_alert(rdev, false); + if (ret) + return ret; + ret = si_thermal_set_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); + if (ret) + return ret; + ret = si_thermal_enable_alert(rdev, true); + if (ret) + return ret; - ret = si_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) - return ret; - rdev->irq.dpm_thermal = true; - radeon_irq_set(rdev); - result = si_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt); + return ret; +} - if (result != PPSMC_Result_OK) - DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); - } +int si_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; - return 0; + ret = si_set_temperature_range(rdev); + if (ret) + return ret; + + return ret; } void si_dpm_disable(struct radeon_device *rdev) -- cgit v1.2.3 From 1955f107a7bf5c9f718bf5025a24f5ff1607d7b2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sun, 14 Sep 2014 23:45:30 -0400 Subject: drm/radeon: rework CI dpm thermal setup In preparation for fan control. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 70 +++++++++++++++++++++++++++++------------ drivers/gpu/drm/radeon/ppsmc.h | 4 ++- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 11a55e9dad7f..51bf7980bd6a 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -814,7 +814,7 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev, } } -static int ci_set_thermal_temperature_range(struct radeon_device *rdev, +static int ci_thermal_set_temperature_range(struct radeon_device *rdev, int min_temp, int max_temp) { int low_temp = 0 * 1000; @@ -850,6 +850,35 @@ static int ci_set_thermal_temperature_range(struct radeon_device *rdev, return 0; } +static int ci_thermal_enable_alert(struct radeon_device *rdev, + bool enable) +{ + u32 thermal_int = RREG32_SMC(CG_THERMAL_INT); + PPSMC_Result result; + + if (enable) { + thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); + rdev->irq.dpm_thermal = false; + result = ci_send_msg_to_smc(rdev, PPSMC_MSG_Thermal_Cntl_Enable); + 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; + rdev->irq.dpm_thermal = true; + result = ci_send_msg_to_smc(rdev, PPSMC_MSG_Thermal_Cntl_Disable); + if (result != PPSMC_Result_OK) { + DRM_DEBUG_KMS("Could not disable thermal interrupts.\n"); + return -EINVAL; + } + } + + WREG32_SMC(CG_THERMAL_INT, thermal_int); + + return 0; +} + #if 0 static int ci_read_smc_soft_register(struct radeon_device *rdev, u16 reg_offset, u32 *value) @@ -4682,29 +4711,30 @@ int ci_dpm_enable(struct radeon_device *rdev) return 0; } -int ci_dpm_late_enable(struct radeon_device *rdev) +static int ci_set_temperature_range(struct radeon_device *rdev) { int ret; - if (rdev->irq.installed && - r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { -#if 0 - PPSMC_Result result; -#endif - ret = ci_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) { - DRM_ERROR("ci_set_thermal_temperature_range failed\n"); - return ret; - } - rdev->irq.dpm_thermal = true; - radeon_irq_set(rdev); -#if 0 - result = ci_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt); + ret = ci_thermal_enable_alert(rdev, false); + if (ret) + return ret; + ret = ci_thermal_set_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); + if (ret) + return ret; + ret = ci_thermal_enable_alert(rdev, true); + if (ret) + return ret; - if (result != PPSMC_Result_OK) - DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); -#endif - } + return ret; +} + +int ci_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; + + ret = ci_set_temperature_range(rdev); + if (ret) + return ret; ci_dpm_powergate_uvd(rdev, true); diff --git a/drivers/gpu/drm/radeon/ppsmc.h b/drivers/gpu/drm/radeon/ppsmc.h index 5670b8291285..11c0e4d5c0bf 100644 --- a/drivers/gpu/drm/radeon/ppsmc.h +++ b/drivers/gpu/drm/radeon/ppsmc.h @@ -106,6 +106,7 @@ typedef uint8_t PPSMC_Result; #define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) #define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) #define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) +#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) #define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) #define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) #define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) @@ -157,10 +158,11 @@ typedef uint8_t PPSMC_Result; #define PPSMC_MSG_DPM_Config ((uint32_t) 0x102) #define PPSMC_MSG_DPM_ForceState ((uint32_t) 0x104) #define PPSMC_MSG_PG_SIMD_Config ((uint32_t) 0x108) -#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint32_t) 0x112) +#define PPSMC_MSG_Thermal_Cntl_Enable ((uint32_t) 0x10a) #define PPSMC_MSG_Voltage_Cntl_Enable ((uint32_t) 0x109) #define PPSMC_MSG_VCEPowerOFF ((uint32_t) 0x10e) #define PPSMC_MSG_VCEPowerON ((uint32_t) 0x10f) +#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint32_t) 0x112) #define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d) #define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e) #define PPSMC_MSG_EnableBAPM ((uint32_t) 0x120) -- cgit v1.2.3 From 129acb7c0b682512e89c4f65c33593d50f2f49a9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 11:05:04 -0500 Subject: drm/radeon: fix typo in CI dpm disable Need to disable DS, not enable it when disabling dpm. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/ci_dpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 51bf7980bd6a..7092034901bd 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -4759,7 +4759,7 @@ void ci_dpm_disable(struct radeon_device *rdev) ci_enable_spread_spectrum(rdev, false); ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, false); ci_stop_dpm(rdev); - ci_enable_ds_master_switch(rdev, true); + ci_enable_ds_master_switch(rdev, false); ci_enable_ulv(rdev, false); ci_clear_vc(rdev); ci_reset_to_default(rdev); -- cgit v1.2.3 From 09e619c0c60013921678994a9888c8abe2a6e10b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 11:16:25 -0500 Subject: drm/radeon: export radeon_atombios_lookup_gpio We need it for dpm. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atombios.c | 12 ++++++------ drivers/gpu/drm/radeon/radeon_mode.h | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 9beadf87056e..7ef3d9e53af5 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -196,8 +196,8 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev) } } -static struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, - u8 id) +struct radeon_gpio_rec radeon_atombios_lookup_gpio(struct radeon_device *rdev, + u8 id) { struct atom_context *ctx = rdev->mode_info.atom_context; struct radeon_gpio_rec gpio; @@ -801,7 +801,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) hpd_record = (ATOM_HPD_INT_RECORD *) record; - gpio = radeon_lookup_gpio(rdev, + gpio = radeon_atombios_lookup_gpio(rdev, hpd_record->ucHPDIntGPIOID); hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); hpd.plugged_state = hpd_record->ucPlugged_PinState; @@ -2128,7 +2128,7 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO; rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = - radeon_lookup_gpio(rdev, + radeon_atombios_lookup_gpio(rdev, power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = @@ -2164,7 +2164,7 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO; rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = - radeon_lookup_gpio(rdev, + radeon_atombios_lookup_gpio(rdev, power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = @@ -2200,7 +2200,7 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO; rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = - radeon_lookup_gpio(rdev, + radeon_atombios_lookup_gpio(rdev, power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 04db2fdd8692..0ef1413c3117 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -748,6 +748,8 @@ extern bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, extern bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, struct radeon_atom_ss *ss, int id, u32 clock); +extern struct radeon_gpio_rec radeon_atombios_lookup_gpio(struct radeon_device *rdev, + u8 id); extern void radeon_compute_pll_legacy(struct radeon_pll *pll, uint64_t freq, -- cgit v1.2.3 From 727b3d25be4116315f4488ee1918ec64927b3eb4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 11:34:57 -0500 Subject: drm/radeon: store the gpio shift as well We need this in the dpm code. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atombios.c | 1 + drivers/gpu/drm/radeon/radeon_mode.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 7ef3d9e53af5..dbc94f300297 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -221,6 +221,7 @@ struct radeon_gpio_rec radeon_atombios_lookup_gpio(struct radeon_device *rdev, if (id == pin->ucGPIO_ID) { gpio.id = pin->ucGPIO_ID; gpio.reg = le16_to_cpu(pin->usGpioPin_AIndex) * 4; + gpio.shift = pin->ucGpioPinBitShift; gpio.mask = (1 << pin->ucGpioPinBitShift); gpio.valid = true; break; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 0ef1413c3117..64eba7ebb354 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -462,6 +462,7 @@ struct radeon_gpio_rec { u8 id; u32 reg; u32 mask; + u32 shift; }; struct radeon_hpd { -- cgit v1.2.3 From 34fc0b58d91f7eef2884b5ae798f760323831ae7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 11:52:12 -0500 Subject: drm/radeon/ci: handle gpio controlled dpm features properly Certain feature enablement depends on entries in the atom gpio pin table. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 51 +++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/ci_dpm.h | 2 ++ 2 files changed, 53 insertions(+) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 7092034901bd..9a3c71c0e66e 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -5098,6 +5098,8 @@ void ci_dpm_fini(struct radeon_device *rdev) int ci_dpm_init(struct radeon_device *rdev) { int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); + SMU7_Discrete_DpmTable *dpm_table; + struct radeon_gpio_rec gpio; u16 data_offset, size; u8 frev, crev; struct ci_power_info *pi; @@ -5231,6 +5233,55 @@ int ci_dpm_init(struct radeon_device *rdev) pi->uvd_enabled = false; + dpm_table = &pi->smc_state_table; + + gpio = radeon_atombios_lookup_gpio(rdev, VDDC_VRHOT_GPIO_PINID); + if (gpio.valid) { + dpm_table->VRHotGpio = gpio.shift; + rdev->pm.dpm.platform_caps |= ATOM_PP_PLATFORM_CAP_REGULATOR_HOT; + } else { + dpm_table->VRHotGpio = CISLANDS_UNUSED_GPIO_PIN; + rdev->pm.dpm.platform_caps &= ~ATOM_PP_PLATFORM_CAP_REGULATOR_HOT; + } + + gpio = radeon_atombios_lookup_gpio(rdev, PP_AC_DC_SWITCH_GPIO_PINID); + if (gpio.valid) { + dpm_table->AcDcGpio = gpio.shift; + rdev->pm.dpm.platform_caps |= ATOM_PP_PLATFORM_CAP_HARDWAREDC; + } else { + dpm_table->AcDcGpio = CISLANDS_UNUSED_GPIO_PIN; + rdev->pm.dpm.platform_caps &= ~ATOM_PP_PLATFORM_CAP_HARDWAREDC; + } + + gpio = radeon_atombios_lookup_gpio(rdev, VDDC_PCC_GPIO_PINID); + if (gpio.valid) { + u32 tmp = RREG32_SMC(CNB_PWRMGT_CNTL); + + switch (gpio.shift) { + case 0: + tmp &= ~GNB_SLOW_MODE_MASK; + tmp |= GNB_SLOW_MODE(1); + break; + case 1: + tmp &= ~GNB_SLOW_MODE_MASK; + tmp |= GNB_SLOW_MODE(2); + break; + case 2: + tmp |= GNB_SLOW; + break; + case 3: + tmp |= FORCE_NB_PS1; + break; + case 4: + tmp |= DPM_ENABLED; + break; + default: + DRM_ERROR("Invalid PCC GPIO!"); + break; + } + WREG32_SMC(CNB_PWRMGT_CNTL, tmp); + } + pi->voltage_control = CISLANDS_VOLTAGE_CONTROL_NONE; pi->vddci_control = CISLANDS_VOLTAGE_CONTROL_NONE; pi->mvdd_control = CISLANDS_VOLTAGE_CONTROL_NONE; diff --git a/drivers/gpu/drm/radeon/ci_dpm.h b/drivers/gpu/drm/radeon/ci_dpm.h index 93bbed977ffb..615cb2cacf2c 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.h +++ b/drivers/gpu/drm/radeon/ci_dpm.h @@ -33,6 +33,8 @@ #define CISLANDS_MAX_HARDWARE_POWERLEVELS 2 +#define CISLANDS_UNUSED_GPIO_PIN 0x7F + struct ci_pl { u32 mclk; u32 sclk; -- cgit v1.2.3 From 9feb3dda5ce0a9d2155f20506384d2e359f151ce Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 12:00:25 -0500 Subject: drm/radeon: fix for memory training on bonaire 0x6649 Workaround for memory link training on certain variants of 0x6649. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 377afa504d2b..57a359d34830 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -1806,7 +1806,7 @@ int ci_mc_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data = NULL; const __le32 *new_fw_data = NULL; - u32 running, blackout = 0; + u32 running, blackout = 0, tmp; u32 *io_mc_regs = NULL; const __le32 *new_io_mc_regs = NULL; int i, regs_size, ucode_size; @@ -1866,6 +1866,15 @@ int ci_mc_load_microcode(struct radeon_device *rdev) WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); } } + + tmp = RREG32(MC_SEQ_MISC0); + if ((rdev->pdev->device == 0x6649) && ((tmp & 0xff00) == 0x5600)) { + WREG32(MC_SEQ_IO_DEBUG_INDEX, 5); + WREG32(MC_SEQ_IO_DEBUG_DATA, 0x00000023); + WREG32(MC_SEQ_IO_DEBUG_INDEX, 9); + WREG32(MC_SEQ_IO_DEBUG_DATA, 0x000001f0); + } + /* load the MC ucode */ for (i = 0; i < ucode_size; i++) { if (rdev->new_fw) -- cgit v1.2.3 From 1c52279f578f8d1dc164c0d27f8f00b5aa06f2c1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 12:06:56 -0500 Subject: drm/radeon: switch force state commands for CI Use the preferred SMC commands for forcing state on CI. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 9a3c71c0e66e..893ed68cbaed 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -1282,7 +1282,7 @@ static int ci_dpm_force_state_sclk(struct radeon_device *rdev, u32 n) if (!pi->sclk_dpm_key_disabled) { PPSMC_Result smc_result = - ci_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, n); + ci_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SCLKDPM_SetEnabledMask, 1 << n); if (smc_result != PPSMC_Result_OK) return -EINVAL; } @@ -1296,7 +1296,7 @@ static int ci_dpm_force_state_mclk(struct radeon_device *rdev, u32 n) if (!pi->mclk_dpm_key_disabled) { PPSMC_Result smc_result = - ci_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_MCLKDPM_ForceState, n); + ci_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_MCLKDPM_SetEnabledMask, 1 << n); if (smc_result != PPSMC_Result_OK) return -EINVAL; } @@ -3736,7 +3736,6 @@ int ci_dpm_force_performance_level(struct radeon_device *rdev, enum radeon_dpm_forced_level level) { struct ci_power_info *pi = ci_get_pi(rdev); - PPSMC_Result smc_result; u32 tmp, levels, i; int ret; @@ -3845,21 +3844,9 @@ int ci_dpm_force_performance_level(struct radeon_device *rdev, } } } else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) { - if (!pi->sclk_dpm_key_disabled) { - smc_result = ci_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel); - if (smc_result != PPSMC_Result_OK) - return -EINVAL; - } - if (!pi->mclk_dpm_key_disabled) { - smc_result = ci_send_msg_to_smc(rdev, PPSMC_MSG_MCLKDPM_NoForcedLevel); - if (smc_result != PPSMC_Result_OK) - return -EINVAL; - } - if (!pi->pcie_dpm_key_disabled) { - smc_result = ci_send_msg_to_smc(rdev, PPSMC_MSG_PCIeDPM_UnForceLevel); - if (smc_result != PPSMC_Result_OK) - return -EINVAL; - } + ret = ci_upload_dpm_level_enable_mask(rdev); + if (ret) + return ret; } rdev->pm.dpm.forced_level = level; -- cgit v1.2.3 From 21b8a369046fbccb39f66cf065c43289376e63fa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 12:51:04 -0500 Subject: drm/radeon: fix dram timing for certain hawaii boards Certain memory configurations need a fix. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 893ed68cbaed..4dd8f3575238 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -2071,6 +2071,33 @@ static int ci_force_switch_to_arb_f0(struct radeon_device *rdev) return ni_copy_and_switch_arb_sets(rdev, tmp, MC_CG_ARB_FREQ_F0); } +static void ci_register_patching_mc_arb(struct radeon_device *rdev, + const u32 engine_clock, + const u32 memory_clock, + u32 *dram_timimg2) +{ + bool patch; + u32 tmp, tmp2; + + tmp = RREG32(MC_SEQ_MISC0); + patch = ((tmp & 0x0000f00) == 0x300) ? true : false; + + if (patch && + ((rdev->pdev->device == 0x67B0) || + (rdev->pdev->device == 0x67B1))) { + if ((memory_clock > 100000) && (memory_clock <= 125000)) { + tmp2 = (((0x31 * engine_clock) / 125000) - 1) & 0xff; + *dram_timimg2 &= ~0x00ff0000; + *dram_timimg2 |= tmp2 << 16; + } else if ((memory_clock > 125000) && (memory_clock <= 137500)) { + tmp2 = (((0x36 * engine_clock) / 137500) - 1) & 0xff; + *dram_timimg2 &= ~0x00ff0000; + *dram_timimg2 |= tmp2 << 16; + } + } +} + + static int ci_populate_memory_timing_parameters(struct radeon_device *rdev, u32 sclk, u32 mclk, @@ -2086,6 +2113,8 @@ static int ci_populate_memory_timing_parameters(struct radeon_device *rdev, dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); burst_time = RREG32(MC_ARB_BURST_TIME) & STATE0_MASK; + ci_register_patching_mc_arb(rdev, sclk, mclk, &dram_timing2); + arb_regs->McArbDramTiming = cpu_to_be32(dram_timing); arb_regs->McArbDramTiming2 = cpu_to_be32(dram_timing2); arb_regs->McArbBurstTime = (u8)burst_time; -- cgit v1.2.3 From c0392f8f0971fee63fa736c800e7c32b59773ba7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 12:56:00 -0500 Subject: drm/radeon: improve mclk param calcuations for ci dpm Properly take into account the post divider. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 4dd8f3575238..3705d13218e6 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -2409,10 +2409,10 @@ static int ci_calculate_mclk_params(struct radeon_device *rdev, u32 tmp; u32 reference_clock = rdev->clock.mpll.reference_freq; - if (pi->mem_gddr5) - freq_nom = memory_clock * 4; + if (mpll_param.qdr == 1) + freq_nom = memory_clock * 4 * (1 << mpll_param.post_div); else - freq_nom = memory_clock * 2; + freq_nom = memory_clock * 2 * (1 << mpll_param.post_div); tmp = (freq_nom / reference_clock); tmp = tmp * tmp; -- cgit v1.2.3 From d3052b8ce8a308d2086519fa5f7c4966257ea184 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 13:04:47 -0500 Subject: drm/radeon: fix activity settings for sclk and mclk for CI Only need to be enabled on the first level. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 3705d13218e6..9d04e68e4f09 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -2492,7 +2492,6 @@ static int ci_populate_single_memory_level(struct radeon_device *rdev, &memory_level->MinVddcPhases); memory_level->EnabledForThrottle = 1; - memory_level->EnabledForActivity = 1; memory_level->UpH = 0; memory_level->DownH = 100; memory_level->VoltageDownH = 0; @@ -2825,7 +2824,6 @@ static int ci_populate_single_graphic_level(struct radeon_device *rdev, graphic_level->CcPwrDynRm = 0; graphic_level->CcPwrDynRm1 = 0; - graphic_level->EnabledForActivity = 1; graphic_level->EnabledForThrottle = 1; graphic_level->UpH = 0; graphic_level->DownH = 0; @@ -2878,6 +2876,7 @@ static int ci_populate_all_graphic_levels(struct radeon_device *rdev) pi->smc_state_table.GraphicsLevel[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; } + pi->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; pi->smc_state_table.GraphicsDpmLevelCount = (u8)dpm_table->sclk_table.count; pi->dpm_level_enable_mask.sclk_dpm_enable_mask = @@ -2921,6 +2920,8 @@ static int ci_populate_all_memory_levels(struct radeon_device *rdev) return ret; } + pi->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + pi->smc_state_table.MemoryLevel[0].ActivityLevel = cpu_to_be16(0x1F); pi->smc_state_table.MemoryDpmLevelCount = (u8)dpm_table->mclk_table.count; -- cgit v1.2.3 From 489ba72c1ef9c6ceb1480be1550f235d9591d59a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 13:06:57 -0500 Subject: drm/radeon: fix sclk DS enablement Only enable it for levels 0 and 1. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 9d04e68e4f09..324e31d4b27d 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -2872,6 +2872,8 @@ static int ci_populate_all_graphic_levels(struct radeon_device *rdev) &pi->smc_state_table.GraphicsLevel[i]); if (ret) return ret; + if (i > 1) + pi->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; if (i == (dpm_table->sclk_table.count - 1)) pi->smc_state_table.GraphicsLevel[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; -- cgit v1.2.3 From 127e056e2a82406fd3455a9da20d02f192ae8a05 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 13:11:39 -0500 Subject: drm/radeon: fix mclk vddc configuration for cards for hawaii Need to use vddc0 for vdcc1 for certain hawaii configurations. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 324e31d4b27d..a33e23880cb6 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -2924,6 +2924,14 @@ static int ci_populate_all_memory_levels(struct radeon_device *rdev) pi->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + if ((dpm_table->mclk_table.count >= 2) && + ((rdev->pdev->device == 0x67B0) || (rdev->pdev->device == 0x67B1))) { + pi->smc_state_table.MemoryLevel[1].MinVddc = + pi->smc_state_table.MemoryLevel[0].MinVddc; + pi->smc_state_table.MemoryLevel[1].MinVddcPhases = + pi->smc_state_table.MemoryLevel[0].MinVddcPhases; + } + pi->smc_state_table.MemoryLevel[0].ActivityLevel = cpu_to_be16(0x1F); pi->smc_state_table.MemoryDpmLevelCount = (u8)dpm_table->mclk_table.count; -- cgit v1.2.3 From 36654dd4b9b9dd65143095ca48f5b9c846b13e0b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 13:19:17 -0500 Subject: drm/radeon: workaround a hw bug in bonaire pcie dpm Some boards get stuck in pcie x1 otherwise. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index a33e23880cb6..aad64770ee55 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -2988,9 +2988,14 @@ static int ci_setup_default_pcie_tables(struct radeon_device *rdev) &pi->dpm_table.pcie_speed_table, SMU7_MAX_LEVELS_LINK); - ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 0, - pi->pcie_gen_powersaving.min, - pi->pcie_lane_powersaving.min); + if (rdev->family == CHIP_BONAIRE) + ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 0, + pi->pcie_gen_powersaving.min, + pi->pcie_lane_powersaving.max); + else + ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 0, + pi->pcie_gen_powersaving.min, + pi->pcie_lane_powersaving.min); ci_setup_pcie_table_entry(&pi->dpm_table.pcie_speed_table, 1, pi->pcie_gen_performance.min, pi->pcie_lane_performance.min); -- cgit v1.2.3 From b6b41cf3b64f88472f08276a90248a6fa36ee8c7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 13:24:54 -0500 Subject: drm/radeon: fix default dpm state setup Only enable the first levels for mclk and sclk. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index aad64770ee55..dbc6d2aa6d22 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -3062,19 +3062,21 @@ static int ci_setup_default_dpm_tables(struct radeon_device *rdev) allowed_sclk_vddc_table->entries[i].clk)) { pi->dpm_table.sclk_table.dpm_levels[pi->dpm_table.sclk_table.count].value = allowed_sclk_vddc_table->entries[i].clk; - pi->dpm_table.sclk_table.dpm_levels[pi->dpm_table.sclk_table.count].enabled = true; + pi->dpm_table.sclk_table.dpm_levels[pi->dpm_table.sclk_table.count].enabled = + (i == 0) ? true : false; pi->dpm_table.sclk_table.count++; } } pi->dpm_table.mclk_table.count = 0; for (i = 0; i < allowed_mclk_table->count; i++) { - if ((i==0) || + if ((i == 0) || (pi->dpm_table.mclk_table.dpm_levels[pi->dpm_table.mclk_table.count-1].value != allowed_mclk_table->entries[i].clk)) { pi->dpm_table.mclk_table.dpm_levels[pi->dpm_table.mclk_table.count].value = allowed_mclk_table->entries[i].clk; - pi->dpm_table.mclk_table.dpm_levels[pi->dpm_table.mclk_table.count].enabled = true; + pi->dpm_table.mclk_table.dpm_levels[pi->dpm_table.mclk_table.count].enabled = + (i == 0) ? true : false; pi->dpm_table.mclk_table.count++; } } -- cgit v1.2.3 From 4e21518c3d635ad8cad7c07198bb3f592b25395c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 13:34:28 -0500 Subject: drm/radeon: set bootup pcie level to max for ci dpm Avoids problems when re-loading the driver. Does not affect power saving when dpm is enabled. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index dbc6d2aa6d22..befa84c4a6ae 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -3242,7 +3242,7 @@ static int ci_init_smc_table(struct radeon_device *rdev) table->VddcVddciDelta = 4000; table->PhaseResponseTime = 0; table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; + table->PCIeBootLinkLevel = pi->dpm_table.pcie_speed_table.count - 1; table->PCIeGenInterval = 1; if (pi->voltage_control == CISLANDS_VOLTAGE_CONTROL_BY_SVID2) table->SVI2Enable = 1; -- cgit v1.2.3 From 90b2fee35cb9c143f049091ff7ea87500c5c7c46 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 13:58:11 -0500 Subject: drm/radeon: fix dpm mc init for certain hawaii boards Needs special overrides for certain vram configurations. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 94 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index befa84c4a6ae..d9071aefc5f5 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -4099,6 +4099,96 @@ static int ci_copy_vbios_mc_reg_table(const struct atom_mc_reg_table *table, return 0; } +static int ci_register_patching_mc_seq(struct radeon_device *rdev, + struct ci_mc_reg_table *table) +{ + u8 i, k; + u32 tmp; + bool patch; + + tmp = RREG32(MC_SEQ_MISC0); + patch = ((tmp & 0x0000f00) == 0x300) ? true : false; + + if (patch && + ((rdev->pdev->device == 0x67B0) || + (rdev->pdev->device == 0x67B1))) { + for (i = 0; i < table->last; i++) { + if (table->last >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + switch(table->mc_reg_address[i].s1 >> 2) { + case MC_SEQ_MISC1: + for (k = 0; k < table->num_entries; k++) { + if ((table->mc_reg_table_entry[k].mclk_max == 125000) || + (table->mc_reg_table_entry[k].mclk_max == 137500)) + table->mc_reg_table_entry[k].mc_data[i] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFFFFF8) | + 0x00000007; + } + break; + case MC_SEQ_WR_CTL_D0: + for (k = 0; k < table->num_entries; k++) { + if ((table->mc_reg_table_entry[k].mclk_max == 125000) || + (table->mc_reg_table_entry[k].mclk_max == 137500)) + table->mc_reg_table_entry[k].mc_data[i] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFF0F00) | + 0x0000D0DD; + } + break; + case MC_SEQ_WR_CTL_D1: + for (k = 0; k < table->num_entries; k++) { + if ((table->mc_reg_table_entry[k].mclk_max == 125000) || + (table->mc_reg_table_entry[k].mclk_max == 137500)) + table->mc_reg_table_entry[k].mc_data[i] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFF0F00) | + 0x0000D0DD; + } + break; + case MC_SEQ_WR_CTL_2: + for (k = 0; k < table->num_entries; k++) { + if ((table->mc_reg_table_entry[k].mclk_max == 125000) || + (table->mc_reg_table_entry[k].mclk_max == 137500)) + table->mc_reg_table_entry[k].mc_data[i] = 0; + } + break; + case MC_SEQ_CAS_TIMING: + for (k = 0; k < table->num_entries; k++) { + if (table->mc_reg_table_entry[k].mclk_max == 125000) + table->mc_reg_table_entry[k].mc_data[i] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xFFE0FE0F) | + 0x000C0140; + else if (table->mc_reg_table_entry[k].mclk_max == 137500) + table->mc_reg_table_entry[k].mc_data[i] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xFFE0FE0F) | + 0x000C0150; + } + break; + case MC_SEQ_MISC_TIMING: + for (k = 0; k < table->num_entries; k++) { + if (table->mc_reg_table_entry[k].mclk_max == 125000) + table->mc_reg_table_entry[k].mc_data[i] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFFFFE0) | + 0x00000030; + else if (table->mc_reg_table_entry[k].mclk_max == 137500) + table->mc_reg_table_entry[k].mc_data[i] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xFFFFFFE0) | + 0x00000035; + } + break; + default: + break; + } + } + + WREG32(MC_SEQ_IO_DEBUG_INDEX, 3); + tmp = RREG32(MC_SEQ_IO_DEBUG_DATA); + tmp = (tmp & 0xFFF8FFFF) | (1 << 16); + WREG32(MC_SEQ_IO_DEBUG_INDEX, 3); + WREG32(MC_SEQ_IO_DEBUG_DATA, tmp); + } + + return 0; +} + static int ci_initialize_mc_reg_table(struct radeon_device *rdev) { struct ci_power_info *pi = ci_get_pi(rdev); @@ -4142,6 +4232,10 @@ static int ci_initialize_mc_reg_table(struct radeon_device *rdev) ci_set_s0_mc_reg_index(ci_table); + ret = ci_register_patching_mc_seq(rdev, ci_table); + if (ret) + goto init_mc_done; + ret = ci_set_mc_special_registers(rdev, ci_table); if (ret) goto init_mc_done; -- cgit v1.2.3 From 542b379b55513ac1c564de7d8dac1cee8b3ba7e8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 18:31:39 -0500 Subject: drm/radeon: powertune fixes for hawaii - bapm is not available on hawaii - update pt defaults Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index d9071aefc5f5..4d880906a390 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -46,15 +46,15 @@ static const struct ci_pt_defaults defaults_hawaii_xt = { 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000, - { 0x84, 0x0, 0x0, 0x7F, 0x0, 0x0, 0x5A, 0x60, 0x51, 0x8E, 0x79, 0x6B, 0x5F, 0x90, 0x79 }, - { 0x1EA, 0x1EA, 0x1EA, 0x224, 0x224, 0x224, 0x24F, 0x24F, 0x24F, 0x28E, 0x28E, 0x28E, 0x2BC, 0x2BC, 0x2BC } + { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, + { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } }; static const struct ci_pt_defaults defaults_hawaii_pro = { 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062, - { 0x93, 0x0, 0x0, 0x97, 0x0, 0x0, 0x6B, 0x60, 0x51, 0x95, 0x79, 0x6B, 0x5F, 0x90, 0x79 }, - { 0x1EA, 0x1EA, 0x1EA, 0x224, 0x224, 0x224, 0x24F, 0x24F, 0x24F, 0x28E, 0x28E, 0x28E, 0x2BC, 0x2BC, 0x2BC } + { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, + { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } }; static const struct ci_pt_defaults defaults_bonaire_xt = @@ -249,7 +249,10 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev) if (pi->caps_power_containment) { pi->caps_cac = true; - pi->enable_bapm_feature = true; + if (rdev->family == CHIP_HAWAII) + pi->enable_bapm_feature = false; + else + pi->enable_bapm_feature = true; pi->enable_tdc_limit_feature = true; pi->enable_pkg_pwr_tracking_feature = true; } @@ -700,13 +703,11 @@ static int ci_power_control_set_level(struct radeon_device *rdev) int ret = 0; bool adjust_polarity = false; /* ??? */ - if (pi->caps_power_containment && - (pi->power_containment_features & POWERCONTAINMENT_FEATURE_BAPM)) { + if (pi->caps_power_containment) { adjust_percent = adjust_polarity ? rdev->pm.dpm.tdp_adjustment : (-1 * rdev->pm.dpm.tdp_adjustment); target_tdp = ((100 + adjust_percent) * (s32)cac_tdp_table->configurable_tdp) / 100; - target_tdp *= 256; ret = ci_set_overdrive_target_tdp(rdev, (u32)target_tdp); } -- cgit v1.2.3 From b94b95e7e3710a6137f8bc1311938cab3b067a0e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Nov 2014 14:12:14 -0500 Subject: drm/radeon: set power control in ci dpm enable Necessary for poper operation. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 4d880906a390..9dbc52f3c4d1 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -4833,6 +4833,12 @@ int ci_dpm_enable(struct radeon_device *rdev) return ret; } + ret = ci_power_control_set_level(rdev); + if (ret) { + DRM_ERROR("ci_power_control_set_level failed\n"); + return ret; + } + ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); ci_update_current_ps(rdev, boot_ps); @@ -4963,11 +4969,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev) return 0; } -int ci_dpm_power_control_set_level(struct radeon_device *rdev) -{ - return ci_power_control_set_level(rdev); -} - void ci_dpm_reset_asic(struct radeon_device *rdev) { ci_set_boot_state(rdev); -- cgit v1.2.3 From c81b99423bd9d3fc35ac8752ca5fb4c50eab063c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 10 Nov 2014 16:51:08 +1000 Subject: drm/radeon/si/ci: make u8 static arrays constant These two arrays don't change, just make them constant, reduces data segment by a few bytes. Signed-off-by: Dave Airlie Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_smc.c | 2 +- drivers/gpu/drm/radeon/si_smc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_smc.c b/drivers/gpu/drm/radeon/ci_smc.c index b630edc2fd0c..e78bcad7a43e 100644 --- a/drivers/gpu/drm/radeon/ci_smc.c +++ b/drivers/gpu/drm/radeon/ci_smc.c @@ -129,7 +129,7 @@ void ci_reset_smc(struct radeon_device *rdev) int ci_program_jump_on_start(struct radeon_device *rdev) { - static u8 data[] = { 0xE0, 0x00, 0x80, 0x40 }; + static const u8 data[] = { 0xE0, 0x00, 0x80, 0x40 }; return ci_copy_bytes_to_smc(rdev, 0x0, data, 4, sizeof(data)+1); } diff --git a/drivers/gpu/drm/radeon/si_smc.c b/drivers/gpu/drm/radeon/si_smc.c index 73dbc79c959d..e5bb92f16775 100644 --- a/drivers/gpu/drm/radeon/si_smc.c +++ b/drivers/gpu/drm/radeon/si_smc.c @@ -135,7 +135,7 @@ void si_reset_smc(struct radeon_device *rdev) int si_program_jump_on_start(struct radeon_device *rdev) { - static u8 data[] = { 0x0E, 0x00, 0x40, 0x40 }; + static const u8 data[] = { 0x0E, 0x00, 0x40, 0x40 }; return si_copy_bytes_to_smc(rdev, 0x0, data, 4, sizeof(data)+1); } -- cgit v1.2.3