From 267364ac17f6474c69b03034340f769b22f46105 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 8 Mar 2010 17:10:41 -0500 Subject: drm/radeon/kms: further spread spectrum fixes Adjust modeset ordering to fix spread spectrum. The spread spectrum command table relies on the crtc routing to already be set in order to work properly on some asics. Should fix fdo bug 25741. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index bc926ea0a53..4eae30cc521 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1216,6 +1216,9 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) } atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + /* update scratch regs with new routing */ + radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); } static void @@ -1326,19 +1329,9 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); - if (radeon_encoder->active_device & - (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { - struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - if (dig) - dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); - } radeon_encoder->pixel_clock = adjusted_mode->clock; - radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); - atombios_set_encoder_crtc_source(encoder); - if (ASIC_IS_AVIVO(rdev)) { if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) atombios_yuv_setup(encoder, true); @@ -1492,8 +1485,20 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + if (radeon_encoder->active_device & + (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + if (dig) + dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder); + } + radeon_atom_output_lock(encoder, true); radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + + /* this is needed for the pll/ss setup to work correctly in some cases */ + atombios_set_encoder_crtc_source(encoder); } static void radeon_atom_encoder_commit(struct drm_encoder *encoder) -- cgit v1.2.3-70-g09d2 From 2cd6218cb8043ef4360b561e726cd081f8a380cc Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 8 Mar 2010 22:14:01 +0000 Subject: drm/radeon/kms: clean assigning HDMI blocks to encoders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We almost always used first HDMI block for first encoder and second for sencod. Exception was KLDSCP_LVTMA. Analyzing code picking DIG encoder shows the same behaviour. It shows HDMI block are related to DIGs, which relation we now use. Signed-off-by: Rafał Miłecki Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_audio.c | 7 +- drivers/gpu/drm/radeon/r600_hdmi.c | 114 +++++++++++++------------------ drivers/gpu/drm/radeon/radeon.h | 3 +- drivers/gpu/drm/radeon/radeon_encoders.c | 10 +-- 4 files changed, 62 insertions(+), 72 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c') diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index db928016d03..baf222faf15 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c @@ -224,6 +224,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; int base_rate = 48000; switch (radeon_encoder->encoder_id) { @@ -245,7 +246,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) return; } - switch (r600_audio_tmds_index(encoder)) { + switch (dig->dig_encoder) { case 0: WREG32(R600_AUDIO_PLL1_MUL, base_rate*50); WREG32(R600_AUDIO_PLL1_DIV, clock*100); @@ -257,6 +258,10 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) WREG32(R600_AUDIO_PLL2_DIV, clock*100); WREG32(R600_AUDIO_CLK_SRCSEL, 1); break; + default: + dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n", + radeon_encoder->encoder_id); + return; } } diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 4d09973ad6a..5275a81b1df 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -417,90 +417,74 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000); } -/* - * enable/disable the HDMI engine - */ -void r600_hdmi_enable(struct drm_encoder *encoder, int enable) +static void r600_hdmi_assign_block(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset; + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - if (!offset) + if (!dig) { + dev_err(rdev->dev, "Enabling HDMI on non-dig encoder\n"); return; + } - DRM_DEBUG("%s HDMI interface @ 0x%04X\n", enable ? "Enabling" : "Disabling", offset); - - /* some version of atombios ignore the enable HDMI flag - * so enabling/disabling HDMI was moved here for TMDS1+2 */ - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - WREG32_P(AVIVO_TMDSA_CNTL, enable ? 0x4 : 0x0, ~0x4); - WREG32(offset+R600_HDMI_ENABLE, enable ? 0x101 : 0x0); - break; - - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - WREG32_P(AVIVO_LVTMA_CNTL, enable ? 0x4 : 0x0, ~0x4); - WREG32(offset+R600_HDMI_ENABLE, enable ? 0x105 : 0x0); - break; - - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - /* This part is doubtfull in my opinion */ - WREG32(offset+R600_HDMI_ENABLE, enable ? 0x110 : 0x0); - break; - - default: - DRM_ERROR("unknown HDMI output type\n"); - break; + if (ASIC_IS_DCE4(rdev)) { + /* TODO */ + } else if (ASIC_IS_DCE3(rdev)) { + radeon_encoder->hdmi_offset = dig->dig_encoder ? + R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1; + if (ASIC_IS_DCE32(rdev)) + radeon_encoder->hdmi_config_offset = dig->dig_encoder ? + R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1; } } /* - * determin at which register offset the HDMI encoder is + * enable the HDMI engine */ -void r600_hdmi_init(struct drm_encoder *encoder) +void r600_hdmi_enable(struct drm_encoder *encoder) { + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - radeon_encoder->hdmi_offset = R600_HDMI_BLOCK1; - break; - - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - switch (r600_audio_tmds_index(encoder)) { - case 0: - radeon_encoder->hdmi_offset = R600_HDMI_BLOCK1; - break; - case 1: - radeon_encoder->hdmi_offset = R600_HDMI_BLOCK2; - break; - default: - radeon_encoder->hdmi_offset = 0; - break; + if (!radeon_encoder->hdmi_offset) { + r600_hdmi_assign_block(encoder); + if (!radeon_encoder->hdmi_offset) { + dev_warn(rdev->dev, "Could not find HDMI block for " + "0x%x encoder\n", radeon_encoder->encoder_id); + return; } - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - radeon_encoder->hdmi_offset = R600_HDMI_BLOCK2; - break; + } - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - radeon_encoder->hdmi_offset = R600_HDMI_BLOCK3; - break; + if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) + WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1); + + DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", + radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); +} - default: - radeon_encoder->hdmi_offset = 0; - break; +/* + * disable the HDMI engine + */ +void r600_hdmi_disable(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + + if (!radeon_encoder->hdmi_offset) { + dev_err(rdev->dev, "Disabling not enabled HDMI\n"); + return; } - DRM_DEBUG("using HDMI engine at offset 0x%04X for encoder 0x%x\n", - radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); + DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", + radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); + + if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) + WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1); - /* TODO: make this configureable */ - radeon_encoder->hdmi_audio_workaround = 0; + radeon_encoder->hdmi_offset = 0; + radeon_encoder->hdmi_config_offset = 0; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 829e26e8a4b..ba93e5a20b2 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1322,7 +1322,8 @@ extern int r600_audio_tmds_index(struct drm_encoder *encoder); extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); extern void r600_audio_fini(struct radeon_device *rdev); extern void r600_hdmi_init(struct drm_encoder *encoder); -extern void r600_hdmi_enable(struct drm_encoder *encoder, int enable); +extern void r600_hdmi_enable(struct drm_encoder *encoder); +extern void r600_hdmi_disable(struct drm_encoder *encoder); extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 4eae30cc521..a236c75496c 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -593,7 +593,6 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) } atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); - r600_hdmi_enable(encoder, hdmi_detected); } int @@ -1389,9 +1388,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, } atombios_apply_encoder_quirks(encoder, adjusted_mode); - /* XXX */ - if (!ASIC_IS_DCE4(rdev)) + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { + r600_hdmi_enable(encoder); r600_hdmi_setmode(encoder, adjusted_mode); + } } static bool @@ -1514,6 +1514,8 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); if (radeon_encoder_is_digital(encoder)) { + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) + r600_hdmi_disable(encoder); dig = radeon_encoder->enc_priv; dig->dig_encoder = -1; } @@ -1664,6 +1666,4 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); break; } - - r600_hdmi_init(encoder); } -- cgit v1.2.3-70-g09d2 From a084e6ee6e64a76f1a9665d527203cdab7d6048f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 18 Mar 2010 01:04:01 -0400 Subject: drm/radeon/kms/atom: make sure tables are valid (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atom.c | 32 ++- drivers/gpu/drm/radeon/atom.h | 6 +- drivers/gpu/drm/radeon/atombios_crtc.c | 15 +- drivers/gpu/drm/radeon/radeon_atombios.c | 367 +++++++++++++++---------------- drivers/gpu/drm/radeon/radeon_display.c | 5 +- drivers/gpu/drm/radeon/radeon_encoders.c | 15 +- drivers/gpu/drm/radeon/rs690.c | 74 ++++--- 7 files changed, 272 insertions(+), 242 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c') diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index b7fe660985c..247f8ee7e94 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -1295,12 +1295,16 @@ void atom_destroy(struct atom_context *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 * data_start) { int offset = index * 2 + 4; int idx = CU16(ctx->data_table + offset); + u16 *mdt = (u16 *)(ctx->bios + ctx->data_table + 4); + + if (!mdt[index]) + return false; if (size) *size = CU16(idx); @@ -1309,38 +1313,42 @@ void atom_parse_data_header(struct atom_context *ctx, int index, if (crev) *crev = CU8(idx + 3); *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) { int offset = index * 2 + 4; int idx = CU16(ctx->cmd_table + offset); + u16 *mct = (u16 *)(ctx->bios + ctx->cmd_table + 4); + + if (!mct[index]) + return false; if (frev) *frev = CU8(idx + 2); if (crev) *crev = CU8(idx + 3); - return; + return true; } int atom_allocate_fb_scratch(struct atom_context *ctx) { int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware); uint16_t data_offset; - int usage_bytes; + int usage_bytes = 0; 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", - firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware, - 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) usage_bytes = 20 * 1024; /* allocate some scratch memory */ diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index 1b262631480..cd1b64ab5ca 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h @@ -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_asic_init(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); -void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev); +bool 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_cmd_header(struct atom_context *ctx, int index, + uint8_t *frev, uint8_t *crev); int atom_allocate_fb_scratch(struct atom_context *ctx); #include "atom-types.h" #include "atombios.h" diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 94aa6b293e0..56107b3a997 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -541,8 +541,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, int index; index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); - 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 adjusted_clock; memset(&args, 0, sizeof(args)); @@ -630,8 +631,9 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc) memset(&args, 0, sizeof(args)); index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); - 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) { case 1: @@ -705,8 +707,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode &ref_div, &post_div); index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); - 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) { case 1: diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 3733cb78779..f0ea7f8da67 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -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)); i2c.valid = false; - atom_parse_data_header(ctx, index, NULL, NULL, NULL, &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]; - - if (gpio->sucI2cId.ucAccess == id) { - 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); - - if (gpio->sucI2cId.sbfAccess.bfHW_Capable) - i2c.hw_capable = true; - else - i2c.hw_capable = false; - - if (gpio->sucI2cId.ucAccess == 0xa0) - i2c.mm_i2c = true; - else - i2c.mm_i2c = false; - - i2c.i2c_id = gpio->sucI2cId.ucAccess; - - i2c.valid = true; - break; + if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &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]; + + if (gpio->sucI2cId.ucAccess == id) { + 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); + + if (gpio->sucI2cId.sbfAccess.bfHW_Capable) + i2c.hw_capable = true; + else + i2c.hw_capable = false; + + if (gpio->sucI2cId.ucAccess == 0xa0) + i2c.mm_i2c = true; + else + i2c.mm_i2c = false; + + i2c.i2c_id = gpio->sucI2cId.ucAccess; + + i2c.valid = true; + break; + } } } @@ -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)); 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]; - if (id == pin->ucGPIO_ID) { - gpio.id = pin->ucGPIO_ID; - gpio.reg = pin->usGpioPin_AIndex * 4; - gpio.mask = (1 << pin->ucGpioPinBitShift); - gpio.valid = true; - break; + for (i = 0; i < num_indices; i++) { + pin = &gpio_info->asGPIO_Pin[i]; + if (id == pin->ucGPIO_ID) { + gpio.id = pin->ucGPIO_ID; + gpio.reg = pin->usGpioPin_AIndex * 4; + gpio.mask = (1 << pin->ucGpioPinBitShift); + gpio.valid = true; + break; + } } } @@ -395,9 +395,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) struct radeon_gpio_rec gpio; struct radeon_hpd hpd; - atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); - - if (data_offset == 0) + if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) return false; if (crev < 2) @@ -449,37 +447,43 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); - atom_parse_data_header(ctx, index, &size, &frev, - &crev, &igp_offset); - - if (crev >= 2) { - igp_obj = - (ATOM_INTEGRATED_SYSTEM_INFO_V2 - *) (ctx->bios + igp_offset); - - if (igp_obj) { - uint32_t slot_config, ct; - - if (con_obj_num == 1) - slot_config = - igp_obj-> - ulDDISlot1Config; - else - slot_config = - igp_obj-> - ulDDISlot2Config; - - ct = (slot_config >> 16) & 0xff; - connector_type = - object_connector_convert - [ct]; - connector_object_id = ct; - igp_lane_info = - slot_config & 0xffff; + if (atom_parse_data_header(ctx, index, &size, &frev, + &crev, &igp_offset)) { + + if (crev >= 2) { + igp_obj = + (ATOM_INTEGRATED_SYSTEM_INFO_V2 + *) (ctx->bios + igp_offset); + + if (igp_obj) { + uint32_t slot_config, ct; + + if (con_obj_num == 1) + slot_config = + igp_obj-> + ulDDISlot1Config; + else + slot_config = + igp_obj-> + ulDDISlot2Config; + + ct = (slot_config >> 16) & 0xff; + connector_type = + object_connector_convert + [ct]; + connector_object_id = ct; + igp_lane_info = + slot_config & 0xffff; + } else + continue; } else continue; - } else - continue; + } else { + igp_lane_info = 0; + connector_type = + object_connector_convert[con_obj_id]; + connector_object_id = con_obj_id; + } } else { igp_lane_info = 0; connector_type = @@ -627,20 +631,23 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev, uint8_t frev, crev; ATOM_XTMDS_INFO *xtmds; - atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); - xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset); + if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) { + xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset); - if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) { - if (connector_type == DRM_MODE_CONNECTOR_DVII) - return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I; - else - return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D; - } else { - if (connector_type == DRM_MODE_CONNECTOR_DVII) - return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; - else - return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D; - } + if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) { + if (connector_type == DRM_MODE_CONNECTOR_DVII) + return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I; + else + return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D; + } else { + if (connector_type == DRM_MODE_CONNECTOR_DVII) + return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; + else + return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D; + } + } else + return supported_devices_connector_object_id_convert + [connector_type]; } else { return supported_devices_connector_object_id_convert [connector_type]; @@ -672,7 +679,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct int i, j, max_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 = (union atom_supported_devices *)(ctx->bios + data_offset); @@ -865,14 +873,11 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) struct radeon_pll *mpll = &rdev->clock.mpll; uint16_t data_offset; - atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, - &crev, &data_offset); - - firmware_info = - (union firmware_info *)(mode_info->atom_context->bios + - data_offset); - - if (firmware_info) { + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + firmware_info = + (union firmware_info *)(mode_info->atom_context->bios + + data_offset); /* pixel clocks */ p1pll->reference_freq = le16_to_cpu(firmware_info->info.usReferenceClock); @@ -1006,13 +1011,10 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev) u8 frev, crev; u16 data_offset; - atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, - &crev, &data_offset); - - igp_info = (union igp_info *)(mode_info->atom_context->bios + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + igp_info = (union igp_info *)(mode_info->atom_context->bios + data_offset); - - if (igp_info) { switch (crev) { case 1: if (igp_info->info.ucMemoryType & 0xf0) @@ -1043,14 +1045,12 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, uint16_t maxfreq; int i; - 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)) { + 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); for (i = 0; i < 4; i++) { tmds->tmds_pll[i].freq = @@ -1099,13 +1099,11 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct if (id > ATOM_MAX_SS_ENTRY) return NULL; - atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, - &crev, &data_offset); - - ss_info = - (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset); + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + ss_info = + (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset); - if (ss_info) { ss = kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL); @@ -1146,13 +1144,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct uint8_t frev, crev; struct radeon_encoder_atom_dig *lvds = NULL; - atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, - &crev, &data_offset); - - lvds_info = - (union lvds_info *)(mode_info->atom_context->bios + data_offset); - - if (lvds_info) { + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + lvds_info = + (union lvds_info *)(mode_info->atom_context->bios + data_offset); lvds = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); @@ -1228,11 +1223,11 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder) uint8_t bg, dac; 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); if (!p_dac) @@ -1257,7 +1252,9 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, u8 frev, crev; 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) { case 1: @@ -1349,47 +1346,50 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev) struct _ATOM_ANALOG_TV_INFO *tv_info; 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) { - case ATOM_TV_NTSC: - tv_std = TV_STD_NTSC; - DRM_INFO("Default TV standard: NTSC\n"); - break; - case ATOM_TV_NTSCJ: - tv_std = TV_STD_NTSC_J; - DRM_INFO("Default TV standard: NTSC-J\n"); - break; - case ATOM_TV_PAL: - tv_std = TV_STD_PAL; - DRM_INFO("Default TV standard: PAL\n"); - break; - case ATOM_TV_PALM: - tv_std = TV_STD_PAL_M; - DRM_INFO("Default TV standard: PAL-M\n"); - break; - case ATOM_TV_PALN: - tv_std = TV_STD_PAL_N; - DRM_INFO("Default TV standard: PAL-N\n"); - break; - case ATOM_TV_PALCN: - tv_std = TV_STD_PAL_CN; - DRM_INFO("Default TV standard: PAL-CN\n"); - break; - case ATOM_TV_PAL60: - tv_std = TV_STD_PAL_60; - DRM_INFO("Default TV standard: PAL-60\n"); - break; - case ATOM_TV_SECAM: - tv_std = TV_STD_SECAM; - DRM_INFO("Default TV standard: SECAM\n"); - break; - default: - tv_std = TV_STD_NTSC; - DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); - break; + switch (tv_info->ucTV_BootUpDefaultStandard) { + case ATOM_TV_NTSC: + tv_std = TV_STD_NTSC; + DRM_INFO("Default TV standard: NTSC\n"); + break; + case ATOM_TV_NTSCJ: + tv_std = TV_STD_NTSC_J; + DRM_INFO("Default TV standard: NTSC-J\n"); + break; + case ATOM_TV_PAL: + tv_std = TV_STD_PAL; + DRM_INFO("Default TV standard: PAL\n"); + break; + case ATOM_TV_PALM: + tv_std = TV_STD_PAL_M; + DRM_INFO("Default TV standard: PAL-M\n"); + break; + case ATOM_TV_PALN: + tv_std = TV_STD_PAL_N; + DRM_INFO("Default TV standard: PAL-N\n"); + break; + case ATOM_TV_PALCN: + tv_std = TV_STD_PAL_CN; + DRM_INFO("Default TV standard: PAL-CN\n"); + break; + case ATOM_TV_PAL60: + tv_std = TV_STD_PAL_60; + DRM_INFO("Default TV standard: PAL-60\n"); + break; + case ATOM_TV_SECAM: + tv_std = TV_STD_SECAM; + DRM_INFO("Default TV standard: SECAM\n"); + break; + default: + tv_std = TV_STD_NTSC; + DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); + break; + } } return tv_std; } @@ -1407,11 +1407,12 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) uint8_t bg, dac; 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); if (!tv_dac) @@ -1479,13 +1480,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) int state_index = 0, mode_index = 0; 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; - 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) { /* add the i2c bus for thermal/fan chip */ if (power_info->info.ucOverdriveThermalController > 0) { diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d65931d2e77..eca714c381d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -368,10 +368,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev) if (rdev->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); - else - ret = radeon_get_atom_connector_info_from_supported_devices_table(dev); } else { ret = radeon_get_legacy_connector_info_from_bios(dev); if (ret == false) diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index a236c75496c..fd4052f71bf 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -519,7 +519,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) 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) { case 1: @@ -725,7 +726,8 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) } 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.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 } } - 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; if (action == ATOM_TRANSMITTER_ACTION_INIT) { @@ -1103,7 +1106,8 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) 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) { case 1: @@ -1411,7 +1415,8 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn 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; diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index e356935b028..f758d5cc116 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -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) { int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); - struct _ATOM_INTEGRATED_SYSTEM_INFO *info; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2; - void *ptr; + union igp_info *info; uint16_t data_offset; uint8_t frev, crev; fixed20_12 tmp; - atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, - &frev, &crev, &data_offset); - ptr = 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 */ - switch (crev) { - case 1: - tmp.full = rfixed_const(100); - 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_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock)); - rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock)); - rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth); - break; - case 2: - tmp.full = rfixed_const(100); - 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_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_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_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth)); - break; - default: + if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, + &frev, &crev, &data_offset)) { + info = (union igp_info *)(rdev->mode_info.atom_context->bios + data_offset); + + /* Get various system informations from bios */ + switch (crev) { + case 1: + tmp.full = rfixed_const(100); + 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_system_mclk.full = rfixed_const(le16_to_cpu(info->info.usK8MemoryClock)); + 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->info.ucHTLinkWidth); + break; + case 2: + tmp.full = rfixed_const(100); + 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_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_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_width.full = rfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth)); + break; + 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); /* We assume the slower possible clock ie worst case */ /* DDR 333Mhz */ @@ -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_width.full = rfixed_const(8); DRM_ERROR("No integrated system info for your GPU, using safe default\n"); - break; } /* Compute various bandwidth */ /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */ -- cgit v1.2.3-70-g09d2 From d9c9fe3622d15e7e84121ffedef60f4080ab4f03 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 29 Mar 2010 17:39:44 -0400 Subject: drm/radeon/kms/atom: minor fixes to transmitter setup - 8 lane links are not valid for DP - remove unused num var Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 54 +++++++++++++------------------- 1 file changed, 21 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index fd4052f71bf..6f334519a06 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -708,7 +708,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) struct radeon_connector_atom_dig *dig_connector = radeon_get_atom_connector_priv_from_encoder(encoder); union dig_encoder_control args; - int index = 0, num = 0; + int index = 0; uint8_t frev, crev; if (!dig || !dig_connector) @@ -724,7 +724,6 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) else index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); } - num = dig->dig_encoder + 1; if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) return; @@ -786,7 +785,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t struct drm_connector *connector; struct radeon_connector *radeon_connector; union dig_transmitter_control args; - int index = 0, num = 0; + int index = 0; uint8_t frev, crev; bool is_dp = false; int pll_id = 0; @@ -862,15 +861,12 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: args.v3.acConfig.ucTransmitterSel = 0; - num = 0; break; case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: args.v3.acConfig.ucTransmitterSel = 1; - num = 1; break; case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: args.v3.acConfig.ucTransmitterSel = 2; - num = 2; break; } @@ -881,23 +877,19 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t args.v3.acConfig.fCoherentMode = 1; } } else if (ASIC_IS_DCE32(rdev)) { - if (dig->dig_encoder == 1) - args.v2.acConfig.ucEncoderSel = 1; + args.v2.acConfig.ucEncoderSel = dig->dig_encoder; if (dig_connector->linkb) args.v2.acConfig.ucLinkSel = 1; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: args.v2.acConfig.ucTransmitterSel = 0; - num = 0; break; case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: args.v2.acConfig.ucTransmitterSel = 1; - num = 1; break; case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: args.v2.acConfig.ucTransmitterSel = 2; - num = 2; break; } @@ -915,31 +907,25 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t else args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - if (rdev->flags & RADEON_IS_IGP) { - if (radeon_encoder->pixel_clock > 165000) { - if (dig_connector->igp_lane_info & 0x3) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; - else if (dig_connector->igp_lane_info & 0xc) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; - } else { - if (dig_connector->igp_lane_info & 0x1) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; - else if (dig_connector->igp_lane_info & 0x2) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; - else if (dig_connector->igp_lane_info & 0x4) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; - else if (dig_connector->igp_lane_info & 0x8) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; - } + if ((rdev->flags & RADEON_IS_IGP) && + (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { + if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { + if (dig_connector->igp_lane_info & 0x1) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; + else if (dig_connector->igp_lane_info & 0x2) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; + else if (dig_connector->igp_lane_info & 0x4) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; + else if (dig_connector->igp_lane_info & 0x8) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; + } else { + if (dig_connector->igp_lane_info & 0x3) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; + else if (dig_connector->igp_lane_info & 0xc) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; } - break; } - if (radeon_encoder->pixel_clock > 165000) - args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; - if (dig_connector->linkb) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; else @@ -950,6 +936,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; + if (radeon_encoder->pixel_clock > 165000) + args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; } } -- cgit v1.2.3-70-g09d2 From 9f998ad7e92a1653b6b396b1278e75560a8be519 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 29 Mar 2010 21:37:08 -0400 Subject: drm/radeon/kms: minor fixes for eDP with LCD* device tags (v2) Some systems have LCD* rather than DFP* device tags in the bios for eDP connectors; notably the new apple iMac. This fixes things up so eDP connectors with either tag will work. v2: fix typo Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 13 +++++++++---- drivers/gpu/drm/radeon/radeon_encoders.c | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 56107b3a997..fd4ef6d1884 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -581,11 +581,16 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, } } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { /* may want to enable SS on DP/eDP eventually */ - args.v3.sInput.ucDispPllConfig |= - DISPPLL_CONFIG_SS_ENABLE; - if (mode->clock > 165000) + /*args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_SS_ENABLE;*/ + if (encoder_mode == ATOM_ENCODER_MODE_DP) args.v3.sInput.ucDispPllConfig |= - DISPPLL_CONFIG_DUAL_LINK; + DISPPLL_CONFIG_COHERENT_MODE; + else { + if (mode->clock > 165000) + args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_DUAL_LINK; + } } atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 6f334519a06..cbc6fa20cf5 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -302,7 +302,7 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, } if (ASIC_IS_DCE3(rdev) && - (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) { + (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); radeon_dp_set_link_config(connector, mode); } -- cgit v1.2.3-70-g09d2 From fb668c2fed628179c7aa409a0de39a2b96bed18c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 31 Mar 2010 14:42:11 -0400 Subject: drm/radeon/kms/evergreen: get DP working Need to enable the VID stream after link training Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index cbc6fa20cf5..52d6f96f274 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1044,16 +1044,25 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) if (is_dig) { switch (mode) { case DRM_MODE_DPMS_ON: - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); - { + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + dp_link_train(encoder, connector); + if (ASIC_IS_DCE4(rdev)) + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON); } + if (!ASIC_IS_DCE4(rdev)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + if (!ASIC_IS_DCE4(rdev)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { + if (ASIC_IS_DCE4(rdev)) + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF); + } break; } } else { -- cgit v1.2.3-70-g09d2 From affd858907aae7bf7d7d7fa02ff19f35de2ff1d8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 6 Apr 2010 01:22:41 -0400 Subject: drm/radeon/kms: clean up atom dac handling - make sure legacy dac1 has an enc priv - remove unused num var - no need for extra tv_dac var in atom dac functions Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_encoders.c') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 52d6f96f274..c52fc3080b6 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -317,12 +317,8 @@ atombios_dac_setup(struct drm_encoder *encoder, int action) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); DAC_ENCODER_CONTROL_PS_ALLOCATION args; - int index = 0, num = 0; + int index = 0; struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; - enum radeon_tv_std tv_std = TV_STD_NTSC; - - if (dac_info->tv_std) - tv_std = dac_info->tv_std; memset(&args, 0, sizeof(args)); @@ -330,12 +326,10 @@ atombios_dac_setup(struct drm_encoder *encoder, int action) case ENCODER_OBJECT_ID_INTERNAL_DAC1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); - num = 1; break; case ENCODER_OBJECT_ID_INTERNAL_DAC2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); - num = 2; break; } @@ -346,7 +340,7 @@ atombios_dac_setup(struct drm_encoder *encoder, int action) else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) args.ucDacStandard = ATOM_DAC1_CV; else { - switch (tv_std) { + switch (dac_info->tv_std) { case TV_STD_PAL: case TV_STD_PAL_M: case TV_STD_SCART_PAL: @@ -377,10 +371,6 @@ atombios_tv_setup(struct drm_encoder *encoder, int action) TV_ENCODER_CONTROL_PS_ALLOCATION args; int index = 0; struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; - enum radeon_tv_std tv_std = TV_STD_NTSC; - - if (dac_info->tv_std) - tv_std = dac_info->tv_std; memset(&args, 0, sizeof(args)); @@ -391,7 +381,7 @@ atombios_tv_setup(struct drm_encoder *encoder, int action) if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) args.sTVEncoder.ucTvStandard = ATOM_TV_CV; else { - switch (tv_std) { + switch (dac_info->tv_std) { case TV_STD_NTSC: args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; break; @@ -1558,12 +1548,14 @@ static const struct drm_encoder_funcs radeon_atom_enc_funcs = { struct radeon_encoder_atom_dac * radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) { + struct drm_device *dev = radeon_encoder->base.dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL); if (!dac) return NULL; - dac->tv_std = TV_STD_NTSC; + dac->tv_std = radeon_atombios_get_tv_info(rdev); return dac; } @@ -1641,6 +1633,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su break; case ENCODER_OBJECT_ID_INTERNAL_DAC1: drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); + radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); break; case ENCODER_OBJECT_ID_INTERNAL_DAC2: -- cgit v1.2.3-70-g09d2