drm/radeon/kms: i2c reorg

- keep the atom i2c id in the i2c rec
- fix gpio regs for GPIO and MDGPIO on pre-avivo chips
- track whether the i2c line is hw capable
- track whether the i2c line uses the multimedia i2c block

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index d1c144b..fc5a2df 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -52,7 +52,7 @@
 	args.lpAuxRequest = 0;
 	args.lpDataOut = 16;
 	args.ucDataOutLen = 0;
-	args.ucChannelID = chan->i2c_id;
+	args.ucChannelID = chan->rec.i2c_id;
 	args.ucDelay = delay / 10;
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
@@ -60,7 +60,7 @@
 	if (args.ucReplyStatus) {
 		DRM_ERROR("failed to get auxch %02x%02x %02x %02x 0x%02x %02x\n",
 			  req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3],
-			  chan->i2c_id, args.ucReplyStatus);
+			  chan->rec.i2c_id, args.ucReplyStatus);
 		return false;
 	}
 
@@ -102,7 +102,7 @@
 	struct radeon_device *rdev = dev->dev_private;
 
 	return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0,
-					 radeon_dig_connector->uc_i2c_id, 0);
+					 radeon_dig_connector->dp_i2c_bus->rec.i2c_id, 0);
 }
 
 union dig_transmitter_control {
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index de05ac9..87bf6b9 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -47,7 +47,7 @@
 			  int connector_type,
 			  struct radeon_i2c_bus_rec *i2c_bus,
 			  bool linkb, uint32_t igp_lane_info,
-			  uint16_t connector_object_id, uint8_t uc_i2c_id);
+			  uint16_t connector_object_id);
 
 /* from radeon_legacy_encoder.c */
 extern void
@@ -65,7 +65,7 @@
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct atom_context *ctx = rdev->mode_info.atom_context;
-	ATOM_GPIO_I2C_ASSIGMENT gpio;
+	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;
@@ -78,24 +78,37 @@
 
 	i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
 
-	gpio = i2c_info->asGPIO_Info[id];
+	gpio = &i2c_info->asGPIO_Info[id];
 
-	i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4;
-	i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4;
-	i2c.en_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4;
-	i2c.en_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
-	i2c.y_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
-	i2c.y_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
-	i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4;
-	i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4;
-	i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift);
-	i2c.mask_data_mask = (1 << gpio.ucDataMaskShift);
-	i2c.en_clk_mask = (1 << gpio.ucClkEnShift);
-	i2c.en_data_mask = (1 << gpio.ucDataEnShift);
-	i2c.y_clk_mask = (1 << gpio.ucClkY_Shift);
-	i2c.y_data_mask = (1 << gpio.ucDataY_Shift);
-	i2c.a_clk_mask = (1 << gpio.ucClkA_Shift);
-	i2c.a_data_mask = (1 << gpio.ucDataA_Shift);
+	i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
+	i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
+	i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
+	i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
+	i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
+	i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
+	i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
+	i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
+	i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
+	i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
+	i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
+	i2c.en_data_mask = (1 << gpio->ucDataEnShift);
+	i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
+	i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
+	i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
+	i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
+
+	if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
+		i2c.hw_capable = true;
+	else
+		i2c.hw_capable = false;
+
+	if (gpio->sucI2cId.ucAccess == 0xa0)
+		i2c.mm_i2c = true;
+	else
+		i2c.mm_i2c = false;
+
+	i2c.i2c_id = gpio->sucI2cId.ucAccess;
+
 	i2c.valid = true;
 
 	return i2c;
@@ -276,7 +289,6 @@
 	uint16_t igp_lane_info, conn_id, connector_object_id;
 	bool linkb;
 	struct radeon_i2c_bus_rec ddc_bus;
-	ATOM_I2C_ID_CONFIG_ACCESS i2c_id;
 	atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
 
 	if (data_offset == 0)
@@ -302,7 +314,6 @@
 		path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
 		path_size += le16_to_cpu(path->usSize);
 		linkb = false;
-		i2c_id.ucAccess = 0;
 		if (device_support & le16_to_cpu(path->usDeviceTag)) {
 			uint8_t con_obj_id, con_obj_num, con_obj_type;
 
@@ -420,7 +431,7 @@
 								 asObjects[j].
 								 usRecordOffset));
 						ATOM_I2C_RECORD *i2c_record;
