drm/i915: use GMBUS to manage i2c links
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 20 Jul 2010 22:44:45 +0000 (15:44 -0700)
committerChris Wilson <chris@chris-wilson.co.uk>
Sat, 18 Sep 2010 14:46:19 +0000 (15:46 +0100)
Use the GMBUS interface rather than direct bit banging to grab the EDID
over DDC (and for other forms of auxiliary communication with external
display controllers). The hope is that this method will be much faster
and more reliable than bit banging for fetching EDIDs from buggy monitors
or through switches, though we still preserve the bit banging as a
fallback in case GMBUS fails.

Based on an original patch by Jesse Barnes.

Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
21 files changed:
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/i915/dvo_ch7017.c
drivers/gpu/drm/i915/dvo_ch7xxx.c
drivers/gpu/drm/i915/dvo_ivch.c
drivers/gpu/drm/i915/dvo_sil164.c
drivers/gpu/drm/i915/dvo_tfp410.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_modes.c
drivers/gpu/drm/i915/intel_sdvo.c

index 96e96310822513bfd9c984054a913eac7b5acc50..fd033ebbdf84c1f731b1935a6e3fbad352a24a0b 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
 #include "drmP.h"
 #include "drm_edid.h"
 #include "drm_edid_modes.h"
index 14d59804acd77b00637ee68c0662a1183cdbca87..0bc8ce1ad9aa5c9df59ed3af9ff358aebc4e43a0 100644 (file)
@@ -168,7 +168,6 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode);
 static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
 {
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[2];
        u8 in_buf[2];
 
@@ -190,7 +189,7 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
        out_buf[0] = addr;
        out_buf[1] = 0;
 
-       if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
+       if (i2c_transfer(adapter, msgs, 2) == 2) {
                *val= in_buf[0];
                return true;
        };
@@ -201,7 +200,6 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
 static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
 {
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        uint8_t out_buf[2];
        struct i2c_msg msg = {
                .addr = dvo->slave_addr,
@@ -213,7 +211,7 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
        out_buf[0] = addr;
        out_buf[1] = val;
 
-       if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
+       if (i2c_transfer(adapter, &msg, 1) == 1)
                return true;
 
        return false;
@@ -223,7 +221,6 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
 static bool ch7017_init(struct intel_dvo_device *dvo,
                        struct i2c_adapter *adapter)
 {
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        struct ch7017_priv *priv;
        uint8_t val;
 
@@ -242,7 +239,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
            val != CH7019_DEVICE_ID_VALUE) {
                DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
                                "Slave %d.\n",
-                         val, i2cbus->adapter.name,dvo->slave_addr);
+                         val, adapter->name,dvo->slave_addr);
                goto fail;
        }
 
index 6f1944b244416c03475e8883a94a4c358fe8d881..7eaa94e4ff061b5450c9d769f70f02fb6459db2a 100644 (file)
@@ -113,7 +113,6 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
        struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[2];
        u8 in_buf[2];
 
@@ -135,14 +134,14 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
        out_buf[0] = addr;
        out_buf[1] = 0;
 
-       if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
+       if (i2c_transfer(adapter, msgs, 2) == 2) {
                *ch = in_buf[0];
                return true;
        };
 
        if (!ch7xxx->quiet) {
                DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
-                         addr, i2cbus->adapter.name, dvo->slave_addr);
+                         addr, adapter->name, dvo->slave_addr);
        }
        return false;
 }
@@ -152,7 +151,6 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
        struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        uint8_t out_buf[2];
        struct i2c_msg msg = {
                .addr = dvo->slave_addr,
@@ -164,12 +162,12 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
        out_buf[0] = addr;
        out_buf[1] = ch;
 
-       if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
+       if (i2c_transfer(adapter, &msg, 1) == 1)
                return true;
 
        if (!ch7xxx->quiet) {
                DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
-                         addr, i2cbus->adapter.name, dvo->slave_addr);
+                         addr, adapter->name, dvo->slave_addr);
        }
 
        return false;
index a2ec3f4872023fbe3510ce0bc54c673c5e4ec56b..a12ed9414cc7358e462dfa78766fe6f16948eacd 100644 (file)
@@ -167,7 +167,6 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
 {
        struct ivch_priv *priv = dvo->dev_priv;
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[1];
        u8 in_buf[2];
 
@@ -193,7 +192,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
 
        out_buf[0] = addr;
 
-       if (i2c_transfer(&i2cbus->adapter, msgs, 3) == 3) {
+       if (i2c_transfer(adapter, msgs, 3) == 3) {
                *data = (in_buf[1] << 8) | in_buf[0];
                return true;
        };
@@ -201,7 +200,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
        if (!priv->quiet) {
                DRM_DEBUG_KMS("Unable to read register 0x%02x from "
                                "%s:%02x.\n",
-                         addr, i2cbus->adapter.name, dvo->slave_addr);
+                         addr, adapter->name, dvo->slave_addr);
        }
        return false;
 }
@@ -211,7 +210,6 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
 {
        struct ivch_priv *priv = dvo->dev_priv;
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[3];
        struct i2c_msg msg = {
                .addr = dvo->slave_addr,
@@ -224,12 +222,12 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
        out_buf[1] = data & 0xff;
        out_buf[2] = data >> 8;
 
-       if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
+       if (i2c_transfer(adapter, &msg, 1) == 1)
                return true;
 
        if (!priv->quiet) {
                DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
-                         addr, i2cbus->adapter.name, dvo->slave_addr);
+                         addr, adapter->name, dvo->slave_addr);
        }
 
        return false;
index 9b8e6765cf260fa8f91f2fa1a9f4432fce2b0287..e4b4091df942faf1196e4c32c057dff77e4a467e 100644 (file)
@@ -69,7 +69,6 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
        struct sil164_priv *sil = dvo->dev_priv;
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[2];
        u8 in_buf[2];
 
@@ -91,14 +90,14 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
        out_buf[0] = addr;
        out_buf[1] = 0;
 
-       if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
+       if (i2c_transfer(adapter, msgs, 2) == 2) {
                *ch = in_buf[0];
                return true;
        };
 
        if (!sil->quiet) {
                DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
-                         addr, i2cbus->adapter.name, dvo->slave_addr);
+                         addr, adapter->name, dvo->slave_addr);
        }
        return false;
 }
@@ -107,7 +106,6 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
        struct sil164_priv *sil= dvo->dev_priv;
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        uint8_t out_buf[2];
        struct i2c_msg msg = {
                .addr = dvo->slave_addr,
@@ -119,12 +117,12 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
        out_buf[0] = addr;
        out_buf[1] = ch;
 
-       if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
+       if (i2c_transfer(adapter, &msg, 1) == 1)
                return true;
 
        if (!sil->quiet) {
                DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
-                         addr, i2cbus->adapter.name, dvo->slave_addr);
+                         addr, adapter->name, dvo->slave_addr);
        }
 
        return false;
index 56f66426207f0a1a293dcb073360985d328fd85e..8ab2855bb544ae88851e4d90ce107382165e5442 100644 (file)
@@ -94,7 +94,6 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
        struct tfp410_priv *tfp = dvo->dev_priv;
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[2];
        u8 in_buf[2];
 
