Commit a084e6ee authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms/atom: make sure tables are valid (v2)

Check that atom cmd and data tables are valid
before using them.

(v2)
- fix some whitespace errors noticed by Rafał Miłecki
- check a few more cases
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent c1bcad9d
...@@ -1295,12 +1295,16 @@ void atom_destroy(struct atom_context *ctx) ...@@ -1295,12 +1295,16 @@ void atom_destroy(struct atom_context *ctx)
kfree(ctx); kfree(ctx);
} }
void atom_parse_data_header(struct atom_context *ctx, int index, bool atom_parse_data_header(struct atom_context *ctx, int index,
uint16_t * size, uint8_t * frev, uint8_t * crev, uint16_t * size, uint8_t * frev, uint8_t * crev,
uint16_t * data_start) uint16_t * data_start)
{ {
int offset = index * 2 + 4; int offset = index * 2 + 4;
int idx = CU16(ctx->data_table + offset); int idx = CU16(ctx->data_table + offset);
u16 *mdt = (u16 *)(ctx->bios + ctx->data_table + 4);
if (!mdt[index])
return false;
if (size) if (size)
*size = CU16(idx); *size = CU16(idx);
...@@ -1309,38 +1313,42 @@ void atom_parse_data_header(struct atom_context *ctx, int index, ...@@ -1309,38 +1313,42 @@ void atom_parse_data_header(struct atom_context *ctx, int index,
if (crev) if (crev)
*crev = CU8(idx + 3); *crev = CU8(idx + 3);
*data_start = idx; *data_start = idx;
return; return true;
} }
void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev, bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
uint8_t * crev) uint8_t * crev)
{ {
int offset = index * 2 + 4; int offset = index * 2 + 4;
int idx = CU16(ctx->cmd_table + offset); int idx = CU16(ctx->cmd_table + offset);
u16 *mct = (u16 *)(ctx->bios + ctx->cmd_table + 4);
if (!mct[index])
return false;
if (frev) if (frev)
*frev = CU8(idx + 2); *frev = CU8(idx + 2);
if (crev) if (crev)
*crev = CU8(idx + 3); *crev = CU8(idx + 3);
return; return true;
} }
int atom_allocate_fb_scratch(struct atom_context *ctx) int atom_allocate_fb_scratch(struct atom_context *ctx)
{ {
int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware); int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
uint16_t data_offset; uint16_t data_offset;
int usage_bytes; int usage_bytes = 0;
struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage; struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset); if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset); DRM_DEBUG("atom firmware requested %08x %dkb\n",
firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
DRM_DEBUG("atom firmware requested %08x %dkb\n", usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware, }
firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
if (usage_bytes == 0) if (usage_bytes == 0)
usage_bytes = 20 * 1024; usage_bytes = 20 * 1024;
/* allocate some scratch memory */ /* allocate some scratch memory */
......
...@@ -143,8 +143,10 @@ struct atom_context *atom_parse(struct card_info *, void *); ...@@ -143,8 +143,10 @@ struct atom_context *atom_parse(struct card_info *, void *);
int atom_execute_table(struct atom_context *, int, uint32_t *); int atom_execute_table(struct atom_context *, int, uint32_t *);
int atom_asic_init(struct atom_context *); int atom_asic_init(struct atom_context *);
void atom_destroy(struct atom_context *); void atom_destroy(struct atom_context *);
void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start); bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev); uint8_t *frev, uint8_t *crev, uint16_t *data_start);
bool atom_parse_cmd_header(struct atom_context *ctx, int index,
uint8_t *frev, uint8_t *crev);
int atom_allocate_fb_scratch(struct atom_context *ctx); int atom_allocate_fb_scratch(struct atom_context *ctx);
#include "atom-types.h" #include "atom-types.h"
#include "atombios.h" #include "atombios.h"
......
...@@ -541,8 +541,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -541,8 +541,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
int index; int index;
index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev); &crev))
return adjusted_clock;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
...@@ -630,8 +631,9 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc) ...@@ -630,8 +631,9 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc)
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev); &crev))
return;
switch (frev) { switch (frev) {
case 1: case 1:
...@@ -705,8 +707,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ...@@ -705,8 +707,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
&ref_div, &post_div); &ref_div, &post_div);
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev); &crev))
return;
switch (frev) { switch (frev) {
case 1: case 1:
......
...@@ -75,46 +75,45 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev ...@@ -75,46 +75,45 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
i2c.valid = false; i2c.valid = false;
atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset); if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
gpio = &i2c_info->asGPIO_Info[i];
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
gpio = &i2c_info->asGPIO_Info[i]; if (gpio->sucI2cId.ucAccess == id) {
i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
if (gpio->sucI2cId.ucAccess == id) { i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); i2c.en_data_mask = (1 << gpio->ucDataEnShift);
i2c.en_clk_mask = (1 << gpio->ucClkEnShift); i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
i2c.en_data_mask = (1 << gpio->ucDataEnShift); i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
i2c.y_data_mask = (1 << gpio->ucDataY_Shift); i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
i2c.a_data_mask = (1 << gpio->ucDataA_Shift); if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
i2c.hw_capable = true;
if (gpio->sucI2cId.sbfAccess.bfHW_Capable) else
i2c.hw_capable = true; i2c.hw_capable = false;
else
i2c.hw_capable = false; if (gpio->sucI2cId.ucAccess == 0xa0)
i2c.mm_i2c = true;
if (gpio->sucI2cId.ucAccess == 0xa0) else
i2c.mm_i2c = true; i2c.mm_i2c = false;
else
i2c.mm_i2c = false; i2c.i2c_id = gpio->sucI2cId.ucAccess;
i2c.i2c_id = gpio->sucI2cId.ucAccess; i2c.valid = true;
break;
i2c.valid = true; }
break;
} }
} }
...@@ -135,20 +134,21 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd ...@@ -135,20 +134,21 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd
memset(&gpio, 0, sizeof(struct radeon_gpio_rec)); memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
gpio.valid = false; gpio.valid = false;
atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset); if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset); num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); for (i = 0; i < num_indices; i++) {
pin = &gpio_info->asGPIO_Pin[i];
for (i = 0; i < num_indices; i++) { if (id == pin->ucGPIO_ID) {
pin = &gpio_info->asGPIO_Pin[i]; gpio.id = pin->ucGPIO_ID;
if (id == pin->ucGPIO_ID) { gpio.reg = pin->usGpioPin_AIndex * 4;
gpio.id = pin->ucGPIO_ID; gpio.mask = (1 << pin->ucGpioPinBitShift);
gpio.reg = pin->usGpioPin_AIndex * 4; gpio.valid = true;
gpio.mask = (1 << pin->ucGpioPinBitShift); break;
gpio.valid = true; }
break;
} }
} }
...@@ -395,9 +395,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -395,9 +395,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
struct radeon_gpio_rec gpio; struct radeon_gpio_rec gpio;
struct radeon_hpd hpd; struct radeon_hpd hpd;
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
if (data_offset == 0)
return false; return false;
if (crev < 2) if (crev < 2)
...@@ -449,37 +447,43 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -449,37 +447,43 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
GetIndexIntoMasterTable(DATA, GetIndexIntoMasterTable(DATA,
IntegratedSystemInfo); IntegratedSystemInfo);
atom_parse_data_header(ctx, index, &size, &frev, if (atom_parse_data_header(ctx, index, &size, &frev,
&crev, &igp_offset); &crev, &igp_offset)) {
if (crev >= 2) { if (crev >= 2) {
igp_obj = igp_obj =
(ATOM_INTEGRATED_SYSTEM_INFO_V2 (ATOM_INTEGRATED_SYSTEM_INFO_V2
*) (ctx->bios + igp_offset); *) (ctx->bios + igp_offset);
if (igp_obj) { if (igp_obj) {
uint32_t slot_config, ct; uint32_t slot_config, ct;
if (con_obj_num == 1) if (con_obj_num == 1)
slot_config = slot_config =
igp_obj-> igp_obj->
ulDDISlot1Config; ulDDISlot1Config;
else else
slot_config = slot_config =
igp_obj-> igp_obj->
ulDDISlot2Config; ulDDISlot2Config;
ct = (slot_config >> 16) & 0xff; ct = (slot_config >> 16) & 0xff;
connector_type = connector_type =
object_connector_convert object_connector_convert
[ct]; [ct];
connector_object_id = ct; connector_object_id = ct;
igp_lane_info = igp_lane_info =
slot_config & 0xffff; slot_config & 0xffff;
} else
continue;
} else } else
continue; continue;
} else } else {
continue; igp_lane_info = 0;
connector_type =
object_connector_convert[con_obj_id];
connector_object_id = con_obj_id;
}
} else { } else {
igp_lane_info = 0; igp_lane_info = 0;
connector_type = connector_type =
...@@ -627,20 +631,23 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev, ...@@ -627,20 +631,23 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
uint8_t frev, crev; uint8_t frev, crev;
ATOM_XTMDS_INFO *xtmds; ATOM_XTMDS_INFO *xtmds;
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) {
xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset); xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) { if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
if (connector_type == DRM_MODE_CONNECTOR_DVII) if (connector_type == DRM_MODE_CONNECTOR_DVII)
return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I; return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
else else
return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D; return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
} else { } else {
if (connector_type == DRM_MODE_CONNECTOR_DVII) if (connector_type == DRM_MODE_CONNECTOR_DVII)
return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
else else
return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D; return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
} }
} else
return supported_devices_connector_object_id_convert
[connector_type];
} else { } else {
return supported_devices_connector_object_id_convert return supported_devices_connector_object_id_convert
[connector_type]; [connector_type];
...@@ -672,7 +679,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct ...@@ -672,7 +679,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
int i, j, max_device; int i, j, max_device;
struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE]; struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
return false;
supported_devices = supported_devices =
(union atom_supported_devices *)(ctx->bios + data_offset); (union atom_supported_devices *)(ctx->bios + data_offset);
...@@ -865,14 +873,11 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) ...@@ -865,14 +873,11 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
struct radeon_pll *mpll = &rdev->clock.mpll; struct radeon_pll *mpll = &rdev->clock.mpll;
uint16_t data_offset; uint16_t data_offset;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&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);
if (firmware_info) {
/* pixel clocks */ /* pixel clocks */
p1pll->reference_freq = p1pll->reference_freq =
le16_to_cpu(firmware_info->info.usReferenceClock); le16_to_cpu(firmware_info->info.usReferenceClock);
...@@ -1006,13 +1011,10 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev) ...@@ -1006,13 +1011,10 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev)
u8 frev, crev; u8 frev, crev;
u16 data_offset; u16 data_offset;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&crev, &data_offset); &frev, &crev, &data_offset)) {
igp_info = (union igp_info *)(mode_info->atom_context->bios +
igp_info = (union igp_info *)(mode_info->atom_context->bios +
data_offset); data_offset);
if (igp_info) {
switch (crev) { switch (crev) {
case 1: case 1:
if (igp_info->info.ucMemoryType & 0xf0) if (igp_info->info.ucMemoryType & 0xf0)
...@@ -1043,14 +1045,12 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, ...@@ -1043,14 +1045,12 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
uint16_t maxfreq; uint16_t maxfreq;
int i; int i;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&crev, &data_offset); &frev, &crev, &data_offset)) {
tmds_info =
(struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
data_offset);
tmds_info =
(struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
data_offset);
if (tmds_info) {
maxfreq = le16_to_cpu(tmds_info->usMaxFrequency); maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
tmds->tmds_pll[i].freq = tmds->tmds_pll[i].freq =
...@@ -1099,13 +1099,11 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct ...@@ -1099,13 +1099,11 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
if (id > ATOM_MAX_SS_ENTRY) if (id > ATOM_MAX_SS_ENTRY)
return NULL; return NULL;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&crev, &data_offset); &frev, &crev, &data_offset)) {
ss_info =
ss_info = (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
(struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
if (ss_info) {
ss = ss =
kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL); kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL);
...@@ -1146,13 +1144,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct ...@@ -1146,13 +1144,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
uint8_t frev, crev; uint8_t frev, crev;
struct radeon_encoder_atom_dig *lvds = NULL; struct radeon_encoder_atom_dig *lvds = NULL;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&crev, &data_offset); &frev, &crev, &data_offset)) {
lvds_info =
lvds_info = (union lvds_info *)(mode_info->atom_context->bios + data_offset);
(union lvds_info *)(mode_info->atom_context->bios + data_offset);
if (lvds_info) {
lvds = lvds =
kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
...@@ -1228,11 +1223,11 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder) ...@@ -1228,11 +1223,11 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
uint8_t bg, dac; uint8_t bg, dac;
struct radeon_encoder_primary_dac *p_dac = NULL; struct radeon_encoder_primary_dac *p_dac = NULL;
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,
&frev, &crev, &data_offset)) {
dac_info = (struct _COMPASSIONATE_DATA *)
(mode_info->atom_context->bios + data_offset);
dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
if (dac_info) {
p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL); p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);
if (!p_dac) if (!p_dac)
...@@ -1257,7 +1252,9 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, ...@@ -1257,7 +1252,9 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
u8 frev, crev; u8 frev, crev;
u16 data_offset, misc; u16 data_offset, misc;
atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset); if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL,
&frev, &crev, &data_offset))
return false;
switch (crev) { switch (crev) {
case 1: case 1:
...@@ -1349,47 +1346,50 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev) ...@@ -1349,47 +1346,50 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
struct _ATOM_ANALOG_TV_INFO *tv_info; struct _ATOM_ANALOG_TV_INFO *tv_info;
enum radeon_tv_std tv_std = TV_STD_NTSC; enum radeon_tv_std tv_std = TV_STD_NTSC;
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,
&frev, &crev, &data_offset)) {
tv_info = (struct _ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset); tv_info = (struct _ATOM_ANALOG_TV_INFO *)
(mode_info->atom_context->bios + data_offset);
switch (tv_info->ucTV_BootUpDefaultStandard) { switch (tv_info->ucTV_BootUpDefaultStandard) {
case ATOM_TV_NTSC: case ATOM_TV_NTSC:
tv_std = TV_STD_NTSC; tv_std = TV_STD_NTSC;
DRM_INFO("Default TV standard: NTSC\n"); DRM_INFO("Default TV standard: NTSC\n");
break; break;
case ATOM_TV_NTSCJ: case ATOM_TV_NTSCJ:
tv_std = TV_STD_NTSC_J; tv_std = TV_STD_NTSC_J;
DRM_INFO("Default TV standard: NTSC-J\n"); DRM_INFO("Default TV standard: NTSC-J\n");
break; break;
case ATOM_TV_PAL: case ATOM_TV_PAL:
tv_std = TV_STD_PAL; tv_std = TV_STD_PAL;
DRM_INFO("Default TV standard: PAL\n"); DRM_INFO("Default TV standard: PAL\n");
break; break;
case ATOM_TV_PALM: case ATOM_TV_PALM:
tv_std = TV_STD_PAL_M; tv_std = TV_STD_PAL_M;
DRM_INFO("Default TV standard: PAL-M\n"); DRM_INFO("Default TV standard: PAL-M\n");
break; break;
case ATOM_TV_PALN: case ATOM_TV_PALN:
tv_std = TV_STD_PAL_N; tv_std = TV_STD_PAL_N;
DRM_INFO("Default TV standard: PAL-N\n"); DRM_INFO("Default TV standard: PAL-N\n");
break; break;
case ATOM_TV_PALCN: case ATOM_TV_PALCN:
tv_std = TV_STD_PAL_CN; tv_std = TV_STD_PAL_CN;
DRM_INFO("Default TV standard: PAL-CN\n"); DRM_INFO("Default TV standard: PAL-CN\n");
break; break;
case ATOM_TV_PAL60: case ATOM_TV_PAL60:
tv_std = TV_STD_PAL_60; tv_std = TV_STD_PAL_60;
DRM_INFO("Default TV standard: PAL-60\n"); DRM_INFO("Default TV standard: PAL-60\n");
break; break;
case ATOM_TV_SECAM: case ATOM_TV_SECAM:
tv_std = TV_STD_SECAM; tv_std = TV_STD_SECAM;
DRM_INFO("Default TV standard: SECAM\n"); DRM_INFO("Default TV standard: SECAM\n");
break; break;
default: default:
tv_std = TV_STD_NTSC; tv_std = TV_STD_NTSC;
DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
break; break;
}
} }
return tv_std; return tv_std;
} }
...@@ -1407,11 +1407,12 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) ...@@ -1407,11 +1407,12 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
uint8_t bg, dac; uint8_t bg, dac;
struct radeon_encoder_tv_dac *tv_dac = NULL; struct radeon_encoder_tv_dac *tv_dac = NULL;
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,
&frev, &crev, &data_offset)) {
dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset); dac_info = (struct _COMPASSIONATE_DATA *)
(mode_info->atom_context->bios + data_offset);
if (dac_info) {
tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
if (!tv_dac) if (!tv_dac)
...@@ -1479,13 +1480,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -1479,13 +1480,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
int state_index = 0, mode_index = 0; int state_index = 0, mode_index = 0;
struct radeon_i2c_bus_rec i2c_bus; struct radeon_i2c_bus_rec i2c_bus;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
rdev->pm.default_power_state = NULL; rdev->pm.default_power_state = NULL;
if (power_info) { if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
if (frev < 4) { 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) {
......
...@@ -368,10 +368,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev) ...@@ -368,10 +368,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
if (rdev->bios) { if (rdev->bios) {
if (rdev->is_atom_bios) { if (rdev->is_atom_bios) {
if (rdev->family >= CHIP_R600) ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
if (ret == false)
ret = radeon_get_atom_connector_info_from_object_table(dev); ret = radeon_get_atom_connector_info_from_object_table(dev);
else
ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
} else { } else {
ret = radeon_get_legacy_connector_info_from_bios(dev); ret = radeon_get_legacy_connector_info_from_bios(dev);
if (ret == false) if (ret == false)
......
...@@ -519,7 +519,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) ...@@ -519,7 +519,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
break; break;
} }
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
switch (frev) { switch (frev) {
case 1: case 1:
...@@ -725,7 +726,8 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) ...@@ -725,7 +726,8 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
} }
num = dig->dig_encoder + 1; num = dig->dig_encoder + 1;
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
args.v1.ucAction = action; args.v1.ucAction = action;
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
...@@ -813,7 +815,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -813,7 +815,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
} }
} }
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
args.v1.ucAction = action; args.v1.ucAction = action;
if (action == ATOM_TRANSMITTER_ACTION_INIT) { if (action == ATOM_TRANSMITTER_ACTION_INIT) {
...@@ -1103,7 +1106,8 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) ...@@ -1103,7 +1106,8 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
switch (frev) { switch (frev) {
case 1: case 1:
...@@ -1411,7 +1415,8 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn ...@@ -1411,7 +1415,8 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return false;
args.sDacload.ucMisc = 0; args.sDacload.ucMisc = 0;
......
...@@ -58,42 +58,57 @@ static void rs690_gpu_init(struct radeon_device *rdev) ...@@ -58,42 +58,57 @@ static void rs690_gpu_init(struct radeon_device *rdev)
} }
} }
union igp_info {
struct _ATOM_INTEGRATED_SYSTEM_INFO info;
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_v2;
};
void rs690_pm_info(struct radeon_device *rdev) void rs690_pm_info(struct radeon_device *rdev)
{ {
int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
struct _ATOM_INTEGRATED_SYSTEM_INFO *info; union igp_info *info;
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2;
void *ptr;
uint16_t data_offset; uint16_t data_offset;
uint8_t frev, crev; uint8_t frev, crev;
fixed20_12 tmp; fixed20_12 tmp;
atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
&frev, &crev, &data_offset); &frev, &crev, &data_offset)) {
ptr = rdev->mode_info.atom_context->bios + data_offset; info = (union igp_info *)(rdev->mode_info.atom_context->bios + data_offset);
info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr;
info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr; /* Get various system informations from bios */
/* Get various system informations from bios */ switch (crev) {
switch (crev) { case 1:
case 1: tmp.full = rfixed_const(100);
tmp.full = rfixed_const(100); rdev->pm.igp_sideport_mclk.full = rfixed_const(info->info.ulBootUpMemoryClock);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock); rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock)); rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->info.usFSBClock));
rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock)); rdev->pm.igp_ht_link_width.full = rfixed_const(info->info.ucHTLinkWidth);
rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth); break;
break; case 2:
case 2: tmp.full = rfixed_const(100);
tmp.full = rfixed_const(100); rdev->pm.igp_sideport_mclk.full = rfixed_const(info->info_v2.ulBootUpSidePortClock);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock); rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); rdev->pm.igp_system_mclk.full = rfixed_const(info->info_v2.ulBootUpUMAClock);
rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock); rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp); rdev->pm.igp_ht_link_clk.full = rfixed_const(info->info_v2.ulHTLinkFreq);
rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq); rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp); rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth)); break;
break; default:
default: tmp.full = rfixed_const(100);
/* We assume the slower possible clock ie worst case */
/* DDR 333Mhz */
rdev->pm.igp_sideport_mclk.full = rfixed_const(333);
/* FIXME: system clock ? */
rdev->pm.igp_system_mclk.full = rfixed_const(100);
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
rdev->pm.igp_ht_link_width.full = rfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n");
break;
}
} else {
tmp.full = rfixed_const(100); tmp.full = rfixed_const(100);
/* We assume the slower possible clock ie worst case */ /* We assume the slower possible clock ie worst case */
/* DDR 333Mhz */ /* DDR 333Mhz */
...@@ -104,7 +119,6 @@ void rs690_pm_info(struct radeon_device *rdev) ...@@ -104,7 +119,6 @@ void rs690_pm_info(struct radeon_device *rdev)
rdev->pm.igp_ht_link_clk.full = rfixed_const(200); rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
rdev->pm.igp_ht_link_width.full = rfixed_const(8); rdev->pm.igp_ht_link_width.full = rfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n"); DRM_ERROR("No integrated system info for your GPU, using safe default\n");
break;
} }
/* Compute various bandwidth */ /* Compute various bandwidth */
/* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */ /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */
......
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