-						
+
 						while (record->ucRecordType > 0
 						       && record->
 						       ucRecordType <=
@@ -431,7 +442,6 @@
 								i2c_record =
 								    (ATOM_I2C_RECORD
 								     *) record;
-								i2c_id.sbfAccess = i2c_record->sucI2cId;
 								line_mux =
 								    i2c_record->
 								    sucI2cId.
@@ -474,7 +484,7 @@
 							      usDeviceTag),
 						  connector_type, &ddc_bus,
 						  linkb, igp_lane_info,
-						  connector_object_id, i2c_id.ucAccess);
+						  connector_object_id);
 
 		}
 	}
@@ -693,7 +703,7 @@
 						  connector_type,
 						  &bios_connectors[i].ddc_bus,
 						  false, 0,
-						  connector_object_id, 0);
+						  connector_object_id);
 		}
 	}
 
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 14d3555..b6761cd 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -442,29 +442,39 @@
 
 }
 
-struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line)
+static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev,
+						       int ddc_line)
 {
 	struct radeon_i2c_bus_rec i2c;
 
-	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;
-	if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
-	    (ddc_line == RADEON_MDGPIO_EN_REG)) {
-		i2c.mask_clk_reg = ddc_line;
-		i2c.mask_data_reg = ddc_line;
-		i2c.a_clk_reg = ddc_line;
-		i2c.a_data_reg = ddc_line;
-		i2c.en_clk_reg = ddc_line;
-		i2c.en_data_reg = ddc_line;
-		i2c.y_clk_reg = ddc_line + 4;
-		i2c.y_data_reg = ddc_line + 4;
+	if (ddc_line == RADEON_GPIOPAD_MASK) {
+		i2c.mask_clk_reg = RADEON_GPIOPAD_MASK;
+		i2c.mask_data_reg = RADEON_GPIOPAD_MASK;
+		i2c.a_clk_reg = RADEON_GPIOPAD_A;
+		i2c.a_data_reg = RADEON_GPIOPAD_A;
+		i2c.en_clk_reg = RADEON_GPIOPAD_EN;
+		i2c.en_data_reg = RADEON_GPIOPAD_EN;
+		i2c.y_clk_reg = RADEON_GPIOPAD_Y;
+		i2c.y_data_reg = RADEON_GPIOPAD_Y;
+	} else if (ddc_line == RADEON_MDGPIO_MASK) {
+		i2c.mask_clk_reg = RADEON_MDGPIO_MASK;
+		i2c.mask_data_reg = RADEON_MDGPIO_MASK;
+		i2c.a_clk_reg = RADEON_MDGPIO_A;
+		i2c.a_data_reg = RADEON_MDGPIO_A;
+		i2c.en_clk_reg = RADEON_MDGPIO_EN;
+		i2c.en_data_reg = RADEON_MDGPIO_EN;
+		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;
@@ -475,6 +485,28 @@
 		i2c.y_data_reg = ddc_line;
 	}
 
+	if (rdev->family < CHIP_R200)
+		i2c.hw_capable = false;
+	else {
+		switch (ddc_line) {
+		case RADEON_GPIO_VGA_DDC:
+		case RADEON_GPIO_DVI_DDC:
+			i2c.hw_capable = true;
+			break;
+		case RADEON_GPIO_MONID:
+			/* hw i2c on RADEON_GPIO_MONID doesn't seem to work
+			 * reliably on some pre-r4xx hardware; not sure why.
+			 */
+			i2c.hw_capable = false;
+			break;
+		default:
+			i2c.hw_capable = false;
+			break;
+		}
+	}
+	i2c.mm_i2c = false;
+	i2c.i2c_id = 0;
+
 	if (ddc_line)
 		i2c.valid = true;
 	else
@@ -1077,7 +1109,7 @@
 	struct radeon_i2c_bus_rec i2c_bus;
 
 	/* default for macs */
-	i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_MONID);
+	i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
 	tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
 
 	/* XXX some macs have duallink chips */
@@ -1153,23 +1185,23 @@
 			gpio = RBIOS8(offset + 4 + 3);
 			switch (gpio) {
 			case DDC_MONID:
-				i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_MONID);
+				i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
 				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
 				break;
 			case DDC_DVI:
-				i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+				i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
 				break;
 			case DDC_VGA:
-				i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+				i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
 				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(RADEON_GPIO_MONID);
+					i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
 				else