@@ -116,14 +115,14 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
        out_buf[0] = addr;
        out_buf[1] = 0;
 
-       if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
+       if (i2c_transfer(adapter, msgs, 2) == 2) {
                *ch = in_buf[0];
                return true;
        };
 
        if (!tfp->quiet) {
                DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
-                         addr, i2cbus->adapter.name, dvo->slave_addr);
+                         addr, adapter->name, dvo->slave_addr);
        }
        return false;
 }
@@ -132,7 +131,6 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
        struct tfp410_priv *tfp = dvo->dev_priv;
        struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        uint8_t out_buf[2];
        struct i2c_msg msg = {
                .addr = dvo->slave_addr,
@@ -144,12 +142,12 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
        out_buf[0] = addr;
        out_buf[1] = ch;
 
-       if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
+       if (i2c_transfer(adapter, &msg, 1) == 1)
                return true;
 
        if (!tfp->quiet) {
                DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
-                         addr, i2cbus->adapter.name, dvo->slave_addr);
+                         addr, adapter->name, dvo->slave_addr);
        }
 
        return false;
index 7c7d1bc9d1bed2e98aa42167ec2160d62cd8ddf8..39aaffe79583eb35148751733d9428475f0ec262 100644 (file)
@@ -2001,6 +2001,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        /* Try to make sure MCHBAR is enabled before poking at it */
        intel_setup_mchbar(dev);
+       intel_setup_gmbus(dev);
        intel_opregion_setup(dev);
 
        i915_gem_load(dev);
@@ -2155,6 +2156,7 @@ int i915_driver_unload(struct drm_device *dev)
                intel_cleanup_overlay(dev);
        }
 
+       intel_teardown_gmbus(dev);
        intel_teardown_mchbar(dev);
 
        destroy_workqueue(dev_priv->wq);
index b0692c40b0c72801347acc912641b50738610ba6..cf08128798a7f42f3028a3588835fe1d9291f409 100644 (file)
@@ -34,6 +34,7 @@
 #include "intel_bios.h"
 #include "intel_ringbuffer.h"
 #include <linux/io-mapping.h>
+#include <linux/i2c.h>
 #include <drm/intel-gtt.h>
 
 /* General customization:
@@ -246,6 +247,12 @@ typedef struct drm_i915_private {
 
        void __iomem *regs;
 
+       struct intel_gmbus {
+               struct i2c_adapter adapter;
+               struct i2c_adapter *force_bitbanging;
+               int pin;
+       } *gmbus;
+
        struct pci_dev *bridge_dev;
        struct intel_ring_buffer render_ring;
        struct intel_ring_buffer bsd_ring;
@@ -339,7 +346,7 @@ typedef struct drm_i915_private {
 
        struct notifier_block lid_notifier;
 
-       int crt_ddc_bus; /* 0 = unknown, else GPIO to use for CRT DDC */
+       int crt_ddc_pin;
        struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
        int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
        int num_fence_regs; /* 8 on pre-965, 16 otherwise */
@@ -1070,6 +1077,11 @@ extern int i915_restore_state(struct drm_device *dev);
 extern int i915_save_state(struct drm_device *dev);
 extern int i915_restore_state(struct drm_device *dev);
 
+/* intel_i2c.c */
+extern int intel_setup_gmbus(struct drm_device *dev);
+extern void intel_teardown_gmbus(struct drm_device *dev);
+extern void intel_i2c_reset(struct drm_device *dev);
+
 /* intel_opregion.c */
 extern int intel_opregion_setup(struct drm_device *dev);
 #ifdef CONFIG_ACPI
index fd229abe0d8658e6baa5e64a955820818587e8fe..18e3749fbd11dbea9132808aaceef0655769b2e1 100644 (file)
 # define GPIO_DATA_VAL_IN              (1 << 12)
 # define GPIO_DATA_PULLUP_DISABLE      (1 << 13)
 
-#define GMBUS0                 0x5100
-#define GMBUS1                 0x5104
-#define GMBUS2                 0x5108
-#define GMBUS3                 0x510c
-#define GMBUS4                 0x5110
-#define GMBUS5                 0x5120
+#define GMBUS0                 0x5100 /* clock/port select */
+#define   GMBUS_RATE_100KHZ    (0<<8)
+#define   GMBUS_RATE_50KHZ     (1<<8)
+#define   GMBUS_RATE_400KHZ    (2<<8) /* reserved on Pineview */
+#define   GMBUS_RATE_1MHZ      (3<<8) /* reserved on Pineview */
+#define   GMBUS_HOLD_EXT       (1<<7) /* 300ns hold time, rsvd on Pineview */
+#define   GMBUS_PORT_DISABLED  0
+#define   GMBUS_PORT_SSC       1
+#define   GMBUS_PORT_VGADDC    2
+#define   GMBUS_PORT_PANEL     3
+#define   GMBUS_PORT_DPC       4 /* HDMIC */
+#define   GMBUS_PORT_DPB       5 /* SDVO, HDMIB */
+                                 /* 6 reserved */
+#define   GMBUS_PORT_DPD       7 /* HDMID */
+#define   GMBUS_NUM_PORTS       8
+#define GMBUS1                 0x5104 /* command/status */
+#define   GMBUS_SW_CLR_INT     (1<<31)
+#define   GMBUS_SW_RDY         (1<<30)
+#define   GMBUS_ENT            (1<<29) /* enable timeout */
+#define   GMBUS_CYCLE_NONE     (0<<25)
+#define   GMBUS_CYCLE_WAIT     (1<<25)
+#define   GMBUS_CYCLE_INDEX    (2<<25)
+#define   GMBUS_CYCLE_STOP     (4<<25)
+#define   GMBUS_BYTE_COUNT_SHIFT 16
+#define   GMBUS_SLAVE_INDEX_SHIFT 8
+#define   GMBUS_SLAVE_ADDR_SHIFT 1
+#define   GMBUS_SLAVE_READ     (1<<0)
+#define   GMBUS_SLAVE_WRITE    (0<<0)
+#define GMBUS2                 0x5108 /* status */
+#define   GMBUS_INUSE          (1<<15)
+#define   GMBUS_HW_WAIT_PHASE  (1<<14)
+#define   GMBUS_STALL_TIMEOUT  (1<<13)
+#define   GMBUS_INT            (1<<12)
+#define   GMBUS_HW_RDY         (1<<11)
+#define   GMBUS_SATOER         (1<<10)
+#define   GMBUS_ACTIVE         (1<<9)
+#define GMBUS3                 0x510c /* data buffer bytes 3-0 */
+#define GMBUS4                 0x5110 /* interrupt mask (Pineview+) */
+#define   GMBUS_SLAVE_TIMEOUT_EN (1<<4)
+#define   GMBUS_NAK_EN         (1<<3)
+#define   GMBUS_IDLE_EN                (1<<2)
+#define   GMBUS_HW_WAIT_EN     (1<<1)
+#define   GMBUS_HW_RDY_EN      (1<<0)
+#define GMBUS5                 0x5120 /* byte index */
+#define   GMBUS_2BYTE_INDEX_EN (1<<31)
 
 /*
  * Clock control & power management
index 2c6b98f2440eff4fdee79ba3c7c95a5bbdf07c4a..5c0de6501828475053886969f62e1b07913ed619 100644 (file)
@@ -860,9 +860,7 @@ int i915_restore_state(struct drm_device *dev)
        for (i = 0; i < 3; i++)
                I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
 
-       /* I2C state */
-       intel_i2c_reset_gmbus(dev);
+       intel_i2c_reset(dev);
 
        return 0;
 }
