diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-04 18:49:37 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-04 18:49:37 +0300 |
commit | 03a2c4d76c9e99b80d74ab8a4f344e135a5ae44b (patch) | |
tree | 7fd7940a4f87dc1ace1c1bdeb1fb0d90ac3beb13 /drivers/gpu/drm/radeon/radeon_combios.c | |
parent | a27341cd5fcb7cf2d2d4726e9f324009f7162c00 (diff) | |
parent | d424b925f7092b9d95e0a8556872349abe79d9b6 (diff) | |
download | linux-03a2c4d76c9e99b80d74ab8a4f344e135a5ae44b.tar.xz |
Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (151 commits)
vga_switcheroo: disable default y by new rules.
drm/nouveau: fix *staging* driver build with switcheroo off.
drm/radeon: fix typo in Makefile
vga_switcheroo: fix build on platforms with no ACPI
drm/radeon: Fix printf type warning in 64bit system.
drm/radeon/kms: bump the KMS version number for square tiling support.
vga_switcheroo: initial implementation (v15)
drm/radeon/kms: do not disable audio engine twice
Revert "drm/radeon/kms: disable HDMI audio for now on rv710/rv730"
drm/radeon/kms: do not preset audio stuff and start timer when not using audio
drm/radeon: r100/r200 ums: block ability for userspace app to trash 0 page and beyond
drm/ttm: fix function prototype to match implementation
drm/radeon: use ALIGN instead of open coding it
drm/radeon/kms: initialize set_surface_reg reg for rs600 asic
drm/i915: Use a dmi quirk to skip a broken SDVO TV output.
drm/i915: enable/disable LVDS port at DPMS time
drm/i915: check for multiple write domains in pin_and_relocate
drm/i915: clean-up i915_gem_flush_gpu_write_domain
drm/i915: reuse i915_gpu_idle helper
drm/i915: ensure lru ordering of fence_list
...
Fixed trivial conflicts in drivers/gpu/vga/Kconfig
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_combios.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_combios.c | 290 |
1 files changed, 231 insertions, 59 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 22d476160d52..e9ea38ece375 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -150,6 +150,9 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, int rev; uint16_t offset = 0, check_offset; + if (!rdev->bios) + return 0; + switch (table) { /* absolute offset tables */ case COMBIOS_ASIC_INIT_1_TABLE: @@ -443,6 +446,39 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, } +bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev) +{ + int edid_info; + struct edid *edid; + edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE); + if (!edid_info) + return false; + + edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1), + GFP_KERNEL); + if (edid == NULL) + return false; + + memcpy((unsigned char *)edid, + (unsigned char *)(rdev->bios + edid_info), EDID_LENGTH); + + if (!drm_edid_is_valid(edid)) { + kfree(edid); + return false; + } + + rdev->mode_info.bios_hardcoded_edid = edid; + return true; +} + +struct edid * +radeon_combios_get_hardcoded_edid(struct radeon_device *rdev) +{ + if (rdev->mode_info.bios_hardcoded_edid) + return rdev->mode_info.bios_hardcoded_edid; + return NULL; +} + static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, int ddc_line) { @@ -486,9 +522,65 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde i2c.y_data_reg = ddc_line; } - if (rdev->family < CHIP_R200) - i2c.hw_capable = false; - else { + switch (rdev->family) { + case CHIP_R100: + case CHIP_RV100: + case CHIP_RS100: + case CHIP_RV200: + case CHIP_RS200: + case CHIP_RS300: + switch (ddc_line) { + case RADEON_GPIO_DVI_DDC: + /* in theory this should be hw capable, + * but it doesn't seem to work + */ + i2c.hw_capable = false; + break; + default: + i2c.hw_capable = false; + break; + } + break; + case CHIP_R200: + switch (ddc_line) { + case RADEON_GPIO_DVI_DDC: + case RADEON_GPIO_MONID: + i2c.hw_capable = true; + break; + default: + i2c.hw_capable = false; + break; + } + break; + case CHIP_RV250: + case CHIP_RV280: + switch (ddc_line) { + case RADEON_GPIO_VGA_DDC: + case RADEON_GPIO_DVI_DDC: + case RADEON_GPIO_CRT2_DDC: + i2c.hw_capable = true; + break; + default: + i2c.hw_capable = false; + break; + } + break; + case CHIP_R300: + case CHIP_R350: + switch (ddc_line) { + case RADEON_GPIO_VGA_DDC: + case RADEON_GPIO_DVI_DDC: + i2c.hw_capable = true; + break; + default: + i2c.hw_capable = false; + break; + } + break; + case CHIP_RV350: + case CHIP_RV380: + case CHIP_RS400: + case CHIP_RS480: switch (ddc_line) { case RADEON_GPIO_VGA_DDC: case RADEON_GPIO_DVI_DDC: @@ -504,9 +596,14 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde i2c.hw_capable = false; break; } + break; + default: + i2c.hw_capable = false; + break; } i2c.mm_i2c = false; i2c.i2c_id = 0; + i2c.hpd_id = 0; if (ddc_line) i2c.valid = true; @@ -527,9 +624,6 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) int8_t rev; uint16_t sclk, mclk; - if (rdev->bios == NULL) - return false; - pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE); if (pll_info) { rev = RBIOS8(pll_info); @@ -654,9 +748,6 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct if (!p_dac) return NULL; - if (rdev->bios == NULL) - goto out; - /* check CRT table */ dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); if (dac_info) { @@ -673,7 +764,6 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct found = 1; } -out: if (!found) /* fallback to defaults */ radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac); @@ -687,9 +777,6 @@ radeon_combios_get_tv_info(struct radeon_device *rdev) uint16_t tv_info; enum radeon_tv_std tv_std = TV_STD_NTSC; - if (rdev->bios == NULL) - return tv_std; - tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); if (tv_info) { if (RBIOS8(tv_info + 6) == 'T') { @@ -793,9 +880,6 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct if (!tv_dac) return NULL; - if (rdev->bios == NULL) - goto out; - /* first check TV table */ dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); if (dac_info) { @@ -857,7 +941,6 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct } } -out: if (!found) /* fallback to defaults */ radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac); @@ -945,11 +1028,6 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder int tmp, i; struct radeon_encoder_lvds *lvds = NULL; - if (rdev->bios == NULL) { - lvds = radeon_legacy_get_lvds_info_from_regs(rdev); - goto out; - } - lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE); if (lcd_info) { @@ -1050,7 +1128,7 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder DRM_INFO("No panel info found in BIOS\n"); lvds = radeon_legacy_get_lvds_info_from_regs(rdev); } -out: + if (lvds) encoder->native_mode = lvds->native_mode; return lvds; @@ -1102,9 +1180,6 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, int i, n; uint8_t ver; - if (rdev->bios == NULL) - return false; - tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); if (tmds_info) { @@ -1184,9 +1259,6 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder enum radeon_combios_ddc gpio; struct radeon_i2c_bus_rec i2c_bus; - if (rdev->bios == NULL) - return false; - tmds->i2c_bus = NULL; if (rdev->flags & RADEON_IS_IGP) { offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); @@ -1253,7 +1325,10 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); break; case DDC_LCD: /* MM i2c */ - DRM_ERROR("MM i2c requires hw i2c engine\n"); + i2c_bus.valid = true; + i2c_bus.hw_capable = true; + i2c_bus.mm_i2c = true; + tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); break; default: DRM_ERROR("Unsupported gpio %d\n", gpio); @@ -1909,9 +1984,6 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) struct radeon_i2c_bus_rec ddc_i2c; struct radeon_hpd hpd; - if (rdev->bios == NULL) - return false; - conn_info = combios_get_table_offset(dev, COMBIOS_CONNECTOR_INFO_TABLE); if (conn_info) { for (i = 0; i < 4; i++) { @@ -2278,6 +2350,115 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) return true; } +void radeon_combios_get_power_modes(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + u16 offset, misc, misc2 = 0; + u8 rev, blocks, tmp; + int state_index = 0; + + rdev->pm.default_power_state = NULL; + + if (rdev->flags & RADEON_IS_MOBILITY) { + offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE); + if (offset) { + rev = RBIOS8(offset); + blocks = RBIOS8(offset + 0x2); + /* power mode 0 tends to be the only valid one */ + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = RBIOS32(offset + 0x5 + 0x2); + rdev->pm.power_state[state_index].clock_info[0].sclk = RBIOS32(offset + 0x5 + 0x6); + if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) + goto default_mode; + /* skip overclock modes for now */ + if ((rdev->pm.power_state[state_index].clock_info[0].mclk > + rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) || + (rdev->pm.power_state[state_index].clock_info[0].sclk > + rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN)) + goto default_mode; + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BATTERY; + misc = RBIOS16(offset + 0x5 + 0x0); + if (rev > 4) + misc2 = RBIOS16(offset + 0x5 + 0xe); + if (misc & 0x4) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO; + if (misc & 0x8) + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + true; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + false; + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = true; + if (rev < 6) { + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg = + RBIOS16(offset + 0x5 + 0xb) * 4; + tmp = RBIOS8(offset + 0x5 + 0xd); + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp); + } else { + u8 entries = RBIOS8(offset + 0x5 + 0xb); + u16 voltage_table_offset = RBIOS16(offset + 0x5 + 0xc); + if (entries && voltage_table_offset) { + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg = + RBIOS16(voltage_table_offset) * 4; + tmp = RBIOS8(voltage_table_offset + 0x2); + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp); + } else + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = false; + } + switch ((misc2 & 0x700) >> 8) { + case 0: + default: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 0; + break; + case 1: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 33; + break; + case 2: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 66; + break; + case 3: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 99; + break; + case 4: + rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 132; + break; + } + } else + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + if (rev > 6) + rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = + RBIOS8(offset + 0x5 + 0x10); + state_index++; + } else { + /* XXX figure out some good default low power mode for mobility cards w/out power tables */ + } + } else { + /* XXX figure out some good default low power mode for desktop cards */ + } + +default_mode: + /* add the default mode */ + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; + rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0]; + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + if (rdev->asic->get_pcie_lanes) + rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev); + else + rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16; + rdev->pm.default_power_state = &rdev->pm.power_state[state_index]; + rdev->pm.num_power_states = state_index + 1; + + rdev->pm.current_power_state = rdev->pm.default_power_state; + rdev->pm.current_clock_mode = + rdev->pm.default_power_state->default_clock_mode; +} + void radeon_external_tmds_setup(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -2289,23 +2470,21 @@ void radeon_external_tmds_setup(struct drm_encoder *encoder) switch (tmds->dvo_chip) { case DVO_SIL164: /* sil 164 */ - radeon_i2c_do_lock(tmds->i2c_bus, 1); - radeon_i2c_sw_put_byte(tmds->i2c_bus, - tmds->slave_addr, - 0x08, 0x30); - radeon_i2c_sw_put_byte(tmds->i2c_bus, + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x08, 0x30); + radeon_i2c_put_byte(tmds->i2c_bus, tmds->slave_addr, 0x09, 0x00); - radeon_i2c_sw_put_byte(tmds->i2c_bus, - tmds->slave_addr, - 0x0a, 0x90); - radeon_i2c_sw_put_byte(tmds->i2c_bus, - tmds->slave_addr, - 0x0c, 0x89); - radeon_i2c_sw_put_byte(tmds->i2c_bus, + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x0a, 0x90); + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + 0x0c, 0x89); + radeon_i2c_put_byte(tmds->i2c_bus, tmds->slave_addr, 0x08, 0x3b); - radeon_i2c_do_lock(tmds->i2c_bus, 0); break; case DVO_SIL1178: /* sil 1178 - untested */ @@ -2338,9 +2517,6 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder) uint32_t reg, val, and_mask, or_mask; struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; - if (rdev->bios == NULL) - return false; - if (!tmds) return false; @@ -2390,11 +2566,9 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder) index++; val = RBIOS8(index); index++; - radeon_i2c_do_lock(tmds->i2c_bus, 1); - radeon_i2c_sw_put_byte(tmds->i2c_bus, - slave_addr, - reg, val); - radeon_i2c_do_lock(tmds->i2c_bus, 0); + radeon_i2c_put_byte(tmds->i2c_bus, + slave_addr, + reg, val); break; default: DRM_ERROR("Unknown id %d\n", id >> 13); @@ -2447,11 +2621,9 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder) reg = id & 0x1fff; val = RBIOS8(index); index += 1; - radeon_i2c_do_lock(tmds->i2c_bus, 1); - radeon_i2c_sw_put_byte(tmds->i2c_bus, - tmds->slave_addr, - reg, val); - radeon_i2c_do_lock(tmds->i2c_bus, 0); + radeon_i2c_put_byte(tmds->i2c_bus, + tmds->slave_addr, + reg, val); break; default: DRM_ERROR("Unknown id %d\n", id >> 13); |