-					i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+					i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
 				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
 				break;
 			case DDC_LCD: /* MM i2c */
@@ -1254,7 +1286,7 @@
 		/* these are the most common settings */
 		if (rdev->flags & RADEON_SINGLE_CRTC) {
 			/* VGA - primary dac */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_CRT1_SUPPORT,
@@ -1267,7 +1299,7 @@
 						    CONNECTOR_OBJECT_ID_VGA);
 		} else if (rdev->flags & RADEON_IS_MOBILITY) {
 			/* LVDS */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
+			ddc_i2c = combios_setup_i2c_bus(rdev, 0);
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_LCD1_SUPPORT,
@@ -1280,7 +1312,7 @@
 						    CONNECTOR_OBJECT_ID_LVDS);
 
 			/* VGA - primary dac */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_CRT1_SUPPORT,
@@ -1293,7 +1325,7 @@
 						    CONNECTOR_OBJECT_ID_VGA);
 		} else {
 			/* DVI-I - tv dac, int tmds */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_DFP1_SUPPORT,
@@ -1312,7 +1344,7 @@
 						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
 
 			/* VGA - primary dac */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_CRT1_SUPPORT,
@@ -1343,7 +1375,7 @@
 		DRM_INFO("Connector Table: %d (ibook)\n",
 			 rdev->mode_info.connector_table);
 		/* LVDS */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_LCD1_SUPPORT,
@@ -1353,7 +1385,7 @@
 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
 					    CONNECTOR_OBJECT_ID_LVDS);
 		/* VGA - TV DAC */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT2_SUPPORT,
@@ -1377,7 +1409,7 @@
 		DRM_INFO("Connector Table: %d (powerbook external tmds)\n",
 			 rdev->mode_info.connector_table);
 		/* LVDS */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_LCD1_SUPPORT,
@@ -1387,7 +1419,7 @@
 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
 					    CONNECTOR_OBJECT_ID_LVDS);
 		/* DVI-I - primary dac, ext tmds */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP2_SUPPORT,
@@ -1419,7 +1451,7 @@
 		DRM_INFO("Connector Table: %d (powerbook internal tmds)\n",
 			 rdev->mode_info.connector_table);
 		/* LVDS */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_LCD1_SUPPORT,
@@ -1429,7 +1461,7 @@
 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
 					    CONNECTOR_OBJECT_ID_LVDS);
 		/* DVI-I - primary dac, int tmds */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP1_SUPPORT,
@@ -1460,7 +1492,7 @@
 		DRM_INFO("Connector Table: %d (powerbook vga)\n",
 			 rdev->mode_info.connector_table);
 		/* LVDS */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_LCD1_SUPPORT,
@@ -1470,7 +1502,7 @@
 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
 					    CONNECTOR_OBJECT_ID_LVDS);
 		/* VGA - primary dac */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT1_SUPPORT,
@@ -1494,7 +1526,7 @@
 		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(RADEON_GPIO_CRT2_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP2_SUPPORT,
@@ -1526,7 +1558,7 @@
 		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(RADEON_GPIO_CRT2_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP1_SUPPORT,
@@ -1557,7 +1589,7 @@
 		DRM_INFO("Connector Table: %d (imac g5 isight)\n",
 			 rdev->mode_info.connector_table);
 		/* DVI-D - int tmds */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP1_SUPPORT,
@@ -1567,7 +1599,7 @@
 					    DRM_MODE_CONNECTOR_DVID, &ddc_i2c,
 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
 		/* VGA - tv dac */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT2_SUPPORT,
@@ -1591,7 +1623,7 @@
 		DRM_INFO("Connector Table: %d (emac)\n",
 			 rdev->mode_info.connector_table);
 		/* VGA - primary dac */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT1_SUPPORT,
@@ -1601,7 +1633,7 @@
 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
 					    CONNECTOR_OBJECT_ID_VGA);
 		/* VGA - tv dac */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT2_SUPPORT,
@@ -1644,11 +1676,11 @@
 	if ((rdev->family == CHIP_RS400 ||
 	     rdev->family == CHIP_RS480) &&
 	    ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
-		*ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
+		*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->valid = true;
+		*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);
@@ -1657,20 +1689,12 @@
 		ddc_i2c->en_data_mask = 0x80;
 		ddc_i2c->y_clk_mask = (0x20 << 8);
 		ddc_i2c->y_data_mask = 0x80;
-		ddc_i2c->mask_clk_reg = RADEON_GPIOPAD_MASK;
-		ddc_i2c->mask_data_reg = RADEON_GPIOPAD_MASK;
-		ddc_i2c->a_clk_reg = RADEON_GPIOPAD_A;
-		ddc_i2c->a_data_reg = RADEON_GPIOPAD_A;
-		ddc_i2c->en_clk_reg = RADEON_GPIOPAD_EN;
-		ddc_i2c->en_data_reg = RADEON_GPIOPAD_EN;
-		ddc_i2c->y_clk_reg = RADEON_GPIOPAD_Y;
-		ddc_i2c->y_data_reg = RADEON_GPIOPAD_Y;
 	}
 
 	/* 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(RADEON_GPIO_DVI_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 */