-
index 8986a4b898dbc54291ed3b114e736f6bb5e4a251..d11bbcad4fea5fa78c194a4c5b4cffbf5b31c91f 100644 (file)
@@ -291,14 +291,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
                          struct bdb_header *bdb)
 {
        struct bdb_general_definitions *general;
-       const int crt_bus_map_table[] = {
-               GPIOB,
-               GPIOA,
-               GPIOC,
-               GPIOD,
-               GPIOE,
-               GPIOF,
-       };
 
        general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
        if (general) {
@@ -306,10 +298,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
                if (block_size >= sizeof(*general)) {
                        int bus_pin = general->crt_ddc_gmbus_pin;
                        DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
-                       if ((bus_pin >= 1) && (bus_pin <= 6)) {
-                               dev_priv->crt_ddc_bus =
-                                       crt_bus_map_table[bus_pin-1];
-                       }
+                       if (bus_pin >= 1 && bus_pin <= 6)
+                               dev_priv->crt_ddc_pin = bus_pin - 1;
                } else {
                        DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
                                  block_size);
@@ -533,6 +523,8 @@ intel_init_bios(struct drm_device *dev)
        struct bdb_header *bdb = NULL;
        u8 __iomem *bios = NULL;
 
+       dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC;
+
        /* XXX Should this validation be moved to intel_opregion.c? */
        if (dev_priv->opregion.vbt) {
                struct vbt_header *vbt = dev_priv->opregion.vbt;
index 2353da625d2524388ed569018a483e91cc166861..8b782ee63085d2512389074ede394ac2590a63e5 100644 (file)
@@ -264,12 +264,13 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
 static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
 {
        struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+       struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 
        /* CRT should always be at 0, but check anyway */
        if (intel_encoder->type != INTEL_OUTPUT_ANALOG)
                return false;
 
-       return intel_ddc_probe(intel_encoder);
+       return intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin);
 }
 
 static enum drm_connector_status
@@ -445,29 +446,18 @@ static void intel_crt_destroy(struct drm_connector *connector)
 
 static int intel_crt_get_modes(struct drm_connector *connector)
 {
-       struct intel_encoder *encoder = intel_attached_encoder(connector);
-       struct i2c_adapter *ddc_bus;
        struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
-       ret = intel_ddc_get_modes(connector, encoder->ddc_bus);
+       ret = intel_ddc_get_modes(connector,
+                                &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
        if (ret || !IS_G4X(dev))
-               goto end;
+               return ret;
 
        /* Try to probe digital port for output in DVI-I -> VGA mode. */
-       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");
-               goto end;
-       }
-       /* Try to get modes by GPIOD port */
-       ret = intel_ddc_get_modes(connector, ddc_bus);
-       intel_i2c_destroy(ddc_bus);
-
-end:
-       return ret;
-
+       return intel_ddc_get_modes(connector,
+                                  &dev_priv->gmbus[GMBUS_PORT_DPB].adapter);
 }
 
 static int intel_crt_set_property(struct drm_connector *connector,
@@ -513,7 +503,6 @@ void intel_crt_init(struct drm_device *dev)
        struct intel_encoder *intel_encoder;
        struct intel_connector *intel_connector;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 i2c_reg;
 
        intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL);
        if (!intel_encoder)
@@ -534,27 +523,6 @@ void intel_crt_init(struct drm_device *dev)
 
        intel_connector_attach_encoder(intel_connector, intel_encoder);
 
-       /* Set up the DDC bus. */
-       if (HAS_PCH_SPLIT(dev))
-               i2c_reg = PCH_GPIOA;
-       else {
-               i2c_reg = GPIOA;
-               /* Use VBT information for CRT DDC if available */
-               if (dev_priv->crt_ddc_bus != 0)
-                       i2c_reg = dev_priv->crt_ddc_bus;
-       }
-       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");
-               drm_connector_cleanup(&intel_connector->base);
-               kfree(intel_connector);
-               drm_encoder_cleanup(&intel_encoder->base);
-               kfree(intel_encoder);
-               return;
-       }
-
        intel_encoder->type = INTEL_OUTPUT_ANALOG;
        intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
                                   (1 << INTEL_ANALOG_CLONE_BIT) |
index 11d643acf2fa644bd7a14dfd6631e9483e423fe6..86ea3890aa8a6cc7f2a884b5e52ee69549c3ff56 100644 (file)
@@ -2530,12 +2530,6 @@ void intel_encoder_destroy(struct drm_encoder *encoder)
 {
        struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
 
-       if (intel_encoder->ddc_bus)
-               intel_i2c_destroy(intel_encoder->ddc_bus);
-
-       if (intel_encoder->i2c_bus)
-               intel_i2c_destroy(intel_encoder->i2c_bus);
-
        drm_encoder_cleanup(encoder);
        kfree(intel_encoder);
 }
index 208a4ec3e432bfa87fa69d21fecf6b4a989d44e4..9a87ec5175e6e3d8a5a7b79f86f097c4f3367f06 100644 (file)
@@ -1490,7 +1490,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
        /* We should parse the EDID data and find out if it has an audio sink
         */
 
-       ret = intel_ddc_get_modes(connector, intel_dp->base.ddc_bus);
+       ret = intel_ddc_get_modes(connector, &intel_dp->adapter);
        if (ret) {
                if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
                    !dev_priv->panel_fixed_mode) {
@@ -1705,7 +1705,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
        intel_dp_i2c_init(intel_dp, intel_connector, name);
 
-       intel_encoder->ddc_bus = &intel_dp->adapter;
        intel_encoder->hot_plug = intel_dp_hot_plug;
 
        if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {
index 8fe6b730c67933197359fd0d0619518f5d546097..60ce9305e7725af76141017fbe6e8174ef62c11a 100644 (file)
@@ -26,8 +26,6 @@
 #define __INTEL_DRV_H__
 
 #include <linux/i2c.h>
-#include <linux/i2c-id.h>
-#include <linux/i2c-algo-bit.h>
 #include "i915_drv.h"
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
@@ -127,13 +125,6 @@ intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode)
        return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK) >> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT;
 }
 
