Merge branch 'drm-next-3.19' of git://people.freedesktop.org/~agd5f/linux into drm-next

Radeon patches for 3.19.  Christian has a number of GPUVM improvements
slated as well, but I'd like to wait until he gets back to work next week
to pull those in. Highlights of this pull:
- ttm performance improvements
- CI dpm fixes

* 'drm-next-3.19' of git://people.freedesktop.org/~agd5f/linux: (26 commits)
  drm/radeon/si/ci: make u8 static arrays constant
  drm/radeon: set power control in ci dpm enable
  drm/radeon: powertune fixes for hawaii
  drm/radeon: fix dpm mc init for certain hawaii boards
  drm/radeon: set bootup pcie level to max for ci dpm
  drm/radeon: fix default dpm state setup
  drm/radeon: workaround a hw bug in bonaire pcie dpm
  drm/radeon: fix mclk vddc configuration for cards for hawaii
  drm/radeon: fix sclk DS enablement
  drm/radeon: fix activity settings for sclk and mclk for CI
  drm/radeon: improve mclk param calcuations for ci dpm
  drm/radeon: fix dram timing for certain hawaii boards
  drm/radeon: switch force state commands for CI
  drm/radeon: fix for memory training on bonaire 0x6649
  drm/radeon/ci: handle gpio controlled dpm features properly
  drm/radeon: store the gpio shift as well
  drm/radeon: export radeon_atombios_lookup_gpio
  drm/radeon: fix typo in CI dpm disable
  drm/radeon: rework CI dpm thermal setup
  drm/radeon: rework SI dpm thermal setup
  ...
This commit is contained in:
Dave Airlie 2014-11-13 09:06:41 +10:00
commit 7fd36c0bae
13 changed files with 429 additions and 106 deletions

View File

@ -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);
}
@ -814,7 +815,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 +851,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)
@ -1253,7 +1283,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;
}
@ -1267,7 +1297,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;
}
@ -2042,6 +2072,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,
@ -2057,6 +2114,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;
@ -2351,10 +2410,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;
@ -2434,7 +2493,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;
@ -2767,7 +2825,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;
@ -2816,10 +2873,13 @@ 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;
}
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 =
@ -2863,6 +2923,16 @@ static int ci_populate_all_memory_levels(struct radeon_device *rdev)
return ret;
}
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;
@ -2919,9 +2989,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);
@ -2988,19 +3063,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++;
}
}
@ -3166,7 +3243,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;
@ -3707,7 +3784,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;
@ -3816,21 +3892,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;
@ -4036,6 +4100,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);
@ -4079,6 +4233,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;
@ -4675,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);
@ -4682,29 +4846,30 @@ int ci_dpm_enable(struct radeon_device *rdev)
return 0;
}
static int ci_set_temperature_range(struct radeon_device *rdev)
{
int ret;
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;
return ret;
}
int ci_dpm_late_enable(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);
if (result != PPSMC_Result_OK)
DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
#endif
}
ret = ci_set_temperature_range(rdev);
if (ret)
return ret;
ci_dpm_powergate_uvd(rdev, true);
@ -4729,7 +4894,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);
@ -4804,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);
@ -5068,6 +5228,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;
@ -5201,6 +5363,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;

View File

@ -33,6 +33,8 @@
#define CISLANDS_MAX_HARDWARE_POWERLEVELS 2
#define CISLANDS_UNUSED_GPIO_PIN 0x7F
struct ci_pl {
u32 mclk;
u32 sclk;

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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;
@ -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;

View File

@ -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;
@ -221,6 +221,7 @@ static struct radeon_gpio_rec radeon_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;
@ -801,7 +802,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 +2129,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 +2165,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 +2201,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 =
@ -2248,6 +2249,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 &

View File

@ -462,6 +462,7 @@ struct radeon_gpio_rec {
u8 id;
u32 reg;
u32 mask;
u32 shift;
};
struct radeon_hpd {
@ -748,6 +749,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,

View File

@ -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
@ -157,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;
}
@ -743,8 +763,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 +781,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);

View File

@ -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:

View File

@ -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;
}
static int si_set_temperature_range(struct radeon_device *rdev)
{
int ret;
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;
return ret;
}
int si_dpm_late_enable(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_set_temperature_range(rdev);
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);
if (result != PPSMC_Result_OK)
DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
}
return 0;
return ret;
}
void si_dpm_disable(struct radeon_device *rdev)

View File

@ -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);
}

View File

@ -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)) {