Commit 2feea49a authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: properly program vddci on evergreen+

Change vddci as well as vddc when changing power modes
on evergreen/ni.  Also, properly set vddci on boot up
for ni cards.  The vbios only sets the limited clocks
and voltages on boot until the mc ucode is loaded.  This
should fix stability problems on some btc cards.
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 8a83ec5e
...@@ -120,11 +120,16 @@ void evergreen_pm_misc(struct radeon_device *rdev) ...@@ -120,11 +120,16 @@ void evergreen_pm_misc(struct radeon_device *rdev)
struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { if (voltage->type == VOLTAGE_SW) {
if (voltage->voltage != rdev->pm.current_vddc) { if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) {
radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
rdev->pm.current_vddc = voltage->voltage; rdev->pm.current_vddc = voltage->voltage;
DRM_DEBUG("Setting: v: %d\n", voltage->voltage); DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
}
if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) {
radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI);
rdev->pm.current_vddci = voltage->vddci;
DRM_DEBUG("Setting: vddci: %d\n", voltage->vddci);
} }
} }
} }
......
...@@ -767,7 +767,9 @@ struct radeon_voltage { ...@@ -767,7 +767,9 @@ struct radeon_voltage {
u8 vddci_id; /* index into vddci voltage table */ u8 vddci_id; /* index into vddci voltage table */
bool vddci_enabled; bool vddci_enabled;
/* r6xx+ sw */ /* r6xx+ sw */
u32 voltage; u16 voltage;
/* evergreen+ vddci */
u16 vddci;
}; };
/* clock mode flags */ /* clock mode flags */
...@@ -835,10 +837,12 @@ struct radeon_pm { ...@@ -835,10 +837,12 @@ struct radeon_pm {
int default_power_state_index; int default_power_state_index;
u32 current_sclk; u32 current_sclk;
u32 current_mclk; u32 current_mclk;
u32 current_vddc; u16 current_vddc;
u16 current_vddci;
u32 default_sclk; u32 default_sclk;
u32 default_mclk; u32 default_mclk;
u32 default_vddc; u16 default_vddc;
u16 default_vddci;
struct radeon_i2c_chan *i2c_bus; struct radeon_i2c_chan *i2c_bus;
/* selected pm method */ /* selected pm method */
enum radeon_pm_method pm_method; enum radeon_pm_method pm_method;
......
...@@ -2176,24 +2176,27 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r ...@@ -2176,24 +2176,27 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r
} }
} }
static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev) static void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
u16 *vddc, u16 *vddci)
{ {
struct radeon_mode_info *mode_info = &rdev->mode_info; struct radeon_mode_info *mode_info = &rdev->mode_info;
int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
u8 frev, crev; u8 frev, crev;
u16 data_offset; u16 data_offset;
union firmware_info *firmware_info; union firmware_info *firmware_info;
u16 vddc = 0;
*vddc = 0;
*vddci = 0;
if (atom_parse_data_header(mode_info->atom_context, index, NULL, if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) { &frev, &crev, &data_offset)) {
firmware_info = firmware_info =
(union firmware_info *)(mode_info->atom_context->bios + (union firmware_info *)(mode_info->atom_context->bios +
data_offset); data_offset);
vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
if ((frev == 2) && (crev >= 2))
*vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage);
} }
return vddc;
} }
static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev, static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev,
...@@ -2203,7 +2206,9 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde ...@@ -2203,7 +2206,9 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde
int j; int j;
u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
u32 misc2 = le16_to_cpu(non_clock_info->usClassification); u32 misc2 = le16_to_cpu(non_clock_info->usClassification);
u16 vddc = radeon_atombios_get_default_vddc(rdev); u16 vddc, vddci;
radeon_atombios_get_default_voltages(rdev, &vddc, &vddci);
rdev->pm.power_state[state_index].misc = misc; rdev->pm.power_state[state_index].misc = misc;
rdev->pm.power_state[state_index].misc2 = misc2; rdev->pm.power_state[state_index].misc2 = misc2;
...@@ -2244,6 +2249,7 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde ...@@ -2244,6 +2249,7 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde
rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage;
rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci;
} else { } else {
/* patch the table values with the default slck/mclk from firmware info */ /* patch the table values with the default slck/mclk from firmware info */
for (j = 0; j < mode_index; j++) { for (j = 0; j < mode_index; j++) {
...@@ -2286,6 +2292,8 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, ...@@ -2286,6 +2292,8 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev,
VOLTAGE_SW; VOLTAGE_SW;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
le16_to_cpu(clock_info->evergreen.usVDDC); le16_to_cpu(clock_info->evergreen.usVDDC);
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
le16_to_cpu(clock_info->evergreen.usVDDCI);
} else { } else {
sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
sclk |= clock_info->r600.ucEngineClockHigh << 16; sclk |= clock_info->r600.ucEngineClockHigh << 16;
......
...@@ -538,6 +538,9 @@ void radeon_pm_resume(struct radeon_device *rdev) ...@@ -538,6 +538,9 @@ void radeon_pm_resume(struct radeon_device *rdev)
if (rdev->pm.default_vddc) if (rdev->pm.default_vddc)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
SET_VOLTAGE_TYPE_ASIC_VDDC); SET_VOLTAGE_TYPE_ASIC_VDDC);
if (rdev->pm.default_vddci)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
SET_VOLTAGE_TYPE_ASIC_VDDCI);
if (rdev->pm.default_sclk) if (rdev->pm.default_sclk)
radeon_set_engine_clock(rdev, rdev->pm.default_sclk); radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
if (rdev->pm.default_mclk) if (rdev->pm.default_mclk)
...@@ -550,6 +553,7 @@ void radeon_pm_resume(struct radeon_device *rdev) ...@@ -550,6 +553,7 @@ void radeon_pm_resume(struct radeon_device *rdev)
rdev->pm.current_sclk = rdev->pm.default_sclk; rdev->pm.current_sclk = rdev->pm.default_sclk;
rdev->pm.current_mclk = rdev->pm.default_mclk; rdev->pm.current_mclk = rdev->pm.default_mclk;
rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
if (rdev->pm.pm_method == PM_METHOD_DYNPM if (rdev->pm.pm_method == PM_METHOD_DYNPM
&& rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment