Previously we added i2c buses as needed when enumerating connectors power management, etc. This only exposed the actual buses used and could have lead to the same buse getting created more than once if one buses was used for more than one purpose. This patch sets up all i2c buses on the card in one place and users of the buses just point back to the one instance.
Signed-off-by: Alex Deucher alexdeucher@gmail.com --- drivers/gpu/drm/radeon/radeon.h | 2 + drivers/gpu/drm/radeon/radeon_atombios.c | 67 +++++++++++++++++++++++- drivers/gpu/drm/radeon/radeon_combios.c | 77 +++++++++++++++++++++++++--- drivers/gpu/drm/radeon/radeon_connectors.c | 31 ++++-------- drivers/gpu/drm/radeon/radeon_display.c | 5 ++ drivers/gpu/drm/radeon/radeon_i2c.c | 53 +++++++++++++++++++ drivers/gpu/drm/radeon/radeon_mode.h | 11 ++++ 7 files changed, 214 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 368fecf..fed3d07 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1100,6 +1100,8 @@ struct radeon_device { struct notifier_block acpi_nb; /* only one userspace can use Hyperz features at a time */ struct drm_file *hyperz_filp; + /* i2c buses */ + struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS]; };
int radeon_device_init(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 2b9a516..7851008 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -114,7 +114,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
i2c.i2c_id = gpio->sucI2cId.ucAccess;
- i2c.valid = true; + if (i2c.mask_clk_reg) + i2c.valid = true; break; } } @@ -123,6 +124,66 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev return i2c; }
+void radeon_atombios_i2c_init(struct radeon_device *rdev) +{ + struct atom_context *ctx = rdev->mode_info.atom_context; + ATOM_GPIO_I2C_ASSIGMENT *gpio; + struct radeon_i2c_bus_rec i2c; + int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); + struct _ATOM_GPIO_I2C_INFO *i2c_info; + uint16_t data_offset, size; + int i, num_indices; + char stmp[32]; + + memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); + + if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { + i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); + + num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_GPIO_I2C_ASSIGMENT); + + for (i = 0; i < num_indices; i++) { + gpio = &i2c_info->asGPIO_Info[i]; + i2c.valid = false; + 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; + + if (i2c.mask_clk_reg) { + i2c.valid = true; + sprintf(stmp, "0x%x", i2c.i2c_id); + rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp); + } + } + } +} + static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev, u8 id) { @@ -1531,7 +1592,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) thermal_controller_names[power_info->info.ucOverdriveThermalController], power_info->info.ucOverdriveControllerAddress >> 1); i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); - rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal"); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); if (rdev->pm.i2c_bus) { struct i2c_board_info info = { }; const char *name = thermal_controller_names[power_info->info. @@ -1824,7 +1885,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); - rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal"); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); if (rdev->pm.i2c_bus) { struct i2c_board_info info = { }; const char *name = pp_lib_thermal_controller_names[controller->ucType]; diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 5e1474c..18c84cf 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -479,6 +479,17 @@ radeon_combios_get_hardcoded_edid(struct radeon_device *rdev) return NULL; }
+/* standard i2c gpio lines */ +#define RADEON_I2C_MONID_ID 0 +#define RADEON_I2C_DVI_ID 1 +#define RADEON_I2C_VGA_ID 2 +#define RADEON_I2C_CRT2_ID 3 +#define RADEON_I2C_MM_ID 4 +/* custom defined gpio lines */ +#define RADEON_I2C_LCD_ID 5 /* ddc for laptop panels */ +#define RADEON_I2C_GPIO_ID 6 /* rs4xx gpio ddc */ +#define RADEON_I2C_DVO_ID 7 /* i2c bus for dvo */ + static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, int ddc_line) { @@ -599,7 +610,24 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde break; } i2c.mm_i2c = false; - i2c.i2c_id = 0; + + switch (ddc_line) { + case RADEON_GPIO_MONID: + i2c.i2c_id = RADEON_I2C_MONID_ID; + break; + case RADEON_GPIO_DVI_DDC: + i2c.i2c_id = RADEON_I2C_DVI_ID; + break; + case RADEON_GPIO_VGA_DDC: + i2c.i2c_id = RADEON_I2C_VGA_ID; + break; + case RADEON_GPIO_CRT2_DDC: + i2c.i2c_id = RADEON_I2C_CRT2_ID; + break; + default: + i2c.i2c_id = 0xff; + break; + } i2c.hpd = RADEON_HPD_NONE;
if (ddc_line) @@ -610,6 +638,30 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde return i2c; }
+void radeon_combios_i2c_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct radeon_i2c_bus_rec i2c; + + i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); + rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "MONID"); + + i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "DVI_DDC"); + + i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "VGA_DDC"); + + i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "CRT2_DDC"); + + i2c.valid = true; + i2c.hw_capable = true; + i2c.mm_i2c = true; + i2c.i2c_id = RADEON_I2C_MM_ID; + rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "MM_I2C"); +} + bool radeon_combios_get_clock_info(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; @@ -1248,7 +1300,7 @@ bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder,
/* default for macs */ i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); - tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
/* XXX some macs have duallink chips */ switch (rdev->mode_info.connector_table) { @@ -1303,7 +1355,9 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder i2c_bus.en_data_reg = RADEON_GPIOPAD_EN; i2c_bus.y_clk_reg = RADEON_GPIOPAD_Y; i2c_bus.y_data_reg = RADEON_GPIOPAD_Y; - tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + i2c_bus.i2c_id = RADEON_I2C_DVO_ID; + radeon_i2c_add(rdev, &i2c_bus, "DVO"); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); tmds->dvo_chip = DVO_SIL164; tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ break; @@ -1321,15 +1375,15 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder switch (gpio) { case DDC_MONID: i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); - tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); break; case DDC_DVI: i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); - tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); break; case DDC_VGA: i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); - tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); break; case DDC_CRT2: /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ @@ -1337,13 +1391,14 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); else i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); - tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); break; case DDC_LCD: /* MM i2c */ i2c_bus.valid = true; i2c_bus.hw_capable = true; i2c_bus.mm_i2c = true; - tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO"); + i2c_bus.i2c_id = RADEON_I2C_MM_ID; + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); break; default: DRM_ERROR("Unsupported gpio %d\n", gpio); @@ -1926,6 +1981,8 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev, ddc_i2c->en_data_mask = 0x80; ddc_i2c->y_clk_mask = (0x20 << 8); ddc_i2c->y_data_mask = 0x80; + ddc_i2c->i2c_id = RADEON_I2C_GPIO_ID; + radeon_i2c_add(rdev, ddc_i2c, "GPIO_DDC"); }
/* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ @@ -2318,6 +2375,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) RBIOS32(lcd_ddc_info + 3); ddc_i2c.y_data_mask = RBIOS32(lcd_ddc_info + 7); + ddc_i2c.i2c_id = RADEON_I2C_LCD_ID; + radeon_i2c_add(rdev, &ddc_i2c, "LCD"); break; case DDC_GPIO: ddc_i2c = @@ -2339,6 +2398,8 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) RBIOS32(lcd_ddc_info + 3); ddc_i2c.y_data_mask = RBIOS32(lcd_ddc_info + 7); + ddc_i2c.i2c_id = RADEON_I2C_LCD_ID; + radeon_i2c_add(rdev, &ddc_i2c, "LCD"); break; default: ddc_i2c.valid = false; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2395c86..185a6d9 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -518,8 +518,6 @@ static void radeon_connector_destroy(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- if (radeon_connector->ddc_bus) - radeon_i2c_destroy(radeon_connector->ddc_bus); if (radeon_connector->edid) kfree(radeon_connector->edid); kfree(radeon_connector->con_priv); @@ -955,8 +953,6 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector) struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
- if (radeon_connector->ddc_bus) - radeon_i2c_destroy(radeon_connector->ddc_bus); if (radeon_connector->edid) kfree(radeon_connector->edid); if (radeon_dig_connector->dp_i2c_bus) @@ -1088,7 +1084,7 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1104,7 +1100,7 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1126,7 +1122,7 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1156,7 +1152,7 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1187,10 +1183,7 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); if (!radeon_dig_connector->dp_i2c_bus) goto failed; - if (connector_type == DRM_MODE_CONNECTOR_eDP) - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "eDP"); - else - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1230,7 +1223,7 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1252,8 +1245,6 @@ radeon_add_atom_connector(struct drm_device *dev, return;
failed: - if (radeon_connector->ddc_bus) - radeon_i2c_destroy(radeon_connector->ddc_bus); drm_connector_cleanup(connector); kfree(connector); } @@ -1300,7 +1291,7 @@ radeon_add_legacy_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1316,7 +1307,7 @@ radeon_add_legacy_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1332,7 +1323,7 @@ radeon_add_legacy_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1372,7 +1363,7 @@ radeon_add_legacy_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); if (i2c_bus->valid) { - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (!radeon_connector->ddc_bus) goto failed; } @@ -1393,8 +1384,6 @@ radeon_add_legacy_connector(struct drm_device *dev, return;
failed: - if (radeon_connector->ddc_bus) - radeon_i2c_destroy(radeon_connector->ddc_bus); drm_connector_cleanup(connector); kfree(connector); } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 74dac96..52ac08e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1040,6 +1040,9 @@ int radeon_modeset_init(struct radeon_device *rdev) return ret; }
+ /* init i2c buses */ + radeon_i2c_init(rdev); + /* check combios for a valid hardcoded EDID - Sun servers */ if (!rdev->is_atom_bios) { /* check for hardcoded EDID in BIOS */ @@ -1080,6 +1083,8 @@ void radeon_modeset_fini(struct radeon_device *rdev) drm_mode_config_cleanup(rdev->ddev); rdev->mode_info.mode_config_initialized = false; } + /* free i2c buses */ + radeon_i2c_fini(rdev); }
bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 5def6f5..e71f2eb 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -960,6 +960,59 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) kfree(i2c); }
+/* Add the default buses */ +void radeon_i2c_init(struct radeon_device *rdev) +{ + if (rdev->is_atom_bios) + radeon_atombios_i2c_init(rdev); + else + radeon_combios_i2c_init(rdev); +} + +/* remove all the buses */ +void radeon_i2c_fini(struct radeon_device *rdev) +{ + int i; + + for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { + if (rdev->i2c_bus[i]) { + radeon_i2c_destroy(rdev->i2c_bus[i]); + rdev->i2c_bus[i] = NULL; + } + } +} + +/* Add additional buses */ +void radeon_i2c_add(struct radeon_device *rdev, + struct radeon_i2c_bus_rec *rec, + const char *name) +{ + struct drm_device *dev = rdev->ddev; + int i; + + for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { + if (!rdev->i2c_bus[i]) { + rdev->i2c_bus[i] = radeon_i2c_create(dev, rec, name); + return; + } + } +} + +/* looks up bus based on id */ +struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, + struct radeon_i2c_bus_rec *i2c_bus) +{ + int i; + + for (i = 0; i < RADEON_MAX_I2C_BUS; i++) { + if (rdev->i2c_bus[i] && + (rdev->i2c_bus[i]->rec.i2c_id == i2c_bus->i2c_id)) { + return rdev->i2c_bus[i]; + } + } + return NULL; +} + struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) { return NULL; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 71aea40..02d4e2a 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -82,6 +82,8 @@ enum radeon_hpd_id { RADEON_HPD_NONE = 0xff, };
+#define RADEON_MAX_I2C_BUS 16 + /* radeon gpio-based i2c * 1. "mask" reg and bits * grabs the gpio pins for software use @@ -445,6 +447,15 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, uint8_t write_byte, uint8_t *read_byte);
+extern void radeon_i2c_init(struct radeon_device *rdev); +extern void radeon_i2c_fini(struct radeon_device *rdev); +extern void radeon_combios_i2c_init(struct radeon_device *rdev); +extern void radeon_atombios_i2c_init(struct radeon_device *rdev); +extern void radeon_i2c_add(struct radeon_device *rdev, + struct radeon_i2c_bus_rec *rec, + const char *name); +extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, + struct radeon_i2c_bus_rec *i2c_bus); extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, struct radeon_i2c_bus_rec *rec, const char *name);
Handle asic specific table to hw mappings in combios_setup_i2c_bus() directly. This allows us to remove most of the combios quirks and clean up the i2c bus setup.
Signed-off-by: Alex Deucher alexdeucher@gmail.com --- drivers/gpu/drm/radeon/radeon_combios.c | 415 +++++++++++++------------------ 1 files changed, 168 insertions(+), 247 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 18c84cf..885dcfa 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -479,21 +479,67 @@ radeon_combios_get_hardcoded_edid(struct radeon_device *rdev) return NULL; }
-/* standard i2c gpio lines */ -#define RADEON_I2C_MONID_ID 0 -#define RADEON_I2C_DVI_ID 1 -#define RADEON_I2C_VGA_ID 2 -#define RADEON_I2C_CRT2_ID 3 -#define RADEON_I2C_MM_ID 4 -/* custom defined gpio lines */ -#define RADEON_I2C_LCD_ID 5 /* ddc for laptop panels */ -#define RADEON_I2C_GPIO_ID 6 /* rs4xx gpio ddc */ -#define RADEON_I2C_DVO_ID 7 /* i2c bus for dvo */ - static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev, - int ddc_line) + enum radeon_combios_ddc ddc, + u32 clk_mask, + u32 data_mask) { struct radeon_i2c_bus_rec i2c; + int ddc_line = 0; + + /* ddc id = mask reg + * DDC_NONE_DETECTED = none + * DDC_DVI = RADEON_GPIO_DVI_DDC + * DDC_VGA = RADEON_GPIO_VGA_DDC + * DDC_LCD = RADEON_GPIOPAD_MASK + * DDC_GPIO = RADEON_MDGPIO_MASK + * r1xx/r2xx + * DDC_MONID = RADEON_GPIO_MONID + * DDC_CRT2 = RADEON_GPIO_CRT2_DDC + * r3xx + * DDC_MONID = RADEON_GPIO_MONID + * DDC_CRT2 = RADEON_GPIO_DVI_DDC + * rs3xx/rs4xx + * DDC_MONID = RADEON_GPIOPAD_MASK + * DDC_CRT2 = RADEON_GPIO_MONID + */ + switch (ddc) { + case DDC_NONE_DETECTED: + default: + ddc_line = 0; + break; + case DDC_DVI: + ddc_line = RADEON_GPIO_DVI_DDC; + break; + case DDC_VGA: + ddc_line = RADEON_GPIO_VGA_DDC; + break; + case DDC_LCD: + ddc_line = RADEON_GPIOPAD_MASK; + break; + case DDC_GPIO: + ddc_line = RADEON_MDGPIO_MASK; + break; + case DDC_MONID: + if (rdev->family == CHIP_RS300 || + rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) + ddc_line = RADEON_GPIOPAD_MASK; + else + ddc_line = RADEON_GPIO_MONID; + break; + case DDC_CRT2: + if (rdev->family == CHIP_RS300 || + rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) + ddc_line = RADEON_GPIO_MONID; + else if (rdev->family >= CHIP_R300) { + ddc_line = RADEON_GPIO_DVI_DDC; + ddc = DDC_DVI; + } else + ddc_line = RADEON_GPIO_CRT2_DDC; + break; + }
if (ddc_line == RADEON_GPIOPAD_MASK) { i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; @@ -514,15 +560,6 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde i2c.y_clk_reg = RADEON_MDGPIO_Y; i2c.y_data_reg = RADEON_MDGPIO_Y; } else { - i2c.mask_clk_mask = RADEON_GPIO_EN_1; - i2c.mask_data_mask = RADEON_GPIO_EN_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; - i2c.en_data_mask = RADEON_GPIO_EN_0; - i2c.y_clk_mask = RADEON_GPIO_Y_1; - i2c.y_data_mask = RADEON_GPIO_Y_0; - i2c.mask_clk_reg = ddc_line; i2c.mask_data_reg = ddc_line; i2c.a_clk_reg = ddc_line; @@ -533,6 +570,26 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde i2c.y_data_reg = ddc_line; }
+ if (clk_mask && data_mask) { + i2c.mask_clk_mask = clk_mask; + i2c.mask_data_mask = data_mask; + i2c.a_clk_mask = clk_mask; + i2c.a_data_mask = data_mask; + i2c.en_clk_mask = clk_mask; + i2c.en_data_mask = data_mask; + i2c.y_clk_mask = clk_mask; + i2c.y_data_mask = data_mask; + } else { + i2c.mask_clk_mask = RADEON_GPIO_EN_1; + i2c.mask_data_mask = RADEON_GPIO_EN_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; + i2c.en_data_mask = RADEON_GPIO_EN_0; + i2c.y_clk_mask = RADEON_GPIO_Y_1; + i2c.y_data_mask = RADEON_GPIO_Y_0; + } + switch (rdev->family) { case CHIP_R100: case CHIP_RV100: @@ -611,23 +668,7 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde } i2c.mm_i2c = false;
- switch (ddc_line) { - case RADEON_GPIO_MONID: - i2c.i2c_id = RADEON_I2C_MONID_ID; - break; - case RADEON_GPIO_DVI_DDC: - i2c.i2c_id = RADEON_I2C_DVI_ID; - break; - case RADEON_GPIO_VGA_DDC: - i2c.i2c_id = RADEON_I2C_VGA_ID; - break; - case RADEON_GPIO_CRT2_DDC: - i2c.i2c_id = RADEON_I2C_CRT2_ID; - break; - default: - i2c.i2c_id = 0xff; - break; - } + i2c.i2c_id = ddc; i2c.hpd = RADEON_HPD_NONE;
if (ddc_line) @@ -643,23 +684,55 @@ void radeon_combios_i2c_init(struct radeon_device *rdev) struct drm_device *dev = rdev->ddev; struct radeon_i2c_bus_rec i2c;
- i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); - rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "MONID"); - - i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); - rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "DVI_DDC");
- i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); - rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "VGA_DDC"); + i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + rdev->i2c_bus[0] = radeon_i2c_create(dev, &i2c, "DVI_DDC");
- i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); - rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "CRT2_DDC"); + i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + rdev->i2c_bus[1] = radeon_i2c_create(dev, &i2c, "VGA_DDC");
i2c.valid = true; i2c.hw_capable = true; i2c.mm_i2c = true; - i2c.i2c_id = RADEON_I2C_MM_ID; - rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "MM_I2C"); + i2c.i2c_id = 0xa0; + rdev->i2c_bus[2] = radeon_i2c_create(dev, &i2c, "MM_I2C"); + + if (rdev->family == CHIP_RS300 || + rdev->family == CHIP_RS400 || + rdev->family == CHIP_RS480) { + u16 offset; + u8 id, blocks, clk, data; + int i; + + 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); + i2c = combios_setup_i2c_bus(rdev, DDC_MONID, + clk, data); + rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); + break; + } + } + } + + } else if (rdev->family >= CHIP_R300) { + i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); + } else { + i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); + + i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); + rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "CRT2_DDC"); + } }
bool radeon_combios_get_clock_info(struct drm_device *dev) @@ -1299,7 +1372,7 @@ bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder, struct radeon_i2c_bus_rec i2c_bus;
/* default for macs */ - i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); + i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
/* XXX some macs have duallink chips */ @@ -1321,49 +1394,16 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder struct drm_device *dev = encoder->base.dev; struct radeon_device *rdev = dev->dev_private; uint16_t offset; - uint8_t ver, id, blocks, clk, data; - int i; + uint8_t ver; enum radeon_combios_ddc gpio; struct radeon_i2c_bus_rec i2c_bus;
tmds->i2c_bus = NULL; if (rdev->flags & RADEON_IS_IGP) { - offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); - if (offset) { - ver = RBIOS8(offset); - DRM_INFO("GPIO Table revision: %d\n", ver); - 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); - i2c_bus.valid = true; - i2c_bus.mask_clk_mask = (1 << clk); - i2c_bus.mask_data_mask = (1 << data); - i2c_bus.a_clk_mask = (1 << clk); - i2c_bus.a_data_mask = (1 << data); - i2c_bus.en_clk_mask = (1 << clk); - i2c_bus.en_data_mask = (1 << data); - i2c_bus.y_clk_mask = (1 << clk); - i2c_bus.y_data_mask = (1 << data); - i2c_bus.mask_clk_reg = RADEON_GPIOPAD_MASK; - i2c_bus.mask_data_reg = RADEON_GPIOPAD_MASK; - i2c_bus.a_clk_reg = RADEON_GPIOPAD_A; - i2c_bus.a_data_reg = RADEON_GPIOPAD_A; - i2c_bus.en_clk_reg = RADEON_GPIOPAD_EN; - i2c_bus.en_data_reg = RADEON_GPIOPAD_EN; - i2c_bus.y_clk_reg = RADEON_GPIOPAD_Y; - i2c_bus.y_data_reg = RADEON_GPIOPAD_Y; - i2c_bus.i2c_id = RADEON_I2C_DVO_ID; - radeon_i2c_add(rdev, &i2c_bus, "DVO"); - tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); - tmds->dvo_chip = DVO_SIL164; - tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ - break; - } - } - } + i2c_bus = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + tmds->dvo_chip = DVO_SIL164; + tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */ } else { offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); if (offset) { @@ -1372,38 +1412,15 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder tmds->slave_addr = RBIOS8(offset + 4 + 2); tmds->slave_addr >>= 1; /* 7 bit addressing */ gpio = RBIOS8(offset + 4 + 3); - switch (gpio) { - case DDC_MONID: - i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); - tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); - break; - case DDC_DVI: - i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); - tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); - break; - case DDC_VGA: - i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); - tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); - break; - case DDC_CRT2: - /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ - if (rdev->family >= CHIP_R300) - i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); - else - i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); - tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); - break; - case DDC_LCD: /* MM i2c */ + if (gpio == DDC_LCD) { + /* MM i2c */ i2c_bus.valid = true; i2c_bus.hw_capable = true; i2c_bus.mm_i2c = true; - i2c_bus.i2c_id = RADEON_I2C_MM_ID; - tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); - break; - default: - DRM_ERROR("Unsupported gpio %d\n", gpio); - break; - } + i2c_bus.i2c_id = 0xa0; + } else + i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0); + tmds->i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); } }
@@ -1485,7 +1502,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) /* these are the most common settings */ if (rdev->flags & RADEON_SINGLE_CRTC) { /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1500,7 +1517,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) &hpd); } else if (rdev->flags & RADEON_IS_MOBILITY) { /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(rdev, 0); + 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_id(dev, @@ -1515,7 +1532,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) &hpd);
/* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1530,7 +1547,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) &hpd); } else { /* DVI-I - tv dac, int tmds */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_1; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1551,7 +1568,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) &hpd);
/* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1587,7 +1604,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (ibook)\n", rdev->mode_info.connector_table); /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1599,7 +1616,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_LVDS, &hpd); /* VGA - TV DAC */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1628,7 +1645,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (powerbook external tmds)\n", rdev->mode_info.connector_table); /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1640,7 +1657,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_LVDS, &hpd); /* DVI-I - primary dac, ext tmds */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_2; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1677,7 +1694,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (powerbook internal tmds)\n", rdev->mode_info.connector_table); /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1689,7 +1706,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_LVDS, &hpd); /* DVI-I - primary dac, int tmds */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1725,7 +1742,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (powerbook vga)\n", rdev->mode_info.connector_table); /* LVDS */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1737,7 +1754,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_LVDS, &hpd); /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1766,7 +1783,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (mini external tmds)\n", rdev->mode_info.connector_table); /* DVI-I - tv dac, ext tmds */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); hpd.hpd = RADEON_HPD_2; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1803,7 +1820,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (mini internal tmds)\n", rdev->mode_info.connector_table); /* DVI-I - tv dac, int tmds */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1839,7 +1856,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (imac g5 isight)\n", rdev->mode_info.connector_table); /* DVI-D - int tmds */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1851,7 +1868,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D, &hpd); /* VGA - tv dac */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1880,7 +1897,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (emac)\n", rdev->mode_info.connector_table); /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1892,7 +1909,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_VGA, &hpd); /* VGA - tv dac */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1921,7 +1938,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_INFO("Connector Table: %d (rn50-power)\n", rdev->mode_info.connector_table); /* VGA - primary dac */ - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1932,7 +1949,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_MODE_CONNECTOR_VGA, &ddc_i2c, CONNECTOR_OBJECT_ID_VGA, &hpd); - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, @@ -1962,33 +1979,6 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev, struct radeon_i2c_bus_rec *ddc_i2c, struct radeon_hpd *hpd) { - struct radeon_device *rdev = dev->dev_private; - - /* XPRESS DDC quirks */ - if ((rdev->family == CHIP_RS400 || - rdev->family == CHIP_RS480) && - ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) - *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); - else if ((rdev->family == CHIP_RS400 || - rdev->family == CHIP_RS480) && - ddc_i2c->mask_clk_reg == RADEON_GPIO_MONID) { - *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIOPAD_MASK); - ddc_i2c->mask_clk_mask = (0x20 << 8); - ddc_i2c->mask_data_mask = 0x80; - ddc_i2c->a_clk_mask = (0x20 << 8); - ddc_i2c->a_data_mask = 0x80; - ddc_i2c->en_clk_mask = (0x20 << 8); - ddc_i2c->en_data_mask = 0x80; - ddc_i2c->y_clk_mask = (0x20 << 8); - ddc_i2c->y_data_mask = 0x80; - ddc_i2c->i2c_id = RADEON_I2C_GPIO_ID; - radeon_i2c_add(rdev, ddc_i2c, "GPIO_DDC"); - } - - /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ - if ((rdev->family >= CHIP_R300) && - ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) - *ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
/* Certain IBM chipset RN50s have a BIOS reporting two VGAs, one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ @@ -2092,27 +2082,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) connector = (tmp >> 12) & 0xf;
ddc_type = (tmp >> 8) & 0xf; - switch (ddc_type) { - case DDC_MONID: - ddc_i2c = - combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID); - break; - case DDC_DVI: - ddc_i2c = - combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); - break; - case DDC_VGA: - ddc_i2c = - combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); - break; - case DDC_CRT2: - ddc_i2c = - combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); - break; - default: - ddc_i2c.valid = false; - break; - } + ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0);
switch (connector) { case CONNECTOR_PROPRIETARY_LEGACY: @@ -2282,7 +2252,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) 0), ATOM_DEVICE_DFP1_SUPPORT);
- ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_1; radeon_add_legacy_connector(dev, 0, @@ -2302,7 +2272,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); - ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_connector(dev, 0, @@ -2335,74 +2305,25 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) if (lcd_ddc_info) { ddc_type = RBIOS8(lcd_ddc_info + 2); switch (ddc_type) { - case DDC_MONID: - ddc_i2c = - combios_setup_i2c_bus - (rdev, RADEON_GPIO_MONID); - break; - case DDC_DVI: - ddc_i2c = - combios_setup_i2c_bus - (rdev, RADEON_GPIO_DVI_DDC); - break; - case DDC_VGA: - ddc_i2c = - combios_setup_i2c_bus - (rdev, RADEON_GPIO_VGA_DDC); - break; - case DDC_CRT2: - ddc_i2c = - combios_setup_i2c_bus - (rdev, RADEON_GPIO_CRT2_DDC); - break; case DDC_LCD: ddc_i2c = - combios_setup_i2c_bus - (rdev, RADEON_GPIOPAD_MASK); - ddc_i2c.mask_clk_mask = - RBIOS32(lcd_ddc_info + 3); - ddc_i2c.mask_data_mask = - RBIOS32(lcd_ddc_info + 7); - ddc_i2c.a_clk_mask = - RBIOS32(lcd_ddc_info + 3); - ddc_i2c.a_data_mask = - RBIOS32(lcd_ddc_info + 7); - ddc_i2c.en_clk_mask = - RBIOS32(lcd_ddc_info + 3); - ddc_i2c.en_data_mask = - RBIOS32(lcd_ddc_info + 7); - ddc_i2c.y_clk_mask = - RBIOS32(lcd_ddc_info + 3); - ddc_i2c.y_data_mask = - RBIOS32(lcd_ddc_info + 7); - ddc_i2c.i2c_id = RADEON_I2C_LCD_ID; + combios_setup_i2c_bus(rdev, + DDC_LCD, + RBIOS32(lcd_ddc_info + 3), + RBIOS32(lcd_ddc_info + 7)); radeon_i2c_add(rdev, &ddc_i2c, "LCD"); break; case DDC_GPIO: ddc_i2c = - combios_setup_i2c_bus - (rdev, RADEON_MDGPIO_MASK); - ddc_i2c.mask_clk_mask = - RBIOS32(lcd_ddc_info + 3); - ddc_i2c.mask_data_mask = - RBIOS32(lcd_ddc_info + 7); - ddc_i2c.a_clk_mask = - RBIOS32(lcd_ddc_info + 3); - ddc_i2c.a_data_mask = - RBIOS32(lcd_ddc_info + 7); - ddc_i2c.en_clk_mask = - RBIOS32(lcd_ddc_info + 3); - ddc_i2c.en_data_mask = - RBIOS32(lcd_ddc_info + 7); - ddc_i2c.y_clk_mask = - RBIOS32(lcd_ddc_info + 3); - ddc_i2c.y_data_mask = - RBIOS32(lcd_ddc_info + 7); - ddc_i2c.i2c_id = RADEON_I2C_LCD_ID; + combios_setup_i2c_bus(rdev, + DDC_GPIO, + RBIOS32(lcd_ddc_info + 3), + RBIOS32(lcd_ddc_info + 7)); radeon_i2c_add(rdev, &ddc_i2c, "LCD"); break; default: - ddc_i2c.valid = false; + ddc_i2c = + combios_setup_i2c_bus(rdev, ddc_type, 0, 0); break; } DRM_DEBUG_KMS("LCD DDC Info Table found!\n");
router objects are found on systems that use a mux to control ddc line to connector routing or to control the actual clock and data routing from the chip to the connectors. This patch implements ddc line routing.
Signed-off-by: Alex Deucher alexdeucher@gmail.com --- drivers/gpu/drm/radeon/radeon_atombios.c | 94 +++++++++++++++++++++++---- drivers/gpu/drm/radeon/radeon_connectors.c | 14 ++++- drivers/gpu/drm/radeon/radeon_display.c | 12 ++++ drivers/gpu/drm/radeon/radeon_i2c.c | 29 +++++++++ drivers/gpu/drm/radeon/radeon_mode.h | 13 ++++ 5 files changed, 147 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 7851008..6d30868 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -48,7 +48,8 @@ radeon_add_atom_connector(struct drm_device *dev, struct radeon_i2c_bus_rec *i2c_bus, bool linkb, uint32_t igp_lane_info, uint16_t connector_object_id, - struct radeon_hpd *hpd); + struct radeon_hpd *hpd, + struct radeon_router *router);
/* from radeon_legacy_encoder.c */ extern void @@ -470,13 +471,15 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) u16 size, data_offset; u8 frev, crev; ATOM_CONNECTOR_OBJECT_TABLE *con_obj; + ATOM_OBJECT_TABLE *router_obj; ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; ATOM_OBJECT_HEADER *obj_header; - int i, j, path_size, device_support; + int i, j, k, path_size, device_support; int connector_type; u16 igp_lane_info, conn_id, connector_object_id; bool linkb; struct radeon_i2c_bus_rec ddc_bus; + struct radeon_router router; struct radeon_gpio_rec gpio; struct radeon_hpd hpd;
@@ -486,6 +489,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) if (crev < 2) return false;
+ router.valid = false; + obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) (ctx->bios + data_offset + @@ -493,6 +498,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) (ctx->bios + data_offset + le16_to_cpu(obj_header->usConnectorObjectTableOffset)); + router_obj = (ATOM_OBJECT_TABLE *) + (ctx->bios + data_offset + + le16_to_cpu(obj_header->usRouterObjectTableOffset)); device_support = le16_to_cpu(obj_header->usDeviceSupport);
path_size = 0; @@ -579,33 +587,86 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) if (connector_type == DRM_MODE_CONNECTOR_Unknown) continue;
- for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); - j++) { - uint8_t enc_obj_id, enc_obj_num, enc_obj_type; + for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { + uint8_t grph_obj_id, grph_obj_num, grph_obj_type;
- enc_obj_id = + grph_obj_id = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; - enc_obj_num = + grph_obj_num = (le16_to_cpu(path->usGraphicObjIds[j]) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; - enc_obj_type = + grph_obj_type = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
- /* FIXME: add support for router objects */ - if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { - if (enc_obj_num == 2) + if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { + if (grph_obj_num == 2) linkb = true; else linkb = false;
radeon_add_atom_encoder(dev, - enc_obj_id, + grph_obj_id, le16_to_cpu (path-> usDeviceTag));
+ } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { + router.valid = false; + for (k = 0; k < router_obj->ucNumberOfObjects; k++) { + u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID); + if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) { + ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) + (ctx->bios + data_offset + + le16_to_cpu(router_obj->asObjects[k].usRecordOffset)); + ATOM_I2C_RECORD *i2c_record; + ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; + ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path; + ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = + (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) + (ctx->bios + data_offset + + le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset)); + int enum_id; + + router.router_id = router_obj_id; + for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst; + enum_id++) { + if (le16_to_cpu(path->usConnObjectId) == + le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id])) + break; + } + + while (record->ucRecordType > 0 && + record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { + switch (record->ucRecordType) { + case ATOM_I2C_RECORD_TYPE: + i2c_record = + (ATOM_I2C_RECORD *) + record; + i2c_config = + (ATOM_I2C_ID_CONFIG_ACCESS *) + &i2c_record->sucI2cId; + router.i2c_info = + radeon_lookup_i2c_gpio(rdev, + i2c_config-> + ucAccess); + router.i2c_addr = i2c_record->ucI2CAddr >> 1; + break; + case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE: + ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *) + record; + router.valid = true; + router.mux_type = ddc_path->ucMuxType; + router.mux_control_pin = ddc_path->ucMuxControlPin; + router.mux_state = ddc_path->ucMuxState[enum_id]; + break; + } + record = (ATOM_COMMON_RECORD_HEADER *) + ((char *)record + record->ucRecordSize); + } + } + } } }
@@ -685,7 +746,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) connector_type, &ddc_bus, linkb, igp_lane_info, connector_object_id, - &hpd); + &hpd, + &router);
} } @@ -762,6 +824,9 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct int i, j, max_device; struct bios_connector *bios_connectors; size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; + struct radeon_router router; + + router.valid = false;
bios_connectors = kzalloc(bc_size, GFP_KERNEL); if (!bios_connectors) @@ -933,7 +998,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct &bios_connectors[i].ddc_bus, false, 0, connector_object_id, - &bios_connectors[i].hpd); + &bios_connectors[i].hpd, + &router); } }
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 185a6d9..47c4b27 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1040,7 +1040,8 @@ radeon_add_atom_connector(struct drm_device *dev, bool linkb, uint32_t igp_lane_info, uint16_t connector_object_id, - struct radeon_hpd *hpd) + struct radeon_hpd *hpd, + struct radeon_router *router) { struct radeon_device *rdev = dev->dev_private; struct drm_connector *connector; @@ -1065,6 +1066,11 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_connector->shared_ddc = true; shared_ddc = true; } + if (radeon_connector->router_bus && router->valid && + (radeon_connector->router.router_id == router->router_id)) { + radeon_connector->shared_ddc = false; + shared_ddc = false; + } } }
@@ -1079,6 +1085,12 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_connector->shared_ddc = shared_ddc; radeon_connector->connector_object_id = connector_object_id; radeon_connector->hpd = *hpd; + radeon_connector->router = *router; + if (router->valid) { + radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); + if (!radeon_connector->router_bus) + goto failed; + } switch (connector_type) { case DRM_MODE_CONNECTOR_VGA: drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 52ac08e..d49a148 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -319,6 +319,10 @@ static void radeon_print_display_setup(struct drm_device *dev) radeon_connector->ddc_bus->rec.en_data_reg, radeon_connector->ddc_bus->rec.y_clk_reg, radeon_connector->ddc_bus->rec.y_data_reg); + if (radeon_connector->router_bus) + DRM_INFO(" DDC Router 0x%x/0x%x\n", + radeon_connector->router.mux_control_pin, + radeon_connector->router.mux_state); } else { if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || connector->connector_type == DRM_MODE_CONNECTOR_DVII || @@ -395,6 +399,10 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) struct radeon_device *rdev = dev->dev_private; int ret = 0;
+ /* on hw with routers, select right port */ + if (radeon_connector->router.valid) + radeon_router_select_port(radeon_connector); + if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; @@ -425,6 +433,10 @@ static int radeon_ddc_dump(struct drm_connector *connector) struct radeon_connector *radeon_connector = to_radeon_connector(connector); int ret = 0;
+ /* on hw with routers, select right port */ + if (radeon_connector->router.valid) + radeon_router_select_port(radeon_connector); + if (!radeon_connector->ddc_bus) return -1; edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index e71f2eb..bfd2ce5 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -52,6 +52,10 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) } };
+ /* on hw with routers, select right port */ + if (radeon_connector->router.valid) + radeon_router_select_port(radeon_connector); + ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); if (ret == 2) return true; @@ -1073,3 +1077,28 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus, addr, val); }
+/* router switching */ +void radeon_router_select_port(struct radeon_connector *radeon_connector) +{ + u8 val; + + if (!radeon_connector->router.valid) + return; + + radeon_i2c_get_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x3, &val); + val &= radeon_connector->router.mux_control_pin; + radeon_i2c_put_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x3, val); + radeon_i2c_get_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x1, &val); + val &= radeon_connector->router.mux_control_pin; + val |= radeon_connector->router.mux_state; + radeon_i2c_put_byte(radeon_connector->router_bus, + radeon_connector->router.i2c_addr, + 0x1, val); +} + diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 02d4e2a..5bbc086 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -400,6 +400,16 @@ struct radeon_hpd { struct radeon_gpio_rec gpio; };
+struct radeon_router { + bool valid; + u32 router_id; + struct radeon_i2c_bus_rec i2c_info; + u8 i2c_addr; + u8 mux_type; + u8 mux_control_pin; + u8 mux_state; +}; + struct radeon_connector { struct drm_connector base; uint32_t connector_id; @@ -415,6 +425,8 @@ struct radeon_connector { bool dac_load_detect; uint16_t connector_object_id; struct radeon_hpd hpd; + struct radeon_router router; + struct radeon_i2c_chan *router_bus; };
struct radeon_framebuffer { @@ -471,6 +483,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, u8 slave_addr, u8 addr, u8 val); +extern void radeon_router_select_port(struct radeon_connector *radeon_connector); extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
dri-devel@lists.freedesktop.org