-struct intel_i2c_chan {
-       struct intel_encoder *encoder;
-       u32 reg; /* GPIO reg */
-       struct i2c_adapter adapter;
-       struct i2c_algo_bit_data algo;
-};
-
 struct intel_framebuffer {
        struct drm_framebuffer base;
        struct drm_gem_object *obj;
@@ -149,8 +140,6 @@ struct intel_fbdev {
 struct intel_encoder {
        struct drm_encoder base;
        int type;
-       struct i2c_adapter *i2c_bus;
-       struct i2c_adapter *ddc_bus;
        bool load_detect_temp;
        bool needs_tv_clock;
        void (*hot_plug)(struct intel_encoder *);
@@ -206,14 +195,8 @@ struct intel_unpin_work {
        bool enable_stall_check;
 };
 
-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);
-extern bool intel_ddc_probe(struct intel_encoder *intel_encoder);
-void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
-void intel_i2c_reset_gmbus(struct drm_device *dev);
+extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
 
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
index d8a586b41275d27a0e9bbe35087232e40dd897d0..1ee0dbbf6ee1d41fb96c13fc30002194b9feea9b 100644 (file)
@@ -72,7 +72,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
                .name = "ch7017",
                .dvo_reg = DVOC,
                .slave_addr = 0x75,
-               .gpio = GPIOE,
+               .gpio = GMBUS_PORT_DPD,
                .dev_ops = &ch7017_ops,
        }
 };
@@ -81,6 +81,7 @@ struct intel_dvo {
        struct intel_encoder base;
 
        struct intel_dvo_device dev;
+       int ddc_bus;
 
        struct drm_display_mode *panel_fixed_mode;
        bool panel_wants_dither;
@@ -235,13 +236,15 @@ static enum drm_connector_status intel_dvo_detect(struct drm_connector *connecto
 static int intel_dvo_get_modes(struct drm_connector *connector)
 {
        struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
+       struct drm_i915_private *dev_priv = connector->dev->dev_private;
 
        /* We should probably have an i2c driver get_modes function for those
         * devices which will have a fixed set of modes determined by the chip
         * (TV-out, for example), but for now with just TMDS and LVDS,
         * that's not the case.
         */
-       intel_ddc_get_modes(connector, intel_dvo->base.ddc_bus);
+       intel_ddc_get_modes(connector,
+                           &dev_priv->gmbus[intel_dvo->ddc_bus].adapter);
        if (!list_empty(&connector->probed_modes))
                return 1;
 
@@ -341,10 +344,10 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
 
 void intel_dvo_init(struct drm_device *dev)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *intel_encoder;
        struct intel_dvo *intel_dvo;
        struct intel_connector *intel_connector;
-       struct i2c_adapter *i2cbus = NULL;
        int ret = 0;
        int i;
        int encoder_type = DRM_MODE_ENCODER_NONE;
@@ -364,15 +367,13 @@ void intel_dvo_init(struct drm_device *dev)
                         &intel_dvo_enc_funcs, encoder_type);
 
        /* Set up the DDC bus */
-       intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
-                                                 GPIOD, "DVODDC_D");
-       if (!intel_encoder->ddc_bus)
-               goto free_intel;
+       intel_dvo->ddc_bus = GMBUS_PORT_DPB;
 
        /* Now, try to find a controller */
        for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
                struct drm_connector *connector = &intel_connector->base;
                const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
+               struct i2c_adapter *i2c;
                int gpio;
 
                /* Allow the I2C driver info to specify the GPIO to be used in
@@ -382,23 +383,18 @@ void intel_dvo_init(struct drm_device *dev)
                if (dvo->gpio != 0)
                        gpio = dvo->gpio;
                else if (dvo->type == INTEL_DVO_CHIP_LVDS)
-                       gpio = GPIOB;
+                       gpio = GMBUS_PORT_PANEL;
                else
-                       gpio = GPIOE;
+                       gpio = GMBUS_PORT_DPD;
 
                /* Set up the I2C bus necessary for the chip we're probing.
                 * It appears that everything is on GPIOE except for panels
                 * on i830 laptops, which are on GPIOB (DVOA).
                 */
-               if (i2cbus != NULL)
-                       intel_i2c_destroy(i2cbus);
-               i2cbus = intel_i2c_create(intel_encoder, gpio,
-                                         gpio == GPIOB ?  "DVOI2C_B" : "DVOI2C_E");
-               if (i2cbus == NULL)
-                       continue;
+               i2c = &dev_priv->gmbus[gpio].adapter;
 
                intel_dvo->dev = *dvo;
-               ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus);
+               ret = dvo->dev_ops->init(&intel_dvo->dev, i2c);
                if (!ret)
                        continue;
 
@@ -451,11 +447,6 @@ void intel_dvo_init(struct drm_device *dev)
                return;
        }
 
-       intel_i2c_destroy(intel_encoder->ddc_bus);
-       /* Didn't find a chip, so tear down. */
-       if (i2cbus != NULL)
-               intel_i2c_destroy(i2cbus);
-free_intel:
        drm_encoder_cleanup(&intel_encoder->base);
        kfree(intel_dvo);
        kfree(intel_connector);
index 783924c7682ac4a95b173715f0cdf9f5a02319e9..f814cb035e01de4cc6f2b5f75285dec0479f7d21 100644 (file)
@@ -40,6 +40,7 @@
 struct intel_hdmi {
        struct intel_encoder base;
        u32 sdvox_reg;
+       int ddc_bus;
        bool has_hdmi_sink;
 };
 
