23,8 → 23,8 |
* Authors: Dave Airlie |
* Alex Deucher |
*/ |
#include "drmP.h" |
#include "radeon_drm.h" |
#include <drm/drmP.h> |
#include <drm/radeon_drm.h> |
#include "radeon.h" |
|
#include "atom.h" |
56,6 → 56,10 |
radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, |
uint32_t supported_device); |
|
/* local */ |
static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, |
u16 voltage_id, u16 *voltage); |
|
union atom_supported_devices { |
struct _ATOM_SUPPORTED_DEVICES_INFO info; |
struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; |
62,32 → 66,25 |
struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1; |
}; |
|
static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev, |
uint8_t id) |
static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev, |
ATOM_GPIO_I2C_ASSIGMENT *gpio, |
u8 index) |
{ |
struct atom_context *ctx = rdev->mode_info.atom_context; |
ATOM_GPIO_I2C_ASSIGMENT *gpio; |
struct radeon_i2c_bus_rec i2c; |
int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); |
struct _ATOM_GPIO_I2C_INFO *i2c_info; |
uint16_t data_offset, size; |
int i, num_indices; |
/* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ |
if ((rdev->family == CHIP_R420) || |
(rdev->family == CHIP_R423) || |
(rdev->family == CHIP_RV410)) { |
if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || |
(le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || |
(le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { |
gpio->ucClkMaskShift = 0x19; |
gpio->ucDataMaskShift = 0x18; |
} |
} |
|
memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); |
i2c.valid = false; |
|
if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { |
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); |
|
num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / |
sizeof(ATOM_GPIO_I2C_ASSIGMENT); |
|
for (i = 0; i < num_indices; i++) { |
gpio = &i2c_info->asGPIO_Info[i]; |
|
/* some evergreen boards have bad data for this entry */ |
if (ASIC_IS_DCE4(rdev)) { |
if ((i == 7) && |
if ((index == 7) && |
(le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && |
(gpio->sucI2cId.ucAccess == 0)) { |
gpio->sucI2cId.ucAccess = 0x97; |
100,13 → 97,19 |
|
/* some DCE3 boards have bad data for this entry */ |
if (ASIC_IS_DCE3(rdev)) { |
if ((i == 4) && |
if ((index == 4) && |
(le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && |
(gpio->sucI2cId.ucAccess == 0x94)) |
gpio->sucI2cId.ucAccess = 0x14; |
} |
} |
|
if (gpio->sucI2cId.ucAccess == id) { |
static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio) |
{ |
struct radeon_i2c_bus_rec i2c; |
|
memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); |
|
i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; |
i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; |
i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; |
138,15 → 141,14 |
|
if (i2c.mask_clk_reg) |
i2c.valid = true; |
break; |
} |
} |
} |
else |
i2c.valid = false; |
|
return i2c; |
} |
|
void radeon_atombios_i2c_init(struct radeon_device *rdev) |
static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev, |
uint8_t id) |
{ |
struct atom_context *ctx = rdev->mode_info.atom_context; |
ATOM_GPIO_I2C_ASSIGMENT *gpio; |
155,9 → 157,9 |
struct _ATOM_GPIO_I2C_INFO *i2c_info; |
uint16_t data_offset, size; |
int i, num_indices; |
char stmp[32]; |
|
memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); |
i2c.valid = false; |
|
if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { |
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); |
167,60 → 169,44 |
|
for (i = 0; i < num_indices; i++) { |
gpio = &i2c_info->asGPIO_Info[i]; |
i2c.valid = false; |
|
/* some evergreen boards have bad data for this entry */ |
if (ASIC_IS_DCE4(rdev)) { |
if ((i == 7) && |
(le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && |
(gpio->sucI2cId.ucAccess == 0)) { |
gpio->sucI2cId.ucAccess = 0x97; |
gpio->ucDataMaskShift = 8; |
gpio->ucDataEnShift = 8; |
gpio->ucDataY_Shift = 8; |
gpio->ucDataA_Shift = 8; |
radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); |
|
if (gpio->sucI2cId.ucAccess == id) { |
i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); |
break; |
} |
} |
} |
|
/* some DCE3 boards have bad data for this entry */ |
if (ASIC_IS_DCE3(rdev)) { |
if ((i == 4) && |
(le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) && |
(gpio->sucI2cId.ucAccess == 0x94)) |
gpio->sucI2cId.ucAccess = 0x14; |
return i2c; |
} |
|
i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; |
i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; |
i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; |
i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; |
i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; |
i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; |
i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; |
i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; |
i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); |
i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); |
i2c.en_clk_mask = (1 << gpio->ucClkEnShift); |
i2c.en_data_mask = (1 << gpio->ucDataEnShift); |
i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); |
i2c.y_data_mask = (1 << gpio->ucDataY_Shift); |
i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); |
i2c.a_data_mask = (1 << gpio->ucDataA_Shift); |
void radeon_atombios_i2c_init(struct radeon_device *rdev) |
{ |
struct atom_context *ctx = rdev->mode_info.atom_context; |
ATOM_GPIO_I2C_ASSIGMENT *gpio; |
struct radeon_i2c_bus_rec i2c; |
int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); |
struct _ATOM_GPIO_I2C_INFO *i2c_info; |
uint16_t data_offset, size; |
int i, num_indices; |
char stmp[32]; |
|
if (gpio->sucI2cId.sbfAccess.bfHW_Capable) |
i2c.hw_capable = true; |
else |
i2c.hw_capable = false; |
if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { |
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); |
|
if (gpio->sucI2cId.ucAccess == 0xa0) |
i2c.mm_i2c = true; |
else |
i2c.mm_i2c = false; |
num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / |
sizeof(ATOM_GPIO_I2C_ASSIGMENT); |
|
i2c.i2c_id = gpio->sucI2cId.ucAccess; |
for (i = 0; i < num_indices; i++) { |
gpio = &i2c_info->asGPIO_Info[i]; |
|
if (i2c.mask_clk_reg) { |
i2c.valid = true; |
radeon_lookup_i2c_gpio_quirks(rdev, gpio, i); |
|
i2c = radeon_get_bus_rec_for_i2c_gpio(gpio); |
|
if (i2c.valid) { |
sprintf(stmp, "0x%x", i2c.i2c_id); |
rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp); |
} |
228,7 → 214,7 |
} |
} |
|
static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, |
static struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, |
u8 id) |
{ |
struct atom_context *ctx = rdev->mode_info.atom_context; |
271,7 → 257,9 |
|
memset(&hpd, 0, sizeof(struct radeon_hpd)); |
|
if (ASIC_IS_DCE4(rdev)) |
if (ASIC_IS_DCE6(rdev)) |
reg = SI_DC_GPIO_HPD_A; |
else if (ASIC_IS_DCE4(rdev)) |
reg = EVERGREEN_DC_GPIO_HPD_A; |
else |
reg = AVIVO_DC_GPIO_HPD_A; |
456,10 → 444,26 |
*/ |
if ((dev->pdev->device == 0x9498) && |
(dev->pdev->subsystem_vendor == 0x1682) && |
(dev->pdev->subsystem_device == 0x2452)) { |
(dev->pdev->subsystem_device == 0x2452) && |
(i2c_bus->valid == false) && |
!(supported_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))) { |
struct radeon_device *rdev = dev->dev_private; |
*i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93); |
} |
|
/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ |
if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) && |
(dev->pdev->subsystem_vendor == 0x1734) && |
(dev->pdev->subsystem_device == 0x11bd)) { |
if (*connector_type == DRM_MODE_CONNECTOR_VGA) { |
*connector_type = DRM_MODE_CONNECTOR_DVII; |
*line_mux = 0x3103; |
} else if (*connector_type == DRM_MODE_CONNECTOR_DVID) { |
*connector_type = DRM_MODE_CONNECTOR_DVII; |
} |
} |
|
|
return true; |
} |
|
1250,6 → 1254,10 |
if (rdev->clock.max_pixel_clock == 0) |
rdev->clock.max_pixel_clock = 40000; |
|
/* not technically a clock, but... */ |
rdev->mode_info.firmware_flags = |
le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess); |
|
return true; |
} |
|
1259,6 → 1267,8 |
union igp_info { |
struct _ATOM_INTEGRATED_SYSTEM_INFO info; |
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; |
struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; |
struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; |
}; |
|
bool radeon_atombios_sideport_present(struct radeon_device *rdev) |
1386,7 → 1396,7 |
struct radeon_mode_info *mode_info = &rdev->mode_info; |
int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); |
u16 data_offset, size; |
struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info; |
union igp_info *igp_info; |
u8 frev, crev; |
u16 percentage = 0, rate = 0; |
|
1393,22 → 1403,45 |
/* get any igp specific overrides */ |
if (atom_parse_data_header(mode_info->atom_context, index, &size, |
&frev, &crev, &data_offset)) { |
igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *) |
igp_info = (union igp_info *) |
(mode_info->atom_context->bios + data_offset); |
switch (crev) { |
case 6: |
switch (id) { |
case ASIC_INTERNAL_SS_ON_TMDS: |
percentage = le16_to_cpu(igp_info->usDVISSPercentage); |
rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz); |
percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage); |
rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz); |
break; |
case ASIC_INTERNAL_SS_ON_HDMI: |
percentage = le16_to_cpu(igp_info->usHDMISSPercentage); |
rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz); |
percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage); |
rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz); |
break; |
case ASIC_INTERNAL_SS_ON_LVDS: |
percentage = le16_to_cpu(igp_info->usLvdsSSPercentage); |
rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz); |
percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage); |
rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz); |
break; |
} |
break; |
case 7: |
switch (id) { |
case ASIC_INTERNAL_SS_ON_TMDS: |
percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage); |
rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz); |
break; |
case ASIC_INTERNAL_SS_ON_HDMI: |
percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage); |
rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz); |
break; |
case ASIC_INTERNAL_SS_ON_LVDS: |
percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage); |
rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz); |
break; |
} |
break; |
default: |
DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); |
break; |
} |
if (percentage) |
ss->percentage = percentage; |
if (rate) |
1892,6 → 1925,8 |
"emc2103", |
"Sumo", |
"Northern Islands", |
"Southern Islands", |
"lm96163", |
}; |
|
union power_info { |
1908,6 → 1943,7 |
struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; |
struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; |
struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; |
struct _ATOM_PPLIB_SI_CLOCK_INFO si; |
}; |
|
union pplib_power_state { |
1973,7 → 2009,8 |
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); |
|
/* add the i2c bus for thermal/fan chip */ |
if (power_info->info.ucOverdriveThermalController > 0) { |
if ((power_info->info.ucOverdriveThermalController > 0) && |
(power_info->info.ucOverdriveThermalController < ARRAY_SIZE(thermal_controller_names))) { |
DRM_INFO("Possible %s thermal controller at 0x%02x\n", |
thermal_controller_names[power_info->info.ucOverdriveThermalController], |
power_info->info.ucOverdriveControllerAddress >> 1); |
1996,10 → 2033,14 |
return state_index; |
/* last mode is usually default, array is low to high */ |
for (i = 0; i < num_modes; i++) { |
rdev->pm.power_state[state_index].clock_info = |
kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); |
if (!rdev->pm.power_state[state_index].clock_info) |
return state_index; |
rdev->pm.power_state[state_index].num_clock_modes = 1; |
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; |
switch (frev) { |
case 1: |
rdev->pm.power_state[state_index].num_clock_modes = 1; |
rdev->pm.power_state[state_index].clock_info[0].mclk = |
le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); |
rdev->pm.power_state[state_index].clock_info[0].sclk = |
2035,7 → 2076,6 |
state_index++; |
break; |
case 2: |
rdev->pm.power_state[state_index].num_clock_modes = 1; |
rdev->pm.power_state[state_index].clock_info[0].mclk = |
le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); |
rdev->pm.power_state[state_index].clock_info[0].sclk = |
2072,7 → 2112,6 |
state_index++; |
break; |
case 3: |
rdev->pm.power_state[state_index].num_clock_modes = 1; |
rdev->pm.power_state[state_index].clock_info[0].mclk = |
le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); |
rdev->pm.power_state[state_index].clock_info[0].sclk = |
2163,6 → 2202,11 |
(controller->ucFanParameters & |
ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); |
rdev->pm.int_thermal_type = THERMAL_TYPE_NI; |
} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { |
DRM_INFO("Internal thermal controller %s fan control\n", |
(controller->ucFanParameters & |
ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); |
rdev->pm.int_thermal_type = THERMAL_TYPE_SI; |
} else if ((controller->ucType == |
ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || |
(controller->ucType == |
2170,7 → 2214,7 |
(controller->ucType == |
ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { |
DRM_INFO("Special thermal controller config\n"); |
} else { |
} else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { |
DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", |
pp_lib_thermal_controller_names[controller->ucType], |
controller->ucI2cAddress >> 1, |
2185,6 → 2229,12 |
strlcpy(info.type, name, sizeof(info.type)); |
i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); |
} |
} else { |
DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", |
controller->ucType, |
controller->ucI2cAddress >> 1, |
(controller->ucFanParameters & |
ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); |
} |
} |
} |
2257,7 → 2307,7 |
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[mode_index - 1]; |
if (ASIC_IS_DCE5(rdev)) { |
if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) { |
/* NI chips post without MC ucode, so default clocks are strobe mode only */ |
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; |
2283,6 → 2333,7 |
union pplib_clock_info *clock_info) |
{ |
u32 sclk, mclk; |
u16 vddc; |
|
if (rdev->flags & RADEON_IS_IGP) { |
if (rdev->family >= CHIP_PALM) { |
2294,6 → 2345,19 |
sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; |
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; |
} |
} else if (ASIC_IS_DCE6(rdev)) { |
sclk = le16_to_cpu(clock_info->si.usEngineClockLow); |
sclk |= clock_info->si.ucEngineClockHigh << 16; |
mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); |
mclk |= clock_info->si.ucMemoryClockHigh << 16; |
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 = |
le16_to_cpu(clock_info->si.usVDDC); |
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = |
le16_to_cpu(clock_info->si.usVDDCI); |
} else if (ASIC_IS_DCE4(rdev)) { |
sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); |
sclk |= clock_info->evergreen.ucEngineClockHigh << 16; |
2321,11 → 2385,18 |
} |
|
/* patch up vddc if necessary */ |
if (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage == 0xff01) { |
u16 vddc; |
|
if (radeon_atom_get_max_vddc(rdev, &vddc) == 0) |
switch (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage) { |
case ATOM_VIRTUAL_VOLTAGE_ID0: |
case ATOM_VIRTUAL_VOLTAGE_ID1: |
case ATOM_VIRTUAL_VOLTAGE_ID2: |
case ATOM_VIRTUAL_VOLTAGE_ID3: |
if (radeon_atom_get_max_vddc(rdev, VOLTAGE_TYPE_VDDC, |
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage, |
&vddc) == 0) |
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc; |
break; |
default: |
break; |
} |
|
if (rdev->flags & RADEON_IS_IGP) { |
2377,6 → 2448,13 |
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + |
(power_state->v1.ucNonClockStateIndex * |
power_info->pplib.ucNonClockSize)); |
rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * |
((power_info->pplib.ucStateEntrySize - 1) ? |
(power_info->pplib.ucStateEntrySize - 1) : 1), |
GFP_KERNEL); |
if (!rdev->pm.power_state[i].clock_info) |
return state_index; |
if (power_info->pplib.ucStateEntrySize - 1) { |
for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { |
clock_info = (union pplib_clock_info *) |
(mode_info->atom_context->bios + data_offset + |
2389,6 → 2467,13 |
if (valid) |
mode_index++; |
} |
} else { |
rdev->pm.power_state[state_index].clock_info[0].mclk = |
rdev->clock.default_mclk; |
rdev->pm.power_state[state_index].clock_info[0].sclk = |
rdev->clock.default_sclk; |
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, |
2421,9 → 2506,9 |
int i, j, non_clock_array_index, clock_array_index; |
int state_index = 0, mode_index = 0; |
union pplib_clock_info *clock_info; |
struct StateArray *state_array; |
struct ClockInfoArray *clock_info_array; |
struct NonClockInfoArray *non_clock_info_array; |
struct _StateArray *state_array; |
struct _ClockInfoArray *clock_info_array; |
struct _NonClockInfoArray *non_clock_info_array; |
bool valid; |
union power_info *power_info; |
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); |
2436,13 → 2521,13 |
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); |
|
radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); |
state_array = (struct StateArray *) |
state_array = (struct _StateArray *) |
(mode_info->atom_context->bios + data_offset + |
le16_to_cpu(power_info->pplib.usStateArrayOffset)); |
clock_info_array = (struct ClockInfoArray *) |
clock_info_array = (struct _ClockInfoArray *) |
(mode_info->atom_context->bios + data_offset + |
le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); |
non_clock_info_array = (struct NonClockInfoArray *) |
non_clock_info_array = (struct _NonClockInfoArray *) |
(mode_info->atom_context->bios + data_offset + |
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); |
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * |
2456,6 → 2541,13 |
non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ |
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) |
&non_clock_info_array->nonClockInfo[non_clock_array_index]; |
rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * |
(power_state->v2.ucNumDPMLevels ? |
power_state->v2.ucNumDPMLevels : 1), |
GFP_KERNEL); |
if (!rdev->pm.power_state[i].clock_info) |
return state_index; |
if (power_state->v2.ucNumDPMLevels) { |
for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { |
clock_array_index = power_state->v2.clockInfoIndex[j]; |
/* XXX this might be an inagua bug... */ |
2462,7 → 2554,7 |
if (clock_array_index >= clock_info_array->ucNumEntries) |
continue; |
clock_info = (union pplib_clock_info *) |
&clock_info_array->clockInfo[clock_array_index]; |
&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; |
valid = radeon_atombios_parse_pplib_clock_info(rdev, |
state_index, mode_index, |
clock_info); |
2469,6 → 2561,13 |
if (valid) |
mode_index++; |
} |
} else { |
rdev->pm.power_state[state_index].clock_info[0].mclk = |
rdev->clock.default_mclk; |
rdev->pm.power_state[state_index].clock_info[0].sclk = |
rdev->clock.default_sclk; |
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, |
2524,6 → 2623,9 |
} else { |
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL); |
if (rdev->pm.power_state) { |
rdev->pm.power_state[0].clock_info = |
kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); |
if (rdev->pm.power_state[0].clock_info) { |
/* add the default mode */ |
rdev->pm.power_state[state_index].type = |
POWER_STATE_TYPE_DEFAULT; |
2539,12 → 2641,17 |
state_index++; |
} |
} |
} |
|
rdev->pm.num_power_states = state_index; |
|
rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; |
rdev->pm.current_clock_mode_index = 0; |
rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; |
if (rdev->pm.default_power_state_index >= 0) |
rdev->pm.current_vddc = |
rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; |
else |
rdev->pm.current_vddc = 0; |
} |
|
void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) |
2604,6 → 2711,7 |
struct _SET_VOLTAGE_PS_ALLOCATION alloc; |
struct _SET_VOLTAGE_PARAMETERS v1; |
struct _SET_VOLTAGE_PARAMETERS_V2 v2; |
struct _SET_VOLTAGE_PARAMETERS_V1_3 v3; |
}; |
|
void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type) |
2630,6 → 2738,11 |
args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE; |
args.v2.usVoltageLevel = cpu_to_le16(voltage_level); |
break; |
case 3: |
args.v3.ucVoltageType = voltage_type; |
args.v3.ucVoltageMode = ATOM_SET_VOLTAGE; |
args.v3.usVoltageLevel = cpu_to_le16(voltage_level); |
break; |
default: |
DRM_ERROR("Unknown table version %d, %d\n", frev, crev); |
return; |
2638,8 → 2751,8 |
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
} |
|
int radeon_atom_get_max_vddc(struct radeon_device *rdev, |
u16 *voltage) |
static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, |
u16 voltage_id, u16 *voltage) |
{ |
union set_voltage args; |
int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); |
2660,6 → 2773,15 |
|
*voltage = le16_to_cpu(args.v2.usVoltageLevel); |
break; |
case 3: |
args.v3.ucVoltageType = voltage_type; |
args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL; |
args.v3.usVoltageLevel = cpu_to_le16(voltage_id); |
|
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
*voltage = le16_to_cpu(args.v3.usVoltageLevel); |
break; |
default: |
DRM_ERROR("Unknown table version %d, %d\n", frev, crev); |
return -EINVAL; |
2911,6 → 3033,20 |
bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5; |
} |
} |
if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) && |
(radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) { |
if (connected) { |
DRM_DEBUG_KMS("DFP6 connected\n"); |
bios_0_scratch |= ATOM_S0_DFP6; |
bios_3_scratch |= ATOM_S3_DFP6_ACTIVE; |
bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6; |
} else { |
DRM_DEBUG_KMS("DFP6 disconnected\n"); |
bios_0_scratch &= ~ATOM_S0_DFP6; |
bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE; |
bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6; |
} |
} |
|
if (rdev->family >= CHIP_R600) { |
WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch); |
2931,6 → 3067,9 |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
uint32_t bios_3_scratch; |
|
if (ASIC_IS_DCE4(rdev)) |
return; |
|
if (rdev->family >= CHIP_R600) |
bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); |
else |
2983,6 → 3122,9 |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
uint32_t bios_2_scratch; |
|
if (ASIC_IS_DCE4(rdev)) |
return; |
|
if (rdev->family >= CHIP_R600) |
bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); |
else |