summary refs log tree commit diff
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/radeon.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c67
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c77
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c31
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c53
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h11
7 files changed, 214 insertions, 32 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 3cd1c470b777..3dfcfa3ca425 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 3bc2bcdf5308..a841adead1a1 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)
 {
@@ -1521,7 +1582,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.
@@ -1814,7 +1875,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 5e1474cde4b4..18c84cf3eafa 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 2395c8600cf4..185a6d962b72 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 74dac9635d70..52ac08e9a045 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 5def6f5dff38..e71f2eb02ee2 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 71aea4037e90..02d4e2af6180 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);