@@ -148,11 +149,13 @@ static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector)
 {
        struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-       struct edid *edid = NULL;
+       struct drm_i915_private *dev_priv = connector->dev->dev_private;
+       struct edid *edid;
        enum drm_connector_status status = connector_status_disconnected;
 
        intel_hdmi->has_hdmi_sink = false;
-       edid = drm_get_edid(connector, intel_hdmi->base.ddc_bus);
+       edid = drm_get_edid(connector,
+                           &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
 
        if (edid) {
                if (edid->input & DRM_EDID_INPUT_DIGITAL) {
@@ -169,12 +172,14 @@ intel_hdmi_detect(struct drm_connector *connector)
 static int intel_hdmi_get_modes(struct drm_connector *connector)
 {
        struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+       struct drm_i915_private *dev_priv = connector->dev->dev_private;
 
        /* We should parse the EDID data and find out if it's an HDMI sink so
         * we can send audio to it.
         */
 
-       return intel_ddc_get_modes(connector, intel_hdmi->base.ddc_bus);
+       return intel_ddc_get_modes(connector,
+                                  &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
 }
 
 static void intel_hdmi_destroy(struct drm_connector *connector)
@@ -246,32 +251,25 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
        /* 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(intel_encoder,
-                                                         GPIOE, "HDMIB");
+               intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
                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(intel_encoder,
-                                                         GPIOD, "HDMIC");
+               intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
                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(intel_encoder,
-                                                         PCH_GPIOE, "HDMIB");
+               intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
                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(intel_encoder,
-                                                         PCH_GPIOD, "HDMIC");
+               intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
                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(intel_encoder,
-                                                         PCH_GPIOF, "HDMID");
+               intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
                dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
        }
-       if (!intel_encoder->ddc_bus)
-               goto err_connector;
 
        intel_hdmi->sdvox_reg = sdvox_reg;
 
@@ -288,14 +286,4 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
                u32 temp = I915_READ(PEG_BAND_GAP_DATA);
                I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
        }
-
-       return;
-
-err_connector:
-       drm_encoder_cleanup(&intel_encoder->base);
-       drm_connector_cleanup(connector);
-       kfree(intel_hdmi);
-       kfree(intel_connector);
-
-       return;
 }
index d3d65a9cfba14bde84bc579459f35c6c586e935e..6f4d128935acb0a542a6f0e2ff74cae70afa781b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
- * Copyright Â© 2006-2008 Intel Corporation
+ * Copyright Â© 2006-2008,2010 Intel Corporation
  *   Jesse Barnes <jesse.barnes@intel.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  *
  * Authors:
  *     Eric Anholt <eric@anholt.net>
+ *     Chris Wilson <chris@chris-wilson.co.uk>
  */
 #include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/i2c-id.h>
 #include <linux/i2c-algo-bit.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
+/* Intel GPIO access functions */
+
+#define I2C_RISEFALL_TIME 20
+
+struct intel_gpio {
+       struct i2c_adapter adapter;
+       struct i2c_algo_bit_data algo;
+       struct drm_i915_private *dev_priv;
+       u32 reg;
+};
+
+void
+intel_i2c_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       if (HAS_PCH_SPLIT(dev))
+               I915_WRITE(PCH_GMBUS0, 0);
+       else
+               I915_WRITE(GMBUS0, 0);
+}
+
+static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
+{
        u32 val;
 
        /* When using bit bashing for I2C, this bit needs to be set to 1 */
-       if (!IS_PINEVIEW(dev))
+       if (!IS_PINEVIEW(dev_priv->dev))
                return;
 
        val = I915_READ(DSPCLK_GATE_D);
@@ -52,42 +71,30 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
        I915_WRITE(DSPCLK_GATE_D, val);
 }
 
-/*
- * Intel GPIO access functions
- */
-
-#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 = get_dev_priv(chan);
-       return (I915_READ(chan->reg) & GPIO_CLOCK_VAL_IN) != 0;
+       struct intel_gpio *gpio = data;
+       struct drm_i915_private *dev_priv = gpio->dev_priv;
+       return (I915_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
 }
 
 static int get_data(void *data)
 {
-       struct intel_i2c_chan *chan = data;
-       struct drm_i915_private *dev_priv = get_dev_priv(chan);
-       return (I915_READ(chan->reg) & GPIO_DATA_VAL_IN) != 0;
+       struct intel_gpio *gpio = data;
+       struct drm_i915_private *dev_priv = gpio->dev_priv;
+       return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
 }
 
 static void set_clock(void *data, int state_high)
 {
-       struct intel_i2c_chan *chan = data;
-       struct drm_i915_private *dev_priv = get_dev_priv(chan);
+       struct intel_gpio *gpio = data;
+       struct drm_i915_private *dev_priv = gpio->dev_priv;
        struct drm_device *dev = dev_priv->dev;
        u32 reserved = 0, clock_bits;
 
        /* On most chips, these bits must be preserved in software. */
        if (!IS_I830(dev) && !IS_845G(dev))
-               reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+               reserved = I915_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE |
                                                   GPIO_CLOCK_PULLUP_DISABLE);
 
        if (state_high)
@@ -95,20 +102,21 @@ static void set_clock(void *data, int state_high)
        else
                clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
                        GPIO_CLOCK_VAL_MASK;
-       I915_WRITE(chan->reg, reserved | clock_bits);
-       POSTING_READ(chan->reg);
+
+       I915_WRITE(gpio->reg, reserved | clock_bits);
+       POSTING_READ(gpio->reg);
 }
 
 static void set_data(void *data, int state_high)
 {
-       struct intel_i2c_chan *chan = data;
-       struct drm_i915_private *dev_priv = get_dev_priv(chan);
+       struct intel_gpio *gpio = data;
+       struct drm_i915_private *dev_priv = gpio->dev_priv;
        struct drm_device *dev = dev_priv->dev;
        u32 reserved = 0, data_bits;
 
        /* On most chips, these bits must be preserved in software. */
        if (!IS_I830(dev) && !IS_845G(dev))
-               reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+               reserved = I915_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE |
                                                   GPIO_CLOCK_PULLUP_DISABLE);
 
        if (state_high)
@@ -117,111 +125,258 @@ static void set_data(void *data, int state_high)
                data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
                        GPIO_DATA_VAL_MASK;
 
-       I915_WRITE(chan->reg, reserved | data_bits);
-       POSTING_READ(chan->reg);
+       I915_WRITE(gpio->reg, reserved | data_bits);
+       POSTING_READ(gpio->reg);
 }
 
-/* Clears the GMBUS setup.  Our driver doesn't make use of the GMBUS I2C
- * engine, but if the BIOS leaves it enabled, then that can break our use
- * of the bit-banging I2C interfaces.  This is notably the case with the
- * Mac Mini in EFI mode.
- */
-void
-intel_i2c_reset_gmbus(struct drm_device *dev)
+static struct i2c_adapter *
+intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       static const int map_pin_to_reg[] = {
+               0,
+               GPIOB,
+               GPIOA,
+               GPIOC,
+               GPIOD,
+               GPIOE,
+               GPIOF,
+       };
+       struct intel_gpio *gpio;
 
-       if (HAS_PCH_SPLIT(dev))
-               I915_WRITE(PCH_GMBUS0, 0);
-       else
-               I915_WRITE(GMBUS0, 0);
-}
+       if (pin < 1 || pin > 7)
+               return NULL;
 
-/**
- * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
- * @dev: DRM device
- * @output: driver specific output device
- * @reg: GPIO reg to use
- * @name: name for this bus
- * @slave_addr: slave address (if fixed)
- *
- * Creates and registers a new i2c bus with the Linux i2c layer, for use
- * in output probing and control (e.g. DDC or SDVO control functions).
- *
- * Possible values for @reg include:
- *   %GPIOA
- *   %GPIOB
- *   %GPIOC
- *   %GPIOD
- *   %GPIOE
- *   %GPIOF
- *   %GPIOG
- *   %GPIOH
- * see PRM for details on how these different busses are used.
- */
-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;
+       gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL);
+       if (gpio == NULL)
+               return NULL;
 
-       chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL);
-       if (!chan)
-               goto out_free;
+       gpio->reg = map_pin_to_reg[pin];
+       if (HAS_PCH_SPLIT(dev_priv->dev))
+               gpio->reg += PCH_GPIOA - GPIOA;
+       gpio->dev_priv = dev_priv;
 
-       chan->encoder = encoder;
-       chan->reg = reg;
-       snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
-       chan->adapter.owner = THIS_MODULE;
-       chan->adapter.algo_data = &chan->algo;
-       chan->adapter.dev.parent = &dev->pdev->dev;
-       chan->algo.setsda = set_data;
-       chan->algo.setscl = set_clock;
-       chan->algo.getsda = get_data;
-       chan->algo.getscl = get_clock;
-       chan->algo.udelay = I2C_RISEFALL_TIME;
-       chan->algo.timeout = usecs_to_jiffies(2200);
-       chan->algo.data = chan;
-
-       i2c_set_adapdata(&chan->adapter, chan);
-
-       if (i2c_bit_add_bus(&chan->adapter))
+       snprintf(gpio->adapter.name, I2C_NAME_SIZE, "GPIO %d", pin);
+       gpio->adapter.owner = THIS_MODULE;
+       gpio->adapter.algo_data = &gpio->algo;
+       gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev;
+       gpio->algo.setsda = set_data;
+       gpio->algo.setscl = set_clock;
+       gpio->algo.getsda = get_data;
+       gpio->algo.getscl = get_clock;
+       gpio->algo.udelay = I2C_RISEFALL_TIME;
+       gpio->algo.timeout = usecs_to_jiffies(2200);
+       gpio->algo.data = gpio;
+
+       if (i2c_bit_add_bus(&gpio->adapter))
                goto out_free;
 