@@ -1788,19 +1812,19 @@
 			switch (ddc_type) {
 			case DDC_MONID:
 				ddc_i2c =
-				    combios_setup_i2c_bus(RADEON_GPIO_MONID);
+					combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
 				break;
 			case DDC_DVI:
 				ddc_i2c =
-				    combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+					combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 				break;
 			case DDC_VGA:
 				ddc_i2c =
-				    combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+					combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 				break;
 			case DDC_CRT2:
 				ddc_i2c =
-				    combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+					combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
 				break;
 			default:
 				break;
@@ -1955,7 +1979,7 @@
 									0),
 						  ATOM_DEVICE_DFP1_SUPPORT);
 
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 			radeon_add_legacy_connector(dev,
 						    0,
 						    ATOM_DEVICE_CRT1_SUPPORT |
@@ -1973,7 +1997,7 @@
 										ATOM_DEVICE_CRT1_SUPPORT,
 										1),
 							  ATOM_DEVICE_CRT1_SUPPORT);
-				ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+				ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 				radeon_add_legacy_connector(dev,
 							    0,
 							    ATOM_DEVICE_CRT1_SUPPORT,
@@ -2007,27 +2031,27 @@
 				case DDC_MONID:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_GPIO_MONID);
+						(rdev, RADEON_GPIO_MONID);
 					break;
 				case DDC_DVI:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_GPIO_DVI_DDC);
+						(rdev, RADEON_GPIO_DVI_DDC);
 					break;
 				case DDC_VGA:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_GPIO_VGA_DDC);
+						(rdev, RADEON_GPIO_VGA_DDC);
 					break;
 				case DDC_CRT2:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_GPIO_CRT2_DDC);
+						(rdev, RADEON_GPIO_CRT2_DDC);
 					break;
 				case DDC_LCD:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_LCD_GPIO_MASK);
+						(rdev, RADEON_GPIOPAD_MASK);
 					ddc_i2c.mask_clk_mask =
 					    RBIOS32(lcd_ddc_info + 3);
 					ddc_i2c.mask_data_mask =
@@ -2048,7 +2072,7 @@
 				case DDC_GPIO:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_MDGPIO_EN_REG);
+						(rdev, RADEON_MDGPIO_MASK);
 					ddc_i2c.mask_clk_mask =
 					    RBIOS32(lcd_ddc_info + 3);
 					ddc_i2c.mask_data_mask =
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 4d457bc..98634ce 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -952,7 +952,7 @@
 			  struct radeon_i2c_bus_rec *i2c_bus,
 			  bool linkb,
 			  uint32_t igp_lane_info,
-			  uint16_t connector_object_id, uint8_t uc_i2c_id)
+			  uint16_t connector_object_id)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_connector *connector;
@@ -1083,8 +1083,7 @@
 		if (ret)
 			goto failed;
 		/* add DP i2c bus */
-		radeon_dig_connector->uc_i2c_id = uc_i2c_id;
-		radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, "DP-auxch", true, uc_i2c_id);
+		radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
 			if (!radeon_connector->ddc_bus)
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index f200312..da3da1e 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -69,13 +69,15 @@
 	 * holds the i2c port in a bad state - switch hw i2c away before
 	 * doing DDC - do this for all r200s/r300s/r400s for safety sake
 	 */
-	if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
-		if (rec->a_clk_reg == RADEON_GPIO_MONID) {
-			WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
-						R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
-		} else {
-			WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
-						R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
+	if (rec->hw_capable) {
+		if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
+			if (rec->a_clk_reg == RADEON_GPIO_MONID) {
+				WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
+							       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
+			} else {
+				WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
+							       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
+			}
 		}
 	}
 
