Commit 560154e9 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: refactor atombios power state fetching

The function was getting too large.  Rework it to share
more state better handle new power table formats.
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent e719ebd9
...@@ -1763,39 +1763,87 @@ static const char *pp_lib_thermal_controller_names[] = { ...@@ -1763,39 +1763,87 @@ static const char *pp_lib_thermal_controller_names[] = {
"RV6xx", "RV6xx",
"RV770", "RV770",
"adt7473", "adt7473",
"NONE",
"External GPIO", "External GPIO",
"Evergreen", "Evergreen",
"adt7473 with internal", "adt7473 with internal",
}; };
union power_info { union power_info {
struct _ATOM_POWERPLAY_INFO info; struct _ATOM_POWERPLAY_INFO info;
struct _ATOM_POWERPLAY_INFO_V2 info_2; struct _ATOM_POWERPLAY_INFO_V2 info_2;
struct _ATOM_POWERPLAY_INFO_V3 info_3; struct _ATOM_POWERPLAY_INFO_V3 info_3;
struct _ATOM_PPLIB_POWERPLAYTABLE info_4; struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
}; };
void radeon_atombios_get_power_modes(struct radeon_device *rdev) union pplib_clock_info {
struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
};
union pplib_power_state {
struct _ATOM_PPLIB_STATE v1;
struct _ATOM_PPLIB_STATE_V2 v2;
};
static void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev,
int state_index,
u32 misc, u32 misc2)
{
rdev->pm.power_state[state_index].misc = misc;
rdev->pm.power_state[state_index].misc2 = misc2;
/* order matters! */
if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_POWERSAVE;
if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BATTERY;
if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BATTERY;
if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BALANCED;
if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_PERFORMANCE;
rdev->pm.power_state[state_index].flags &=
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
}
if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BALANCED;
if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_DEFAULT;
rdev->pm.default_power_state_index = state_index;
rdev->pm.power_state[state_index].default_clock_mode =
&rdev->pm.power_state[state_index].clock_info[0];
} else if (state_index == 0) {
rdev->pm.power_state[state_index].clock_info[0].flags |=
RADEON_PM_MODE_NO_DISPLAY;
}
}
static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
{ {
struct radeon_mode_info *mode_info = &rdev->mode_info; struct radeon_mode_info *mode_info = &rdev->mode_info;
u32 misc, misc2 = 0;
int num_modes = 0, i;
int state_index = 0;
struct radeon_i2c_bus_rec i2c_bus;
union power_info *power_info;
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
u16 data_offset; u16 data_offset;
u8 frev, crev; u8 frev, crev;
u32 misc, misc2 = 0, sclk, mclk;
union power_info *power_info;
struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
struct _ATOM_PPLIB_STATE *power_state;
int num_modes = 0, i, j;
int state_index = 0, mode_index = 0;
struct radeon_i2c_bus_rec i2c_bus;
rdev->pm.default_power_state_index = -1; if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset))
if (atom_parse_data_header(mode_info->atom_context, index, NULL, return state_index;
&frev, &crev, &data_offset)) {
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
if (frev < 4) {
/* add the i2c bus for thermal/fan chip */ /* add the i2c bus for thermal/fan chip */
if (power_info->info.ucOverdriveThermalController > 0) { if (power_info->info.ucOverdriveThermalController > 0) {
DRM_INFO("Possible %s thermal controller at 0x%02x\n", DRM_INFO("Possible %s thermal controller at 0x%02x\n",
...@@ -1852,38 +1900,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -1852,38 +1900,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
} }
rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
rdev->pm.power_state[state_index].misc = misc; radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0);
/* order matters! */
if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_POWERSAVE;
if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BATTERY;
if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BATTERY;
if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BALANCED;
if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_PERFORMANCE;
rdev->pm.power_state[state_index].flags &=
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
}
if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_DEFAULT;
rdev->pm.default_power_state_index = state_index;
rdev->pm.power_state[state_index].default_clock_mode =
&rdev->pm.power_state[state_index].clock_info[0];
rdev->pm.power_state[state_index].flags &=
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
} else if (state_index == 0) {
rdev->pm.power_state[state_index].clock_info[0].flags |=
RADEON_PM_MODE_NO_DISPLAY;
}
state_index++; state_index++;
break; break;
case 2: case 2:
...@@ -1920,45 +1937,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -1920,45 +1937,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
} }
rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
rdev->pm.power_state[state_index].misc = misc; radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
rdev->pm.power_state[state_index].misc2 = misc2;
/* order matters! */
if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_POWERSAVE;
if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BATTERY;
if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BATTERY;
if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BALANCED;
if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_PERFORMANCE;
rdev->pm.power_state[state_index].flags &=
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
}
if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BALANCED;
if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT)
rdev->pm.power_state[state_index].flags &=
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_DEFAULT;
rdev->pm.default_power_state_index = state_index;
rdev->pm.power_state[state_index].default_clock_mode =
&rdev->pm.power_state[state_index].clock_info[0];
rdev->pm.power_state[state_index].flags &=
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
} else if (state_index == 0) {
rdev->pm.power_state[state_index].clock_info[0].flags |=
RADEON_PM_MODE_NO_DISPLAY;
}
state_index++; state_index++;
break; break;
case 3: case 3:
...@@ -2001,40 +1980,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -2001,40 +1980,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
} }
} }
rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
rdev->pm.power_state[state_index].misc = misc; radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2);
rdev->pm.power_state[state_index].misc2 = misc2;
/* order matters! */
if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_POWERSAVE;
if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BATTERY;
if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BATTERY;
if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BALANCED;
if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_PERFORMANCE;
rdev->pm.power_state[state_index].flags &=
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
}
if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_BALANCED;
if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
rdev->pm.power_state[state_index].type =
POWER_STATE_TYPE_DEFAULT;
rdev->pm.default_power_state_index = state_index;
rdev->pm.power_state[state_index].default_clock_mode =
&rdev->pm.power_state[state_index].clock_info[0];
} else if (state_index == 0) {
rdev->pm.power_state[state_index].clock_info[0].flags |=
RADEON_PM_MODE_NO_DISPLAY;
}
state_index++; state_index++;
break; break;
} }
...@@ -2051,20 +1997,13 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -2051,20 +1997,13 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
rdev->pm.power_state[state_index].misc = 0; rdev->pm.power_state[state_index].misc = 0;
rdev->pm.power_state[state_index].misc2 = 0; rdev->pm.power_state[state_index].misc2 = 0;
} }
} else { return state_index;
int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo); }
uint8_t fw_frev, fw_crev;
uint16_t fw_data_offset, vddc = 0;
union firmware_info *firmware_info;
ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL, static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev,
&fw_frev, &fw_crev, &fw_data_offset)) { ATOM_PPLIB_THERMALCONTROLLER *controller)
firmware_info = {
(union firmware_info *)(mode_info->atom_context->bios + struct radeon_i2c_bus_rec i2c_bus;
fw_data_offset);
vddc = firmware_info->info_14.usBootUpVDDCVoltage;
}
/* add the i2c bus for thermal/fan chip */ /* add the i2c bus for thermal/fan chip */
if (controller->ucType > 0) { if (controller->ucType > 0) {
...@@ -2103,93 +2042,39 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -2103,93 +2042,39 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
strlcpy(info.type, name, sizeof(info.type)); strlcpy(info.type, name, sizeof(info.type));
i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
} }
} }
} }
/* first mode is usually default, followed by low to high */ }
for (i = 0; i < power_info->info_4.ucNumStates; i++) {
mode_index = 0; static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev)
power_state = (struct _ATOM_PPLIB_STATE *) {
(mode_info->atom_context->bios + struct radeon_mode_info *mode_info = &rdev->mode_info;
data_offset + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
le16_to_cpu(power_info->info_4.usStateArrayOffset) + u8 frev, crev;
i * power_info->info_4.ucStateEntrySize); u16 data_offset;
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) union firmware_info *firmware_info;
(mode_info->atom_context->bios + u16 vddc = 0;
data_offset +
le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) + if (atom_parse_data_header(mode_info->atom_context, index, NULL,
(power_state->ucNonClockStateIndex * &frev, &crev, &data_offset)) {
power_info->info_4.ucNonClockSize)); firmware_info =
for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) { (union firmware_info *)(mode_info->atom_context->bios +
if (rdev->flags & RADEON_IS_IGP) { data_offset);
struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info = vddc = firmware_info->info_14.usBootUpVDDCVoltage;
(struct _ATOM_PPLIB_RS780_CLOCK_INFO *)
(mode_info->atom_context->bios +
data_offset +
le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
(power_state->ucClockStateIndices[j] *
power_info->info_4.ucClockInfoSize));
sclk = le16_to_cpu(clock_info->usLowEngineClockLow);
sclk |= clock_info->ucLowEngineClockHigh << 16;
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
/* skip invalid modes */
if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
continue;
/* voltage works differently on IGPs */
mode_index++;
} else if (ASIC_IS_DCE4(rdev)) {
struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info =
(struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *)
(mode_info->atom_context->bios +
data_offset +
le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
(power_state->ucClockStateIndices[j] *
power_info->info_4.ucClockInfoSize));
sclk = le16_to_cpu(clock_info->usEngineClockLow);
sclk |= clock_info->ucEngineClockHigh << 16;
mclk = le16_to_cpu(clock_info->usMemoryClockLow);
mclk |= clock_info->ucMemoryClockHigh << 16;
rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
/* skip invalid modes */
if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
(rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
continue;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
VOLTAGE_SW;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
clock_info->usVDDC;
/* XXX usVDDCI */
mode_index++;
} else {
struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info =
(struct _ATOM_PPLIB_R600_CLOCK_INFO *)
(mode_info->atom_context->bios +
data_offset +
le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
(power_state->ucClockStateIndices[j] *
power_info->info_4.ucClockInfoSize));
sclk = le16_to_cpu(clock_info->usEngineClockLow);
sclk |= clock_info->ucEngineClockHigh << 16;
mclk = le16_to_cpu(clock_info->usMemoryClockLow);
mclk |= clock_info->ucMemoryClockHigh << 16;
rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
/* skip invalid modes */
if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
(rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
continue;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
VOLTAGE_SW;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
clock_info->usVDDC;
mode_index++;
}
} }
rdev->pm.power_state[state_index].num_clock_modes = mode_index;
if (mode_index) { return vddc;
misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); }
misc2 = le16_to_cpu(non_clock_info->usClassification);
static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev,
int state_index, int mode_index,
struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info)
{
int j;
u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
u32 misc2 = le16_to_cpu(non_clock_info->usClassification);
u16 vddc = radeon_atombios_get_default_vddc(rdev);
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;
rdev->pm.power_state[state_index].pcie_lanes = rdev->pm.power_state[state_index].pcie_lanes =
...@@ -2235,6 +2120,103 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -2235,6 +2120,103 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
vddc; vddc;
} }
} }
}
static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev,
int state_index, int mode_index,
union pplib_clock_info *clock_info)
{
u32 sclk, mclk;
if (rdev->flags & RADEON_IS_IGP) {
sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow);
sclk |= clock_info->rs780.ucLowEngineClockHigh << 16;
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
} else if (ASIC_IS_DCE4(rdev)) {
sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
VOLTAGE_SW;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
clock_info->evergreen.usVDDC;
} else {
sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
sclk |= clock_info->r600.ucEngineClockHigh << 16;
mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow);
mclk |= clock_info->r600.ucMemoryClockHigh << 16;
rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
VOLTAGE_SW;
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
clock_info->r600.usVDDC;
}
if (rdev->flags & RADEON_IS_IGP) {
/* skip invalid modes */
if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
return false;
} else {
/* skip invalid modes */
if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
(rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
return false;
}
return true;
}
static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
{
struct radeon_mode_info *mode_info = &rdev->mode_info;
struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
union pplib_power_state *power_state;
int i, j;
int state_index = 0, mode_index = 0;
union pplib_clock_info *clock_info;
bool valid;
union power_info *power_info;
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
u16 data_offset;
u8 frev, crev;
if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset))
return state_index;
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
/* first mode is usually default, followed by low to high */
for (i = 0; i < power_info->pplib.ucNumStates; i++) {
mode_index = 0;
power_state = (union pplib_power_state *)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usStateArrayOffset) +
i * power_info->pplib.ucStateEntrySize);
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
(power_state->v1.ucNonClockStateIndex *
power_info->pplib.ucNonClockSize));
for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
clock_info = (union pplib_clock_info *)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
(power_state->v1.ucClockStateIndices[j] *
power_info->pplib.ucClockInfoSize));
valid = radeon_atombios_parse_pplib_clock_info(rdev,
state_index, mode_index,
clock_info);
if (valid)
mode_index++;
}
rdev->pm.power_state[state_index].num_clock_modes = mode_index;
if (mode_index) {
radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index,
non_clock_info);
state_index++; state_index++;
} }
} }
...@@ -2252,6 +2234,33 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -2252,6 +2234,33 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
rdev->pm.power_state[0].default_clock_mode = rdev->pm.power_state[0].default_clock_mode =
&rdev->pm.power_state[0].clock_info[0]; &rdev->pm.power_state[0].clock_info[0];
} }
return state_index;
}
void radeon_atombios_get_power_modes(struct radeon_device *rdev)
{
struct radeon_mode_info *mode_info = &rdev->mode_info;
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
u16 data_offset;
u8 frev, crev;
int state_index = 0;
rdev->pm.default_power_state_index = -1;
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
switch (frev) {
case 1:
case 2:
case 3:
state_index = radeon_atombios_parse_power_table_1_3(rdev);
break;
case 4:
case 5:
state_index = radeon_atombios_parse_power_table_4_5(rdev);
break;
default:
break;
} }
} else { } else {
/* add the default mode */ /* add the default mode */
......
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