drm/i915/i2c: Track the parent encoder rather than just the dev

The SDVO proxy i2c adapter wants to be able to use information stored in
the encoder, so pass that through intel_i2c rather than iterate over all
known encoders every time.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index b39183b..0403ec9 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -445,19 +445,17 @@
 
 static int intel_crt_get_modes(struct drm_connector *connector)
 {
-	int ret;
 	struct intel_encoder *encoder = intel_attached_encoder(connector);
 	struct i2c_adapter *ddc_bus;
 	struct drm_device *dev = connector->dev;
-
+	int ret;
 
 	ret = intel_ddc_get_modes(connector, encoder->ddc_bus);
 	if (ret || !IS_G4X(dev))
 		goto end;
 
 	/* Try to probe digital port for output in DVI-I -> VGA mode. */
-	ddc_bus = intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D");
-
+	ddc_bus = intel_i2c_create(encoder, GPIOD, "CRTDDC_D");
 	if (!ddc_bus) {
 		dev_printk(KERN_ERR, &connector->dev->pdev->dev,
 			   "DDC bus registration failed for CRTDDC_D.\n");
@@ -545,7 +543,8 @@
 		if (dev_priv->crt_ddc_bus != 0)
 			i2c_reg = dev_priv->crt_ddc_bus;
 	}
-	intel_encoder->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
+	intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
+						  i2c_reg, "CRTDDC_A");
 	if (!intel_encoder->ddc_bus) {
 		dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
 			   "failed.\n");
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 31f072d..8fe6b73 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -128,7 +128,7 @@
 }
 
 struct intel_i2c_chan {
-	struct drm_device *drm_dev; /* for getting at dev. private (mmio etc.) */
+	struct intel_encoder *encoder;
 	u32 reg; /* GPIO reg */
 	struct i2c_adapter adapter;
 	struct i2c_algo_bit_data algo;
@@ -206,7 +206,8 @@
 	bool enable_stall_check;
 };
 
-struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
+struct i2c_adapter *intel_i2c_create(struct intel_encoder *encoder,
+				     const u32 reg,
 				     const char *name);
 void intel_i2c_destroy(struct i2c_adapter *adapter);
 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index df42a9c..7de7d1a 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -362,7 +362,8 @@
 	intel_encoder = &intel_dvo->base;
 
 	/* Set up the DDC bus */
-	intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D");
+	intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
+						  GPIOD, "DVODDC_D");
 	if (!intel_encoder->ddc_bus)
 		goto free_intel;
 
@@ -389,10 +390,10 @@
 		 */
 		if (i2cbus != NULL)
 			intel_i2c_destroy(i2cbus);
-		if (!(i2cbus = intel_i2c_create(dev, gpio,
-			gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
+		i2cbus = intel_i2c_create(intel_encoder, gpio,
+					  gpio == GPIOB ?  "DVOI2C_B" : "DVOI2C_E");
+		if (i2cbus == NULL)
 			continue;
-		}
 
 		intel_dvo->dev = *dvo;
 		ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index bba0aba..93d5b61 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -243,26 +243,28 @@
 	/* Set up the DDC bus. */
 	if (sdvox_reg == SDVOB) {
 		intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
-		intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
+		intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
+							  GPIOE, "HDMIB");
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == SDVOC) {
 		intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
-		intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
+		intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
+							  GPIOD, "HDMIC");
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMIB) {
 		intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
-		intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
-								"HDMIB");
+		intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
+							  PCH_GPIOE, "HDMIB");
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMIC) {
 		intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
-		intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
-								"HDMIC");
+		intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
+							  PCH_GPIOD, "HDMIC");
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMID) {
 		intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
-		intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
-								"HDMID");
+		intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
+							  PCH_GPIOF, "HDMID");
 		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
 	}
 	if (!intel_encoder->ddc_bus)
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index de03989..d3d65a9 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -58,25 +58,31 @@
 
 #define I2C_RISEFALL_TIME 20
 
+static inline struct drm_i915_private *
+get_dev_priv(struct intel_i2c_chan *chan)
+{
+	return chan->encoder->base.dev->dev_private;
+}
+
 static int get_clock(void *data)
 {
 	struct intel_i2c_chan *chan = data;
-	struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
+	struct drm_i915_private *dev_priv = get_dev_priv(chan);
 	return (I915_READ(chan->reg) & GPIO_CLOCK_VAL_IN) != 0;
 }
 
 static int get_data(void *data)
 {
 	struct intel_i2c_chan *chan = data;
-	struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
+	struct drm_i915_private *dev_priv = get_dev_priv(chan);
 	return (I915_READ(chan->reg) & GPIO_DATA_VAL_IN) != 0;
 }
 
 static void set_clock(void *data, int state_high)
 {
 	struct intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
+	struct drm_i915_private *dev_priv = get_dev_priv(chan);
+	struct drm_device *dev = dev_priv->dev;
 	u32 reserved = 0, clock_bits;
 
 	/* On most chips, these bits must be preserved in software. */
@@ -96,8 +102,8 @@
 static void set_data(void *data, int state_high)
 {
 	struct intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
+	struct drm_i915_private *dev_priv = get_dev_priv(chan);
+	struct drm_device *dev = dev_priv->dev;
 	u32 reserved = 0, data_bits;
 
 	/* On most chips, these bits must be preserved in software. */
@@ -153,16 +159,18 @@
  *   %GPIOH
  * see PRM for details on how these different busses are used.
  */
-struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
+struct i2c_adapter *intel_i2c_create(struct intel_encoder *encoder,
+				     const u32 reg,
 				     const char *name)
 {
 	struct intel_i2c_chan *chan;
+	struct drm_device *dev = encoder->base.dev;
 
 	chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL);
 	if (!chan)
 		goto out_free;
 
-	chan->drm_dev = dev;
+	chan->encoder = encoder;
 	chan->reg = reg;
 	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
 	chan->adapter.owner = THIS_MODULE;
@@ -178,7 +186,7 @@
 
 	i2c_set_adapdata(&chan->adapter, chan);
 
-	if(i2c_bit_add_bus(&chan->adapter))
+	if (i2c_bit_add_bus(&chan->adapter))
 		goto out_free;
 
 	intel_i2c_reset_gmbus(dev);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index b56b592..2ff4a5cb 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -899,7 +899,8 @@
 	 */
 
 	/* Set up the DDC bus. */
-	intel_encoder->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C");
+	intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
+						  gpio, "LVDSDDC_C");
 	if (!intel_encoder->ddc_bus) {
 		dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
 			   "failed.\n");
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index a812d65..0e68f96 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -184,7 +184,7 @@
 	u32	cur_dot_crawl,	max_dot_crawl;
 };
 
