24,8 → 24,8 |
* Authors: Dave Airlie |
* Alex Deucher |
*/ |
#include "drmP.h" |
#include "radeon_drm.h" |
#include <drm/drmP.h> |
#include <drm/radeon_drm.h> |
#include "radeon.h" |
#include "atom.h" |
|
620,8 → 620,8 |
i2c.y_data_mask = 0x80; |
} else { |
/* default masks for ddc pads */ |
i2c.mask_clk_mask = RADEON_GPIO_EN_1; |
i2c.mask_data_mask = RADEON_GPIO_EN_0; |
i2c.mask_clk_mask = RADEON_GPIO_MASK_1; |
i2c.mask_data_mask = RADEON_GPIO_MASK_0; |
i2c.a_clk_mask = RADEON_GPIO_A_1; |
i2c.a_data_mask = RADEON_GPIO_A_0; |
i2c.en_clk_mask = RADEON_GPIO_EN_1; |
719,6 → 719,34 |
return i2c; |
} |
|
static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct radeon_device *rdev) |
{ |
struct drm_device *dev = rdev->ddev; |
struct radeon_i2c_bus_rec i2c; |
u16 offset; |
u8 id, blocks, clk, data; |
int i; |
|
i2c.valid = false; |
|
offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); |
if (offset) { |
blocks = RBIOS8(offset + 2); |
for (i = 0; i < blocks; i++) { |
id = RBIOS8(offset + 3 + (i * 5) + 0); |
if (id == 136) { |
clk = RBIOS8(offset + 3 + (i * 5) + 3); |
data = RBIOS8(offset + 3 + (i * 5) + 4); |
/* gpiopad */ |
i2c = combios_setup_i2c_bus(rdev, DDC_MONID, |
(1 << clk), (1 << data)); |
break; |
} |
} |
} |
return i2c; |
} |
|
void radeon_combios_i2c_init(struct radeon_device *rdev) |
{ |
struct drm_device *dev = rdev->ddev; |
755,30 → 783,14 |
} else if (rdev->family == CHIP_RS300 || |
rdev->family == CHIP_RS400 || |
rdev->family == CHIP_RS480) { |
u16 offset; |
u8 id, blocks, clk, data; |
int i; |
|
/* 0x68 */ |
i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); |
rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); |
|
offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); |
if (offset) { |
blocks = RBIOS8(offset + 2); |
for (i = 0; i < blocks; i++) { |
id = RBIOS8(offset + 3 + (i * 5) + 0); |
if (id == 136) { |
clk = RBIOS8(offset + 3 + (i * 5) + 3); |
data = RBIOS8(offset + 3 + (i * 5) + 4); |
/* gpiopad */ |
i2c = combios_setup_i2c_bus(rdev, DDC_MONID, |
(1 << clk), (1 << data)); |
i2c = radeon_combios_get_i2c_info_from_table(rdev); |
if (i2c.valid) |
rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); |
break; |
} |
} |
} |
} else if ((rdev->family == CHIP_R200) || |
(rdev->family >= CHIP_R300)) { |
/* 0x68 */ |
1561,6 → 1573,11 |
(rdev->pdev->subsystem_device == 0x4150)) { |
/* Mac G5 tower 9600 */ |
rdev->mode_info.connector_table = CT_MAC_G5_9600; |
} else if ((rdev->pdev->device == 0x4c66) && |
(rdev->pdev->subsystem_vendor == 0x1002) && |
(rdev->pdev->subsystem_device == 0x4c66)) { |
/* SAM440ep RV250 embedded board */ |
rdev->mode_info.connector_table = CT_SAM440EP; |
} else |
#endif /* CONFIG_PPC_PMAC */ |
#ifdef CONFIG_PPC64 |
2134,6 → 2151,67 |
CONNECTOR_OBJECT_ID_SVIDEO, |
&hpd); |
break; |
case CT_SAM440EP: |
DRM_INFO("Connector Table: %d (SAM440ep embedded board)\n", |
rdev->mode_info.connector_table); |
/* LVDS */ |
ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0); |
hpd.hpd = RADEON_HPD_NONE; |
radeon_add_legacy_encoder(dev, |
radeon_get_encoder_enum(dev, |
ATOM_DEVICE_LCD1_SUPPORT, |
0), |
ATOM_DEVICE_LCD1_SUPPORT); |
radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, |
DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, |
CONNECTOR_OBJECT_ID_LVDS, |
&hpd); |
/* DVI-I - secondary dac, int tmds */ |
ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); |
hpd.hpd = RADEON_HPD_1; /* ??? */ |
radeon_add_legacy_encoder(dev, |
radeon_get_encoder_enum(dev, |
ATOM_DEVICE_DFP1_SUPPORT, |
0), |
ATOM_DEVICE_DFP1_SUPPORT); |
radeon_add_legacy_encoder(dev, |
radeon_get_encoder_enum(dev, |
ATOM_DEVICE_CRT2_SUPPORT, |
2), |
ATOM_DEVICE_CRT2_SUPPORT); |
radeon_add_legacy_connector(dev, 1, |
ATOM_DEVICE_DFP1_SUPPORT | |
ATOM_DEVICE_CRT2_SUPPORT, |
DRM_MODE_CONNECTOR_DVII, &ddc_i2c, |
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, |
&hpd); |
/* VGA - primary dac */ |
ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); |
hpd.hpd = RADEON_HPD_NONE; |
radeon_add_legacy_encoder(dev, |
radeon_get_encoder_enum(dev, |
ATOM_DEVICE_CRT1_SUPPORT, |
1), |
ATOM_DEVICE_CRT1_SUPPORT); |
radeon_add_legacy_connector(dev, 2, |
ATOM_DEVICE_CRT1_SUPPORT, |
DRM_MODE_CONNECTOR_VGA, &ddc_i2c, |
CONNECTOR_OBJECT_ID_VGA, |
&hpd); |
/* TV - TV DAC */ |
ddc_i2c.valid = false; |
hpd.hpd = RADEON_HPD_NONE; |
radeon_add_legacy_encoder(dev, |
radeon_get_encoder_enum(dev, |
ATOM_DEVICE_TV1_SUPPORT, |
2), |
ATOM_DEVICE_TV1_SUPPORT); |
radeon_add_legacy_connector(dev, 3, ATOM_DEVICE_TV1_SUPPORT, |
DRM_MODE_CONNECTOR_SVIDEO, |
&ddc_i2c, |
CONNECTOR_OBJECT_ID_SVIDEO, |
&hpd); |
break; |
default: |
DRM_INFO("Connector table: %d (invalid)\n", |
rdev->mode_info.connector_table); |
2255,6 → 2333,9 |
connector = (tmp >> 12) & 0xf; |
|
ddc_type = (tmp >> 8) & 0xf; |
if (ddc_type == 5) |
ddc_i2c = radeon_combios_get_i2c_info_from_table(rdev); |
else |
ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); |
|
switch (connector) { |
2563,15 → 2644,18 |
|
/* allocate 2 power states */ |
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL); |
if (!rdev->pm.power_state) { |
rdev->pm.default_power_state_index = state_index; |
rdev->pm.num_power_states = 0; |
if (rdev->pm.power_state) { |
/* allocate 1 clock mode per state */ |
rdev->pm.power_state[0].clock_info = |
kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); |
rdev->pm.power_state[1].clock_info = |
kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL); |
if (!rdev->pm.power_state[0].clock_info || |
!rdev->pm.power_state[1].clock_info) |
goto pm_failed; |
} else |
goto pm_failed; |
|
rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; |
rdev->pm.current_clock_mode_index = 0; |
return; |
} |
|
/* check for a thermal chip */ |
offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE); |
if (offset) { |
2617,7 → 2701,26 |
i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); |
} |
} |
} else { |
/* boards with a thermal chip, but no overdrive table */ |
|
/* Asus 9600xt has an f75375 on the monid bus */ |
if ((dev->pdev->device == 0x4152) && |
(dev->pdev->subsystem_vendor == 0x1043) && |
(dev->pdev->subsystem_device == 0xc002)) { |
i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); |
rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
if (rdev->pm.i2c_bus) { |
struct i2c_board_info info = { }; |
const char *name = "f75375"; |
info.addr = 0x28; |
strlcpy(info.type, name, sizeof(info.type)); |
i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); |
DRM_INFO("Possible %s thermal controller at 0x%02x\n", |
name, info.addr); |
} |
} |
} |
|
if (rdev->flags & RADEON_IS_MOBILITY) { |
offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE); |
2716,6 → 2819,14 |
|
rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; |
rdev->pm.current_clock_mode_index = 0; |
return; |
|
pm_failed: |
rdev->pm.default_power_state_index = state_index; |
rdev->pm.num_power_states = 0; |
|
rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; |
rdev->pm.current_clock_mode_index = 0; |
} |
|
void radeon_external_tmds_setup(struct drm_encoder *encoder) |
2815,7 → 2926,7 |
case 4: |
val = RBIOS16(index); |
index += 2; |
udelay(val * 1000); |
mdelay(val); |
break; |
case 6: |
slave_addr = id & 0xff; |
3014,7 → 3125,7 |
udelay(150); |
break; |
case 2: |
udelay(1000); |
mdelay(1); |
break; |
case 3: |
while (tmp--) { |
3045,13 → 3156,13 |
/*mclk_cntl |= 0x00001111;*//* ??? */ |
WREG32_PLL(RADEON_MCLK_CNTL, |
mclk_cntl); |
udelay(10000); |
mdelay(10); |
#endif |
WREG32_PLL |
(RADEON_CLK_PWRMGT_CNTL, |
tmp & |
~RADEON_CG_NO1_DEBUG_0); |
udelay(10000); |
mdelay(10); |
} |
break; |
default: |
3208,15 → 3319,6 |
WREG32(RADEON_CONFIG_MEMSIZE, mem_size); |
} |
|
void radeon_combios_dyn_clk_setup(struct drm_device *dev, int enable) |
{ |
uint16_t dyn_clk_info = |
combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); |
|
if (dyn_clk_info) |
combios_parse_pll_table(dev, dyn_clk_info); |
} |
|
void radeon_combios_asic_init(struct drm_device *dev) |
{ |
struct radeon_device *rdev = dev->dev_private; |
3279,6 → 3381,14 |
rdev->pdev->subsystem_device == 0x30a4) |
return; |
|
/* quirk for rs4xx Compaq Presario V5245EU laptop to make it resume |
* - it hangs on resume inside the dynclk 1 table. |
*/ |
if (rdev->family == CHIP_RS480 && |
rdev->pdev->subsystem_vendor == 0x103c && |
rdev->pdev->subsystem_device == 0x30ae) |
return; |
|
/* DYN CLK 1 */ |
table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); |
if (table) |