-       intel_i2c_reset_gmbus(dev);
+       intel_i2c_reset(dev_priv->dev);
 
        /* JJJ:  raise SCL and SDA? */
-       intel_i2c_quirk_set(dev, true);
-       set_data(chan, 1);
+       intel_i2c_quirk_set(dev_priv, true);
+       set_data(gpio, 1);
        udelay(I2C_RISEFALL_TIME);
-       set_clock(chan, 1);
+       set_clock(gpio, 1);
        udelay(I2C_RISEFALL_TIME);
-       intel_i2c_quirk_set(dev, false);
+       intel_i2c_quirk_set(dev_priv, false);
 
-       return &chan->adapter;
+       return &gpio->adapter;
 
 out_free:
-       kfree(chan);
+       kfree(gpio);
        return NULL;
 }
 
+static int
+quirk_i2c_transfer(struct drm_i915_private *dev_priv,
+                  struct i2c_adapter *adapter,
+                  struct i2c_msg *msgs,
+                  int num)
+{
+       int ret;
+
+       intel_i2c_reset(dev_priv->dev);
+
+       intel_i2c_quirk_set(dev_priv, true);
+       ret = i2c_transfer(adapter, msgs, num);
+       intel_i2c_quirk_set(dev_priv, false);
+
+       return ret;
+}
+
+static int
+gmbus_xfer(struct i2c_adapter *adapter,
+          struct i2c_msg *msgs,
+          int num)
+{
+       struct intel_gmbus *bus = container_of(adapter,
+                                              struct intel_gmbus,
+                                              adapter);
+       struct drm_i915_private *dev_priv = adapter->algo_data;
+       int i, speed, reg_offset;
+
+       if (bus->force_bitbanging)
+               return quirk_i2c_transfer(dev_priv, bus->force_bitbanging, msgs, num);
+
+       reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0;
+
+       speed = GMBUS_RATE_100KHZ;
+       if (INTEL_INFO(dev_priv->dev)->gen > 4 || IS_G4X(dev_priv->dev)) {
+               if (bus->pin == GMBUS_PORT_DPB) /* SDVO only? */
+                       speed = GMBUS_RATE_1MHZ;
+               else
+                       speed = GMBUS_RATE_400KHZ;
+       }
+       I915_WRITE(GMBUS0 + reg_offset, speed | bus->pin);
+
+       for (i = 0; i < num; i++) {
+               u16 len = msgs[i].len;
+               u8 *buf = msgs[i].buf;
+
+               if (msgs[i].flags & I2C_M_RD) {
+                       I915_WRITE(GMBUS1 + reg_offset,
+                                  GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
+                                  (len << GMBUS_BYTE_COUNT_SHIFT) |
+                                  (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                                  GMBUS_SLAVE_READ | GMBUS_SW_RDY);
+                       do {
+                               u32 val, loop = 0;
+
+                               if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
+                                       goto timeout;
+                               if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
+                                       return 0;
+
+                               val = I915_READ(GMBUS3 + reg_offset);
+                               do {
+                                       *buf++ = val & 0xff;
+                                       val >>= 8;
+                               } while (--len && ++loop < 4);
+                       } while (len);
+               } else {
+                       u32 val = 0, loop = 0;
+
+                       BUG_ON(msgs[i].len > 4);
+
+                       do {
+                               val |= *buf++ << (loop*8);
+                       } while (--len && +loop < 4);
+
+                       I915_WRITE(GMBUS3 + reg_offset, val);
+                       I915_WRITE(GMBUS1 + reg_offset,
+                                  (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT ) |
+                                  (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |
+                                  (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                                  GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
+               }
+
+               if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50))
+                       goto timeout;
+               if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
+                       return 0;
+       }
+
+       return num;
+
+timeout:
+       DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d\n", bus->pin);
+       /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
+       bus->force_bitbanging = intel_gpio_create(dev_priv, bus->pin);
+       if (!bus->force_bitbanging)
+               return -ENOMEM;
+
+       return quirk_i2c_transfer(dev_priv, bus->force_bitbanging, msgs, num);
+}
+
+static u32 gmbus_func(struct i2c_adapter *adapter)
+{
+       return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+               /* I2C_FUNC_10BIT_ADDR | */
+               I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+               I2C_FUNC_SMBUS_BLOCK_PROC_CALL);
+}
+
+static const struct i2c_algorithm gmbus_algorithm = {
+       .master_xfer    = gmbus_xfer,
+       .functionality  = gmbus_func
+};
+
 /**
- * intel_i2c_destroy - unregister and free i2c bus resources
- * @output: channel to free
- *
- * Unregister the adapter from the i2c layer, then free the structure.
+ * intel_gmbus_setup - instantiate all Intel i2c GMBuses
+ * @dev: DRM device
  */
-void intel_i2c_destroy(struct i2c_adapter *adapter)
+int intel_setup_gmbus(struct drm_device *dev)
+{
+       static const char *names[] = {
+               "disabled",
+               "ssc",
+               "vga",
+               "panel",
+               "dpc",
+               "dpb",
+               "dpd",
+               "reserved"
+       };
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret, i;
+
+       dev_priv->gmbus = kcalloc(sizeof(struct intel_gmbus), GMBUS_NUM_PORTS,
+                                 GFP_KERNEL);
+       if (dev_priv->gmbus == NULL)
+               return -ENOMEM;
+
+       for (i = 0; i < GMBUS_NUM_PORTS; i++) {
+               struct intel_gmbus *bus = &dev_priv->gmbus[i];
+
+               bus->adapter.owner = THIS_MODULE;
+               bus->adapter.class = I2C_CLASS_DDC;
+               snprintf(bus->adapter.name,
+                        I2C_NAME_SIZE,
+                        "gmbus %s",
+                        names[i]);
+
+               bus->adapter.dev.parent = &dev->pdev->dev;
+               bus->adapter.algo_data  = dev_priv;
+
+               bus->adapter.algo = &gmbus_algorithm;
+               ret = i2c_add_adapter(&bus->adapter);
+               if (ret)
+                       goto err;
+
+               bus->pin = i;
+       }
+
+       intel_i2c_reset(dev_priv->dev);
+
+       return 0;
+
+err:
+       while (--i) {
+               struct intel_gmbus *bus = &dev_priv->gmbus[i];
+               i2c_del_adapter(&bus->adapter);
+       }
+       kfree(dev_priv->gmbus);
+       dev_priv->gmbus = NULL;
+       return ret;
+}
+
+void intel_teardown_gmbus(struct drm_device *dev)
 {
-       struct intel_i2c_chan *chan;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int i;
 
-       if (!adapter)
+       if (dev_priv->gmbus == NULL)
                return;
 
-       chan = container_of(adapter,
-                           struct intel_i2c_chan,
-                           adapter);
-       i2c_del_adapter(&chan->adapter);
-       kfree(chan);
+       for (i = 0; i < GMBUS_NUM_PORTS; i++) {
+               struct intel_gmbus *bus = &dev_priv->gmbus[i];
+               if (bus->force_bitbanging) {
+                       i2c_del_adapter(bus->force_bitbanging);
+                       kfree(bus->force_bitbanging);
+               }
+               i2c_del_adapter(&bus->adapter);
+       }
+
+       kfree(dev_priv->gmbus);
+       dev_priv->gmbus = NULL;
 }
index 2ff4a5cb2d566dd9556b9e607a08a8f3a3200e90..9177c17853e56c154df3906fbc370ef1667b1057 100644 (file)
@@ -474,11 +474,12 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
 {
        struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
        struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_display_mode *mode;
 
        if (intel_lvds->edid_good) {
                int ret = intel_ddc_get_modes(connector,
-                                             intel_lvds->base.ddc_bus);
+                                             &dev_priv->gmbus[GMBUS_PORT_PANEL].adapter);
                if (ret)
                        return ret;
        }
@@ -898,21 +899,12 @@ void intel_lvds_init(struct drm_device *dev)
         *    if closed, act like it's not there for now
         */
 
-       /* Set up the DDC bus. */
-       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");
-               goto failed;
-       }
-
        /*
         * Attempt to get the fixed panel mode from DDC.  Assume that the
         * preferred mode is the right one.
         */
        intel_lvds->edid_good = true;