@@ -86,6 +88,12 @@
 	temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask;
 	WREG32(rec->a_data_reg, temp);
 
+	/* set the pins to input */
+	temp = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask;
+	WREG32(rec->en_clk_reg, temp);
+
+	temp = RREG32(rec->en_data_reg) & ~rec->en_data_mask;
+	WREG32(rec->en_data_reg, temp);
 
 	/* mask the gpio pins for software use */
 	temp = RREG32(rec->mask_clk_reg);
@@ -199,7 +207,8 @@
 }
 
 struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
-					     const char *name, bool dp, u8 i2c_id)
+					     struct radeon_i2c_bus_rec *rec,
+					     const char *name)
 {
 	struct radeon_i2c_chan *i2c;
 	int ret;
@@ -208,7 +217,7 @@
 	if (i2c == NULL)
 		return NULL;
 
-	i2c->i2c_id = i2c_id;
+	i2c->rec = *rec;
 	i2c->adapter.owner = THIS_MODULE;
 	i2c->dev = dev;
 	i2c_set_adapdata(&i2c->adapter, i2c);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 166f753..1964afb 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -106,6 +106,13 @@
  */
 struct radeon_i2c_bus_rec {
 	bool valid;
+	/* id used by atom */
+	uint8_t i2c_id;
+	/* can be used with hw i2c engine */
+	bool hw_capable;
+	/* uses multi-media i2c engine */
+	bool mm_i2c;
+	/* regs and bits */
 	uint32_t mask_clk_reg;
 	uint32_t mask_data_reg;
 	uint32_t a_clk_reg;
@@ -172,7 +179,6 @@
 		struct i2c_algo_bit_data bit;
 	} algo;
 	struct radeon_i2c_bus_rec rec;
-	uint8_t i2c_id;
 };
 
 /* mostly for macs, but really any system without connector tables */
@@ -333,7 +339,6 @@
 struct radeon_connector_atom_dig {
 	uint32_t igp_lane_info;
 	bool linkb;
-	uint16_t uc_i2c_id;
 	struct radeon_i2c_chan *dp_i2c_bus;
 	u8 dpcd[8];
 };
@@ -352,8 +357,6 @@
 	void *con_priv;
 	bool dac_load_detect;
 	uint16_t connector_object_id;
-	/* need to keep this for display port */
-//	
 };
 
 struct radeon_framebuffer {
@@ -362,12 +365,13 @@
 };
 
 extern int radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
-extern void radeon_dp_getdpcd(struct radeon_connector *connector);
+extern void radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
 extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 				uint8_t write_byte, uint8_t *read_byte);
 
 extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
-						    const char *name, bool dp, u8 i2c_id);
+						    struct radeon_i2c_bus_rec *rec,
+						    const char *name);
 extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
 						 struct radeon_i2c_bus_rec *rec,
 						 const char *name);
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index c4c41c8..b811640 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -1148,16 +1148,16 @@
 #       define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13)
 #       define RADEON_MC_MCLK_DYN_ENABLE    (1 << 14)
 #       define RADEON_IO_MCLK_DYN_ENABLE    (1 << 15)
+
 #define RADEON_GPIOPAD_MASK                 0x0198
 #define RADEON_GPIOPAD_A		    0x019c
 #define RADEON_GPIOPAD_EN                   0x01a0
 #define RADEON_GPIOPAD_Y                    0x01a4
-#define RADEON_LCD_GPIO_MASK                0x01a0
-#define RADEON_LCD_GPIO_Y_REG               0x01a4
-#define RADEON_MDGPIO_A_REG                 0x01ac
-#define RADEON_MDGPIO_EN_REG                0x01b0
-#define RADEON_MDGPIO_MASK                  0x0198
-#define RADEON_MDGPIO_Y_REG                 0x01b4
+#define RADEON_MDGPIO_MASK                  0x01a8
+#define RADEON_MDGPIO_A                     0x01ac
+#define RADEON_MDGPIO_EN                    0x01b0
+#define RADEON_MDGPIO_Y                     0x01b4
+
 #define RADEON_MEM_ADDR_CONFIG              0x0148
 #define RADEON_MEM_BASE                     0x0f10 /* PCI */
 #define RADEON_MEM_CNTL                     0x0140