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,31 +1313,34 @@ void atom_parse_data_header(struct atom_context *ctx, int index, ...@@ -1309,31 +1313,34 @@ 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", DRM_DEBUG("atom firmware requested %08x %dkb\n",
...@@ -1341,6 +1348,7 @@ int atom_allocate_fb_scratch(struct atom_context *ctx) ...@@ -1341,6 +1348,7 @@ int atom_allocate_fb_scratch(struct atom_context *ctx)
firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb); firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024; 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,11 +75,9 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev ...@@ -75,11 +75,9 @@ 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++) { for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
gpio = &i2c_info->asGPIO_Info[i]; gpio = &i2c_info->asGPIO_Info[i];
...@@ -117,6 +115,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev ...@@ -117,6 +115,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
break; break;
} }
} }
}
return i2c; return i2c;
} }
...@@ -135,11 +134,11 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd ...@@ -135,11 +134,11 @@ 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++) { for (i = 0; i < num_indices; i++) {
pin = &gpio_info->asGPIO_Pin[i]; pin = &gpio_info->asGPIO_Pin[i];
...@@ -151,6 +150,7 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd ...@@ -151,6 +150,7 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd
break; break;
} }
} }
}
return gpio; return gpio;
} }
...@@ -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,8 +447,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -449,8 +447,8 @@ 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 =
...@@ -486,6 +484,12 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -486,6 +484,12 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
object_connector_convert[con_obj_id]; object_connector_convert[con_obj_id];
connector_object_id = con_obj_id; connector_object_id = con_obj_id;
} }
} else {
igp_lane_info = 0;
connector_type =
object_connector_convert[con_obj_id];
connector_object_id = con_obj_id;
}
if (connector_type == DRM_MODE_CONNECTOR_Unknown) if (connector_type == DRM_MODE_CONNECTOR_Unknown)
continue; continue;
...@@ -627,7 +631,7 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev, ...@@ -627,7 +631,7 @@ 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) {
...@@ -641,6 +645,9 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev, ...@@ -641,6 +645,9 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
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 = tmds_info =
(struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios + (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
data_offset); 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,9 +1346,11 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev) ...@@ -1349,9 +1346,11 @@ 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:
...@@ -1391,6 +1390,7 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev) ...@@ -1391,6 +1390,7 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
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_object_table(dev);
else
ret = radeon_get_atom_connector_info_from_supported_devices_table(dev); ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
if (ret == false)
ret = radeon_get_atom_connector_info_from_object_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,40 +58,42 @@ static void rs690_gpu_init(struct radeon_device *rdev) ...@@ -58,40 +58,42 @@ 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->ulBootUpMemoryClock); rdev->pm.igp_sideport_mclk.full = rfixed_const(info->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->usK8MemoryClock)); rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock)); rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->info.usFSBClock));
rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth); rdev->pm.igp_ht_link_width.full = rfixed_const(info->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_v2->ulBootUpSidePortClock); rdev->pm.igp_sideport_mclk.full = rfixed_const(info->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_v2->ulBootUpUMAClock); rdev->pm.igp_system_mclk.full = rfixed_const(info->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_v2->ulHTLinkFreq); rdev->pm.igp_ht_link_clk.full = rfixed_const(info->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_v2->usMinHTLinkWidth)); rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
break; break;
default: default:
tmp.full = rfixed_const(100); tmp.full = rfixed_const(100);
...@@ -106,6 +108,18 @@ void rs690_pm_info(struct radeon_device *rdev) ...@@ -106,6 +108,18 @@ void rs690_pm_info(struct radeon_device *rdev)
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; break;
} }
} else {
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");
}
/* 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 */
tmp.full = rfixed_const(4); tmp.full = rfixed_const(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