-       if (!intel_ddc_get_modes(connector, intel_encoder->ddc_bus))
+       if (!intel_ddc_get_modes(connector, &dev_priv->gmbus[GMBUS_PORT_PANEL].adapter))
                intel_lvds->edid_good = false;
 
        if (!intel_lvds->edid_good) {
@@ -999,8 +991,6 @@ out:
 
 failed:
        DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
-       if (intel_encoder->ddc_bus)
-               intel_i2c_destroy(intel_encoder->ddc_bus);
        drm_connector_cleanup(connector);
        drm_encoder_cleanup(encoder);
        kfree(intel_lvds);
index 1138aa98573d3679ab63dd3ca83c81da6f3f130e..f70b7cf32bffc43a4325233e0ba11ab5726ce64f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
- * Copyright (c) 2007 Intel Corporation
+ * Copyright (c) 2007, 2010 Intel Corporation
  *   Jesse Barnes <jesse.barnes@intel.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * intel_ddc_probe
  *
  */
-bool intel_ddc_probe(struct intel_encoder *intel_encoder)
+bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus)
 {
+       struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
        u8 out_buf[] = { 0x0, 0x0};
        u8 buf[2];
-       int ret;
        struct i2c_msg msgs[] = {
                {
                        .addr = 0x50,
@@ -54,13 +54,7 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder)
                }
        };
 
-       intel_i2c_quirk_set(intel_encoder->base.dev, true);
-       ret = i2c_transfer(intel_encoder->ddc_bus, msgs, 2);
-       intel_i2c_quirk_set(intel_encoder->base.dev, false);
-       if (ret == 2)
-               return true;
-
-       return false;
+       return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2;
 }
 
 /**
@@ -76,9 +70,7 @@ int intel_ddc_get_modes(struct drm_connector *connector,
        struct edid *edid;
        int ret = 0;
 
-       intel_i2c_quirk_set(connector->dev, true);
        edid = drm_get_edid(connector, adapter);
-       intel_i2c_quirk_set(connector->dev, false);
        if (edid) {
                drm_mode_connector_update_edid_property(connector, edid);
                ret = drm_add_edid_modes(connector, edid);
index f7030e4810833f3577a1f952c702764cda24b9cb..2b3b4754c97d4ed43672410a0f6a21b45b1df41e 100644 (file)
@@ -65,6 +65,7 @@ static const char *tv_format_names[] = {
 struct intel_sdvo {
        struct intel_encoder base;
 
+       struct i2c_adapter *i2c;
        u8 slave_addr;
 
        /* Register for the SDVO device: SDVOB or SDVOC */
@@ -264,7 +265,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch)
        };
        int ret;
 
-       if ((ret = i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 2)) == 2)
+       if ((ret = i2c_transfer(intel_sdvo->i2c, msgs, 2)) == 2)
        {
                *ch = buf[0];
                return true;
@@ -286,7 +287,7 @@ static bool intel_sdvo_write_byte(struct intel_sdvo *intel_sdvo, int addr, u8 ch
                }
        };
 
-       return i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 1) == 1;
+       return i2c_transfer(intel_sdvo->i2c, msgs, 1) == 1;
 }
 
 #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
@@ -566,7 +567,7 @@ static int intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo,
        ret_value[0] = 0;
        ret_value[1] = 0;
 
-       ret = i2c_transfer(intel_sdvo->base.i2c_bus, msgs, 3);
+       ret = i2c_transfer(intel_sdvo->i2c, msgs, 3);
        if (ret < 0)
                return ret;
        if (ret != 3) {
@@ -1375,6 +1376,19 @@ intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
        return (caps > 1);
 }
 