-static struct intel_sdvo *enc_to_intel_sdvo(struct drm_encoder *encoder)
+static struct intel_sdvo *to_intel_sdvo(struct drm_encoder *encoder)
 {
 	return container_of(encoder, struct intel_sdvo, base.base);
 }
@@ -1051,7 +1051,7 @@
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
 {
-	struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder);
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
 	int multiplier;
 
 	/* We need to construct preferred input timings based on our
@@ -1093,7 +1093,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder);
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
 	u32 sdvox;
 	struct intel_sdvo_in_out_map in_out;
 	struct intel_sdvo_dtd input_dtd;
@@ -1200,7 +1200,7 @@
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder);
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	u32 temp;
 
@@ -1899,7 +1899,7 @@
 
 static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
 {
-	struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder);
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
 
 	if (intel_sdvo->analog_ddc_bus)
 		intel_i2c_destroy(intel_sdvo->analog_ddc_bus);
@@ -1984,35 +1984,15 @@
 				     &intel_sdvo->is_hdmi, 1);
 }
 
-static struct intel_sdvo *
-intel_sdvo_chan_to_intel_sdvo(struct intel_i2c_chan *chan)
-{
-	struct drm_device *dev = chan->drm_dev;
-	struct drm_encoder *encoder;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		struct intel_sdvo *intel_sdvo = enc_to_intel_sdvo(encoder);
-		if (intel_sdvo->base.ddc_bus == &chan->adapter)
-			return intel_sdvo;
-	}
-
-	return NULL;
-}
-
 static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
 				  struct i2c_msg msgs[], int num)
 {
 	struct intel_sdvo *intel_sdvo;
-	struct i2c_algo_bit_data *algo_data;
 	const struct i2c_algorithm *algo;
 
-	algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data;
-	intel_sdvo =
-		intel_sdvo_chan_to_intel_sdvo((struct intel_i2c_chan *)
-					      (algo_data->data));
-	if (intel_sdvo == NULL)
-		return -EINVAL;
-
+	intel_sdvo = container_of(i2c_adap->algo_data,
+				  struct intel_sdvo,
+				  base);
 	algo = intel_sdvo->base.i2c_bus->algo;
 
 	intel_sdvo_set_control_bus_switch(intel_sdvo, intel_sdvo->ddc_bus);
@@ -2560,9 +2540,13 @@
 
 	/* setup the DDC bus. */
 	if (IS_SDVOB(sdvo_reg))
-		intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOB");
+		intel_encoder->i2c_bus =
+			intel_i2c_create(intel_encoder,
+					 i2c_reg, "SDVOCTRL_E for SDVOB");
 	else
-		intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOC");
+		intel_encoder->i2c_bus =
+			intel_i2c_create(intel_encoder,
+					 i2c_reg, "SDVOCTRL_E for SDVOC");
 
 	if (!intel_encoder->i2c_bus)
 		goto err_inteloutput;
@@ -2583,14 +2567,20 @@
 
 	/* setup the DDC bus. */
 	if (IS_SDVOB(sdvo_reg)) {
-		intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOB DDC BUS");
-		intel_sdvo->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg,
-						"SDVOB/VGA DDC BUS");
+		intel_encoder->ddc_bus =
+			intel_i2c_create(intel_encoder,
+					 ddc_reg, "SDVOB DDC BUS");
+		intel_sdvo->analog_ddc_bus =
+			intel_i2c_create(intel_encoder,
+					 analog_ddc_reg, "SDVOB/VGA DDC BUS");
 		dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
 	} else {
-		intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOC DDC BUS");
-		intel_sdvo->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg,
-						"SDVOC/VGA DDC BUS");
+		intel_encoder->ddc_bus =
+			intel_i2c_create(intel_encoder,
+					 ddc_reg, "SDVOC DDC BUS");
+		intel_sdvo->analog_ddc_bus =
+			intel_i2c_create(intel_encoder,
+					 analog_ddc_reg, "SDVOC/VGA DDC BUS");
 		dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
 	}
 	if (intel_encoder->ddc_bus == NULL || intel_sdvo->analog_ddc_bus == NULL)