+static struct edid *
+intel_sdvo_get_edid(struct drm_connector *connector, int ddc)
+{
+       struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
+       int ret;
+
+       ret = intel_sdvo_set_control_bus_switch(intel_sdvo, ddc);
+       if (ret)
+               return NULL;
+
+       return drm_get_edid(connector, intel_sdvo->i2c);
+}
+
 static struct drm_connector *
 intel_find_analog_connector(struct drm_device *dev)
 {
@@ -1418,28 +1432,12 @@ intel_analog_is_connected(struct drm_device *dev)
 static struct edid *
 intel_sdvo_get_analog_edid(struct drm_connector *connector)
 {
-       struct intel_encoder *encoder = intel_attached_encoder(connector);
-       struct drm_device *dev = connector->dev;
-       struct i2c_adapter *ddc;
-       struct edid *edid;
-       u32 ddc_reg;
-
-       if (!intel_analog_is_connected(dev))
-               return NULL;
-
-       if (HAS_PCH_SPLIT(dev))
-               ddc_reg = PCH_GPIOA;
-       else
-               ddc_reg = GPIOA;
+       struct drm_i915_private *dev_priv = connector->dev->dev_private;
 
-       ddc = intel_i2c_create(encoder, ddc_reg, "SDVO/VGA DDC BUS");
-       if (ddc == NULL)
+       if (!intel_analog_is_connected(connector->dev))
                return NULL;
 
-       edid = drm_get_edid(connector, ddc);
-       intel_i2c_destroy(ddc);
-
-       return edid;
+       return drm_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
 }
 
 enum drm_connector_status
@@ -1449,28 +1447,26 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
        enum drm_connector_status status;
        struct edid *edid;
 
-       edid = drm_get_edid(connector, intel_sdvo->base.ddc_bus);
+       edid = intel_sdvo_get_edid(connector, intel_sdvo->ddc_bus);
 
        if (edid == NULL && intel_sdvo_multifunc_encoder(intel_sdvo)) {
-               u8 saved_ddc = intel_sdvo->ddc_bus, ddc;
+               u8 ddc;
 
                /*
                 * Don't use the 1 as the argument of DDC bus switch to get
                 * the EDID. It is used for SDVO SPD ROM.
                 */
                for (ddc = intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) {
-                       intel_sdvo->ddc_bus = ddc;
-                       edid = drm_get_edid(connector, intel_sdvo->base.ddc_bus);
-                       if (edid)
+                       edid = intel_sdvo_get_edid(connector, ddc);
+                       if (edid) {
+                               /*
+                                * If we found the EDID on the other bus,
+                                * assume that is the correct DDC bus.
+                                */
+                               intel_sdvo->ddc_bus = ddc;
                                break;
+                       }
                }
-
-               /*
-                * If we found the EDID on the other bus, maybe that is the
-                * correct DDC bus.
-                */
-               if (edid == NULL)
-                       intel_sdvo->ddc_bus = saved_ddc;
        }
 
        /*
@@ -1546,12 +1542,9 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
 {
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
        struct edid *edid;
-       int num_modes;
 
        /* set the bus switch and get the modes */
-       num_modes = intel_ddc_get_modes(connector, intel_sdvo->base.ddc_bus);
-       if (num_modes)
-               return;
+       edid = intel_sdvo_get_edid(connector, intel_sdvo->ddc_bus);
 
        /*
         * Mac mini hack.  On this device, the DVI-I connector shares one DDC
@@ -1559,7 +1552,9 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
         * DDC fails, check to see if the analog output is disconnected, in
         * which case we'll look there for the digital DDC data.
         */
-       edid = intel_sdvo_get_analog_edid(connector);
+       if (edid == NULL)
+               edid = intel_sdvo_get_analog_edid(connector);
+
        if (edid != NULL) {
                drm_mode_connector_update_edid_property(connector, edid);
                drm_add_edid_modes(connector, edid);
@@ -1678,7 +1673,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
         * Assume that the preferred modes are
         * arranged in priority order.
         */
-       intel_ddc_get_modes(connector, intel_sdvo->base.ddc_bus);
+       intel_ddc_get_modes(connector, intel_sdvo->i2c);
        if (list_empty(&connector->probed_modes) == false)
                goto end;
 
@@ -2004,30 +1999,6 @@ intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device)
                                     &intel_sdvo->is_hdmi, 1);
 }
 
-static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
-                                 struct i2c_msg msgs[], int num)
-{
-       struct intel_sdvo *intel_sdvo;
-       const struct i2c_algorithm *algo;
-       int ret;
-
-       intel_sdvo = container_of(i2c_adap->algo_data,
-                                 struct intel_sdvo,
-                                 base);
-       algo = intel_sdvo->base.i2c_bus->algo;
-
-       ret = intel_sdvo_set_control_bus_switch(intel_sdvo,
-                                               intel_sdvo->ddc_bus);
-       if (ret)
-               return ret;
-
-       return algo->master_xfer(i2c_adap, msgs, num);
-}
-
-static struct i2c_algorithm intel_sdvo_i2c_bit_algo = {
-       .master_xfer    = intel_sdvo_master_xfer,
-};
-
 static u8
 intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg)
 {
@@ -2540,9 +2511,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *intel_encoder;
        struct intel_sdvo *intel_sdvo;
-       u8 ch[0x40];
        int i;
-       u32 i2c_reg, ddc_reg;
 
        intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
        if (!intel_sdvo)
@@ -2555,82 +2524,49 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
        /* encoder type will be decided later */
        drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0);
 
-       if (HAS_PCH_SPLIT(dev)) {
-               i2c_reg = PCH_GPIOE;
-               ddc_reg = PCH_GPIOE;
-       } else {
-               i2c_reg = GPIOE;
-               ddc_reg = GPIOE;
-       }
-
-       /* setup the DDC bus. */
-       if (IS_SDVOB(sdvo_reg))
-               intel_encoder->i2c_bus =
-                       intel_i2c_create(intel_encoder,
-                                        i2c_reg, "SDVOCTRL_E for SDVOB");
-       else
-               intel_encoder->i2c_bus =
-                       intel_i2c_create(intel_encoder,
-                                        i2c_reg, "SDVOCTRL_E for SDVOC");
-
-       if (!intel_encoder->i2c_bus)
-               goto err_inteloutput;
+       intel_sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
 
        intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg);
 
-       /* Save the bit-banging i2c functionality for use by the DDC wrapper */
-       intel_sdvo_i2c_bit_algo.functionality = intel_encoder->i2c_bus->algo->functionality;
-
        /* Read the regs to test if we can talk to the device */
        for (i = 0; i < 0x40; i++) {
-               if (!intel_sdvo_read_byte(intel_sdvo, i, &ch[i])) {
+               u8 byte;
+
+               if (!intel_sdvo_read_byte(intel_sdvo, i, &byte)) {
                        DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n",
                                      IS_SDVOB(sdvo_reg) ? 'B' : 'C');
-                       goto err_i2c;
+                       goto err;
                }
        }
 
-       /* setup the DDC bus. */
-       if (IS_SDVOB(sdvo_reg)) {
-               intel_encoder->ddc_bus =
-                       intel_i2c_create(intel_encoder,
-                                        ddc_reg, "SDVOB DDC BUS");
+       if (IS_SDVOB(sdvo_reg))
                dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
-       } else {
-               intel_encoder->ddc_bus =
-                       intel_i2c_create(intel_encoder,
-                                        ddc_reg, "SDVOC DDC BUS");
+       else
                dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
-       }
-       if (intel_encoder->ddc_bus == NULL)
-               goto err_i2c;
-
-       /* Wrap with our custom algo which switches to DDC mode */
-       intel_encoder->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
 
        drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
 
        /* In default case sdvo lvds is false */
        if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
-               goto err_i2c;
+               goto err;
 
        if (intel_sdvo_output_setup(intel_sdvo,
                                    intel_sdvo->caps.output_flags) != true) {
                DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",
                              IS_SDVOB(sdvo_reg) ? 'B' : 'C');
-               goto err_i2c;
+               goto err;
        }
 
        intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
 
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
-               goto err_i2c;
+               goto err;
 
        if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,
                                                    &intel_sdvo->pixel_clock_min,
                                                    &intel_sdvo->pixel_clock_max))
-               goto err_i2c;
+               goto err;
 
        DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
                        "clock range %dMHz - %dMHz, "
@@ -2650,12 +2586,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
                        (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
        return true;
 
-err_i2c:
-       if (intel_encoder->ddc_bus != NULL)
-               intel_i2c_destroy(intel_encoder->ddc_bus);
-       if (intel_encoder->i2c_bus != NULL)
-               intel_i2c_destroy(intel_encoder->i2c_bus);
-err_inteloutput:
+err:
        drm_encoder_cleanup(&intel_encoder->base);
        kfree(intel_sdvo);