提交 f899fc64 编写于 作者: C Chris Wilson

drm/i915: use GMBUS to manage i2c links

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: NChris Wilson <chris@chris-wilson.co.uk>
上级 373a3cf7
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include "drmP.h" #include "drmP.h"
#include "drm_edid.h" #include "drm_edid.h"
#include "drm_edid_modes.h" #include "drm_edid_modes.h"
......
...@@ -168,7 +168,6 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); ...@@ -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) static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
{ {
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
u8 in_buf[2]; u8 in_buf[2];
...@@ -190,7 +189,7 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) ...@@ -190,7 +189,7 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
out_buf[0] = addr; out_buf[0] = addr;
out_buf[1] = 0; out_buf[1] = 0;
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { if (i2c_transfer(adapter, msgs, 2) == 2) {
*val= in_buf[0]; *val= in_buf[0];
return true; return true;
}; };
...@@ -201,7 +200,6 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) ...@@ -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) static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
{ {
struct i2c_adapter *adapter = dvo->i2c_bus; 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]; uint8_t out_buf[2];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .addr = dvo->slave_addr,
...@@ -213,7 +211,7 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) ...@@ -213,7 +211,7 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
out_buf[0] = addr; out_buf[0] = addr;
out_buf[1] = val; out_buf[1] = val;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
return false; return false;
...@@ -223,7 +221,6 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) ...@@ -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, static bool ch7017_init(struct intel_dvo_device *dvo,
struct i2c_adapter *adapter) struct i2c_adapter *adapter)
{ {
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
struct ch7017_priv *priv; struct ch7017_priv *priv;
uint8_t val; uint8_t val;
...@@ -242,7 +239,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, ...@@ -242,7 +239,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
val != CH7019_DEVICE_ID_VALUE) { val != CH7019_DEVICE_ID_VALUE) {
DRM_DEBUG_KMS("ch701x not detected, got %d: from %s " DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
"Slave %d.\n", "Slave %d.\n",
val, i2cbus->adapter.name,dvo->slave_addr); val, adapter->name,dvo->slave_addr);
goto fail; goto fail;
} }
......
...@@ -113,7 +113,6 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -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 ch7xxx_priv *ch7xxx= dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
u8 in_buf[2]; u8 in_buf[2];
...@@ -135,14 +134,14 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -135,14 +134,14 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
out_buf[0] = addr; out_buf[0] = addr;
out_buf[1] = 0; out_buf[1] = 0;
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { if (i2c_transfer(adapter, msgs, 2) == 2) {
*ch = in_buf[0]; *ch = in_buf[0];
return true; return true;
}; };
if (!ch7xxx->quiet) { if (!ch7xxx->quiet) {
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", 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; return false;
} }
...@@ -152,7 +151,6 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -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 ch7xxx_priv *ch7xxx = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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]; uint8_t out_buf[2];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .addr = dvo->slave_addr,
...@@ -164,12 +162,12 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -164,12 +162,12 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
out_buf[0] = addr; out_buf[0] = addr;
out_buf[1] = ch; out_buf[1] = ch;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
if (!ch7xxx->quiet) { if (!ch7xxx->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 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; return false;
......
...@@ -167,7 +167,6 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) ...@@ -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 ivch_priv *priv = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[1];
u8 in_buf[2]; u8 in_buf[2];
...@@ -193,7 +192,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) ...@@ -193,7 +192,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
out_buf[0] = addr; 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]; *data = (in_buf[1] << 8) | in_buf[0];
return true; return true;
}; };
...@@ -201,7 +200,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) ...@@ -201,7 +200,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
if (!priv->quiet) { if (!priv->quiet) {
DRM_DEBUG_KMS("Unable to read register 0x%02x from " DRM_DEBUG_KMS("Unable to read register 0x%02x from "
"%s:%02x.\n", "%s:%02x.\n",
addr, i2cbus->adapter.name, dvo->slave_addr); addr, adapter->name, dvo->slave_addr);
} }
return false; return false;
} }
...@@ -211,7 +210,6 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) ...@@ -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 ivch_priv *priv = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; struct i2c_adapter *adapter = dvo->i2c_bus;
struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
u8 out_buf[3]; u8 out_buf[3];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .addr = dvo->slave_addr,
...@@ -224,12 +222,12 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) ...@@ -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[1] = data & 0xff;
out_buf[2] = data >> 8; out_buf[2] = data >> 8;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
if (!priv->quiet) { if (!priv->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 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; return false;
......
...@@ -69,7 +69,6 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -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 sil164_priv *sil = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
u8 in_buf[2]; u8 in_buf[2];
...@@ -91,14 +90,14 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -91,14 +90,14 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
out_buf[0] = addr; out_buf[0] = addr;
out_buf[1] = 0; out_buf[1] = 0;
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { if (i2c_transfer(adapter, msgs, 2) == 2) {
*ch = in_buf[0]; *ch = in_buf[0];
return true; return true;
}; };
if (!sil->quiet) { if (!sil->quiet) {
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", 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; return false;
} }
...@@ -107,7 +106,6 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -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 sil164_priv *sil= dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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]; uint8_t out_buf[2];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .addr = dvo->slave_addr,
...@@ -119,12 +117,12 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -119,12 +117,12 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
out_buf[0] = addr; out_buf[0] = addr;
out_buf[1] = ch; out_buf[1] = ch;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
if (!sil->quiet) { if (!sil->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 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; return false;
......
...@@ -94,7 +94,6 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -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 tfp410_priv *tfp = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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 out_buf[2];
u8 in_buf[2]; u8 in_buf[2];
...@@ -116,14 +115,14 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) ...@@ -116,14 +115,14 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
out_buf[0] = addr; out_buf[0] = addr;
out_buf[1] = 0; out_buf[1] = 0;
if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) { if (i2c_transfer(adapter, msgs, 2) == 2) {
*ch = in_buf[0]; *ch = in_buf[0];
return true; return true;
}; };
if (!tfp->quiet) { if (!tfp->quiet) {
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", 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; return false;
} }
...@@ -132,7 +131,6 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -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 tfp410_priv *tfp = dvo->dev_priv;
struct i2c_adapter *adapter = dvo->i2c_bus; 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]; uint8_t out_buf[2];
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = dvo->slave_addr, .addr = dvo->slave_addr,
...@@ -144,12 +142,12 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) ...@@ -144,12 +142,12 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
out_buf[0] = addr; out_buf[0] = addr;
out_buf[1] = ch; out_buf[1] = ch;
if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1) if (i2c_transfer(adapter, &msg, 1) == 1)
return true; return true;
if (!tfp->quiet) { if (!tfp->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 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; return false;
......
...@@ -2001,6 +2001,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -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 */ /* Try to make sure MCHBAR is enabled before poking at it */
intel_setup_mchbar(dev); intel_setup_mchbar(dev);
intel_setup_gmbus(dev);
intel_opregion_setup(dev); intel_opregion_setup(dev);
i915_gem_load(dev); i915_gem_load(dev);
...@@ -2155,6 +2156,7 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -2155,6 +2156,7 @@ int i915_driver_unload(struct drm_device *dev)
intel_cleanup_overlay(dev); intel_cleanup_overlay(dev);
} }
intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev); intel_teardown_mchbar(dev);
destroy_workqueue(dev_priv->wq); destroy_workqueue(dev_priv->wq);
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "intel_bios.h" #include "intel_bios.h"
#include "intel_ringbuffer.h" #include "intel_ringbuffer.h"
#include <linux/io-mapping.h> #include <linux/io-mapping.h>
#include <linux/i2c.h>
#include <drm/intel-gtt.h> #include <drm/intel-gtt.h>
/* General customization: /* General customization:
...@@ -246,6 +247,12 @@ typedef struct drm_i915_private { ...@@ -246,6 +247,12 @@ typedef struct drm_i915_private {
void __iomem *regs; void __iomem *regs;
struct intel_gmbus {
struct i2c_adapter adapter;
struct i2c_adapter *force_bitbanging;
int pin;
} *gmbus;
struct pci_dev *bridge_dev; struct pci_dev *bridge_dev;
struct intel_ring_buffer render_ring; struct intel_ring_buffer render_ring;
struct intel_ring_buffer bsd_ring; struct intel_ring_buffer bsd_ring;
...@@ -339,7 +346,7 @@ typedef struct drm_i915_private { ...@@ -339,7 +346,7 @@ typedef struct drm_i915_private {
struct notifier_block lid_notifier; 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 */ struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
int num_fence_regs; /* 8 on pre-965, 16 otherwise */ int num_fence_regs; /* 8 on pre-965, 16 otherwise */
...@@ -1070,6 +1077,11 @@ extern int i915_restore_state(struct drm_device *dev); ...@@ -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_save_state(struct drm_device *dev);
extern int i915_restore_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 */ /* intel_opregion.c */
extern int intel_opregion_setup(struct drm_device *dev); extern int intel_opregion_setup(struct drm_device *dev);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
...@@ -583,12 +583,51 @@ ...@@ -583,12 +583,51 @@
# define GPIO_DATA_VAL_IN (1 << 12) # define GPIO_DATA_VAL_IN (1 << 12)
# define GPIO_DATA_PULLUP_DISABLE (1 << 13) # define GPIO_DATA_PULLUP_DISABLE (1 << 13)
#define GMBUS0 0x5100 #define GMBUS0 0x5100 /* clock/port select */
#define GMBUS1 0x5104 #define GMBUS_RATE_100KHZ (0<<8)
#define GMBUS2 0x5108 #define GMBUS_RATE_50KHZ (1<<8)
#define GMBUS3 0x510c #define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */
#define GMBUS4 0x5110 #define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */
#define GMBUS5 0x5120 #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 * Clock control & power management
......
...@@ -860,9 +860,7 @@ int i915_restore_state(struct drm_device *dev) ...@@ -860,9 +860,7 @@ int i915_restore_state(struct drm_device *dev)
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
/* I2C state */ intel_i2c_reset(dev);
intel_i2c_reset_gmbus(dev);
return 0; return 0;
} }
...@@ -291,14 +291,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv, ...@@ -291,14 +291,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
struct bdb_header *bdb) struct bdb_header *bdb)
{ {
struct bdb_general_definitions *general; struct bdb_general_definitions *general;
const int crt_bus_map_table[] = {
GPIOB,
GPIOA,
GPIOC,
GPIOD,
GPIOE,
GPIOF,
};
general = find_section(bdb, BDB_GENERAL_DEFINITIONS); general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
if (general) { if (general) {
...@@ -306,10 +298,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv, ...@@ -306,10 +298,8 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
if (block_size >= sizeof(*general)) { if (block_size >= sizeof(*general)) {
int bus_pin = general->crt_ddc_gmbus_pin; int bus_pin = general->crt_ddc_gmbus_pin;
DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
if ((bus_pin >= 1) && (bus_pin <= 6)) { if (bus_pin >= 1 && bus_pin <= 6)
dev_priv->crt_ddc_bus = dev_priv->crt_ddc_pin = bus_pin - 1;
crt_bus_map_table[bus_pin-1];
}
} else { } else {
DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
block_size); block_size);
...@@ -533,6 +523,8 @@ intel_init_bios(struct drm_device *dev) ...@@ -533,6 +523,8 @@ intel_init_bios(struct drm_device *dev)
struct bdb_header *bdb = NULL; struct bdb_header *bdb = NULL;
u8 __iomem *bios = NULL; u8 __iomem *bios = NULL;
dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC;
/* XXX Should this validation be moved to intel_opregion.c? */ /* XXX Should this validation be moved to intel_opregion.c? */
if (dev_priv->opregion.vbt) { if (dev_priv->opregion.vbt) {
struct vbt_header *vbt = dev_priv->opregion.vbt; struct vbt_header *vbt = dev_priv->opregion.vbt;
......
...@@ -264,12 +264,13 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) ...@@ -264,12 +264,13 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
static bool intel_crt_detect_ddc(struct drm_encoder *encoder) static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
{ {
struct intel_encoder *intel_encoder = to_intel_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 */ /* CRT should always be at 0, but check anyway */
if (intel_encoder->type != INTEL_OUTPUT_ANALOG) if (intel_encoder->type != INTEL_OUTPUT_ANALOG)
return false; return false;
return intel_ddc_probe(intel_encoder); return intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin);
} }
static enum drm_connector_status static enum drm_connector_status
...@@ -445,29 +446,18 @@ static void intel_crt_destroy(struct drm_connector *connector) ...@@ -445,29 +446,18 @@ static void intel_crt_destroy(struct drm_connector *connector)
static int intel_crt_get_modes(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_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret; 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)) if (ret || !IS_G4X(dev))
goto end;
/* 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 ret;
/* Try to probe digital port for output in DVI-I -> VGA mode. */
return intel_ddc_get_modes(connector,
&dev_priv->gmbus[GMBUS_PORT_DPB].adapter);
} }
static int intel_crt_set_property(struct drm_connector *connector, static int intel_crt_set_property(struct drm_connector *connector,
...@@ -513,7 +503,6 @@ void intel_crt_init(struct drm_device *dev) ...@@ -513,7 +503,6 @@ void intel_crt_init(struct drm_device *dev)
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 i2c_reg;
intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL);
if (!intel_encoder) if (!intel_encoder)
...@@ -534,27 +523,6 @@ void intel_crt_init(struct drm_device *dev) ...@@ -534,27 +523,6 @@ void intel_crt_init(struct drm_device *dev)
intel_connector_attach_encoder(intel_connector, intel_encoder); 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->type = INTEL_OUTPUT_ANALOG;
intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
(1 << INTEL_ANALOG_CLONE_BIT) | (1 << INTEL_ANALOG_CLONE_BIT) |
......
...@@ -2530,12 +2530,6 @@ void intel_encoder_destroy(struct drm_encoder *encoder) ...@@ -2530,12 +2530,6 @@ void intel_encoder_destroy(struct drm_encoder *encoder)
{ {
struct intel_encoder *intel_encoder = to_intel_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); drm_encoder_cleanup(encoder);
kfree(intel_encoder); kfree(intel_encoder);
} }
......
...@@ -1490,7 +1490,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) ...@@ -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 /* 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 (ret) {
if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) && if ((IS_eDP(intel_dp) || IS_PCH_eDP(intel_dp)) &&
!dev_priv->panel_fixed_mode) { !dev_priv->panel_fixed_mode) {
...@@ -1705,7 +1705,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) ...@@ -1705,7 +1705,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
intel_dp_i2c_init(intel_dp, intel_connector, name); intel_dp_i2c_init(intel_dp, intel_connector, name);
intel_encoder->ddc_bus = &intel_dp->adapter;
intel_encoder->hot_plug = intel_dp_hot_plug; intel_encoder->hot_plug = intel_dp_hot_plug;
if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) { if (output_reg == DP_A || IS_PCH_eDP(intel_dp)) {
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#define __INTEL_DRV_H__ #define __INTEL_DRV_H__
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "drm_crtc.h" #include "drm_crtc.h"
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
...@@ -127,13 +125,6 @@ intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode) ...@@ -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; 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 intel_framebuffer {
struct drm_framebuffer base; struct drm_framebuffer base;
struct drm_gem_object *obj; struct drm_gem_object *obj;
...@@ -149,8 +140,6 @@ struct intel_fbdev { ...@@ -149,8 +140,6 @@ struct intel_fbdev {
struct intel_encoder { struct intel_encoder {
struct drm_encoder base; struct drm_encoder base;
int type; int type;
struct i2c_adapter *i2c_bus;
struct i2c_adapter *ddc_bus;
bool load_detect_temp; bool load_detect_temp;
bool needs_tv_clock; bool needs_tv_clock;
void (*hot_plug)(struct intel_encoder *); void (*hot_plug)(struct intel_encoder *);
...@@ -206,14 +195,8 @@ struct intel_unpin_work { ...@@ -206,14 +195,8 @@ struct intel_unpin_work {
bool enable_stall_check; 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); int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
extern bool intel_ddc_probe(struct intel_encoder *intel_encoder); extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
void intel_i2c_reset_gmbus(struct drm_device *dev);
extern void intel_crt_init(struct drm_device *dev); extern void intel_crt_init(struct drm_device *dev);
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
......
...@@ -72,7 +72,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { ...@@ -72,7 +72,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
.name = "ch7017", .name = "ch7017",
.dvo_reg = DVOC, .dvo_reg = DVOC,
.slave_addr = 0x75, .slave_addr = 0x75,
.gpio = GPIOE, .gpio = GMBUS_PORT_DPD,
.dev_ops = &ch7017_ops, .dev_ops = &ch7017_ops,
} }
}; };
...@@ -81,6 +81,7 @@ struct intel_dvo { ...@@ -81,6 +81,7 @@ struct intel_dvo {
struct intel_encoder base; struct intel_encoder base;
struct intel_dvo_device dev; struct intel_dvo_device dev;
int ddc_bus;
struct drm_display_mode *panel_fixed_mode; struct drm_display_mode *panel_fixed_mode;
bool panel_wants_dither; bool panel_wants_dither;
...@@ -235,13 +236,15 @@ static enum drm_connector_status intel_dvo_detect(struct drm_connector *connecto ...@@ -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) static int intel_dvo_get_modes(struct drm_connector *connector)
{ {
struct intel_dvo *intel_dvo = intel_attached_dvo(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 /* 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 * 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, * (TV-out, for example), but for now with just TMDS and LVDS,
* that's not the case. * 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)) if (!list_empty(&connector->probed_modes))
return 1; return 1;
...@@ -341,10 +344,10 @@ intel_dvo_get_current_mode(struct drm_connector *connector) ...@@ -341,10 +344,10 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
void intel_dvo_init(struct drm_device *dev) void intel_dvo_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_dvo *intel_dvo; struct intel_dvo *intel_dvo;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct i2c_adapter *i2cbus = NULL;
int ret = 0; int ret = 0;
int i; int i;
int encoder_type = DRM_MODE_ENCODER_NONE; int encoder_type = DRM_MODE_ENCODER_NONE;
...@@ -364,15 +367,13 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -364,15 +367,13 @@ void intel_dvo_init(struct drm_device *dev)
&intel_dvo_enc_funcs, encoder_type); &intel_dvo_enc_funcs, encoder_type);
/* Set up the DDC bus */ /* Set up the DDC bus */
intel_encoder->ddc_bus = intel_i2c_create(intel_encoder, intel_dvo->ddc_bus = GMBUS_PORT_DPB;
GPIOD, "DVODDC_D");
if (!intel_encoder->ddc_bus)
goto free_intel;
/* Now, try to find a controller */ /* Now, try to find a controller */
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
struct drm_connector *connector = &intel_connector->base; struct drm_connector *connector = &intel_connector->base;
const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
struct i2c_adapter *i2c;
int gpio; int gpio;
/* Allow the I2C driver info to specify the GPIO to be used in /* 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) ...@@ -382,23 +383,18 @@ void intel_dvo_init(struct drm_device *dev)
if (dvo->gpio != 0) if (dvo->gpio != 0)
gpio = dvo->gpio; gpio = dvo->gpio;
else if (dvo->type == INTEL_DVO_CHIP_LVDS) else if (dvo->type == INTEL_DVO_CHIP_LVDS)
gpio = GPIOB; gpio = GMBUS_PORT_PANEL;
else else
gpio = GPIOE; gpio = GMBUS_PORT_DPD;
/* Set up the I2C bus necessary for the chip we're probing. /* Set up the I2C bus necessary for the chip we're probing.
* It appears that everything is on GPIOE except for panels * It appears that everything is on GPIOE except for panels
* on i830 laptops, which are on GPIOB (DVOA). * on i830 laptops, which are on GPIOB (DVOA).
*/ */
if (i2cbus != NULL) i2c = &dev_priv->gmbus[gpio].adapter;
intel_i2c_destroy(i2cbus);
i2cbus = intel_i2c_create(intel_encoder, gpio,
gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E");
if (i2cbus == NULL)
continue;
intel_dvo->dev = *dvo; intel_dvo->dev = *dvo;
ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus); ret = dvo->dev_ops->init(&intel_dvo->dev, i2c);
if (!ret) if (!ret)
continue; continue;
...@@ -451,11 +447,6 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -451,11 +447,6 @@ void intel_dvo_init(struct drm_device *dev)
return; 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); drm_encoder_cleanup(&intel_encoder->base);
kfree(intel_dvo); kfree(intel_dvo);
kfree(intel_connector); kfree(intel_connector);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
struct intel_hdmi { struct intel_hdmi {
struct intel_encoder base; struct intel_encoder base;
u32 sdvox_reg; u32 sdvox_reg;
int ddc_bus;
bool has_hdmi_sink; bool has_hdmi_sink;
}; };
...@@ -148,11 +149,13 @@ static enum drm_connector_status ...@@ -148,11 +149,13 @@ static enum drm_connector_status
intel_hdmi_detect(struct drm_connector *connector) intel_hdmi_detect(struct drm_connector *connector)
{ {
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(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; enum drm_connector_status status = connector_status_disconnected;
intel_hdmi->has_hdmi_sink = false; 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) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) { if (edid->input & DRM_EDID_INPUT_DIGITAL) {
...@@ -169,12 +172,14 @@ intel_hdmi_detect(struct drm_connector *connector) ...@@ -169,12 +172,14 @@ intel_hdmi_detect(struct drm_connector *connector)
static int intel_hdmi_get_modes(struct drm_connector *connector) static int intel_hdmi_get_modes(struct drm_connector *connector)
{ {
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(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 should parse the EDID data and find out if it's an HDMI sink so
* we can send audio to it. * 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) static void intel_hdmi_destroy(struct drm_connector *connector)
...@@ -246,32 +251,25 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -246,32 +251,25 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
/* Set up the DDC bus. */ /* Set up the DDC bus. */
if (sdvox_reg == SDVOB) { if (sdvox_reg == SDVOB) {
intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(intel_encoder, intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
GPIOE, "HDMIB");
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == SDVOC) { } else if (sdvox_reg == SDVOC) {
intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(intel_encoder, intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
GPIOD, "HDMIC");
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMIB) { } else if (sdvox_reg == HDMIB) {
intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(intel_encoder, intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
PCH_GPIOE, "HDMIB");
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMIC) { } else if (sdvox_reg == HDMIC) {
intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(intel_encoder, intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
PCH_GPIOD, "HDMIC");
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
} else if (sdvox_reg == HDMID) { } else if (sdvox_reg == HDMID) {
intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
intel_encoder->ddc_bus = intel_i2c_create(intel_encoder, intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
PCH_GPIOF, "HDMID");
dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
} }
if (!intel_encoder->ddc_bus)
goto err_connector;
intel_hdmi->sdvox_reg = sdvox_reg; intel_hdmi->sdvox_reg = sdvox_reg;
...@@ -288,14 +286,4 @@ void intel_hdmi_init(struct drm_device *dev, int 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); u32 temp = I915_READ(PEG_BAND_GAP_DATA);
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); 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;
} }
/* /*
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie> * 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> * Jesse Barnes <jesse.barnes@intel.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
...@@ -24,10 +24,9 @@ ...@@ -24,10 +24,9 @@
* *
* Authors: * Authors:
* Eric Anholt <eric@anholt.net> * Eric Anholt <eric@anholt.net>
* Chris Wilson <chris@chris-wilson.co.uk>
*/ */
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
...@@ -35,13 +34,33 @@ ...@@ -35,13 +34,33 @@
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.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; 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; u32 val;
/* When using bit bashing for I2C, this bit needs to be set to 1 */ /* 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; return;
val = I915_READ(DSPCLK_GATE_D); val = I915_READ(DSPCLK_GATE_D);
...@@ -52,42 +71,30 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable) ...@@ -52,42 +71,30 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
I915_WRITE(DSPCLK_GATE_D, val); 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) static int get_clock(void *data)
{ {
struct intel_i2c_chan *chan = data; struct intel_gpio *gpio = data;
struct drm_i915_private *dev_priv = get_dev_priv(chan); struct drm_i915_private *dev_priv = gpio->dev_priv;
return (I915_READ(chan->reg) & GPIO_CLOCK_VAL_IN) != 0; return (I915_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0;
} }
static int get_data(void *data) static int get_data(void *data)
{ {
struct intel_i2c_chan *chan = data; struct intel_gpio *gpio = data;
struct drm_i915_private *dev_priv = get_dev_priv(chan); struct drm_i915_private *dev_priv = gpio->dev_priv;
return (I915_READ(chan->reg) & GPIO_DATA_VAL_IN) != 0; return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0;
} }
static void set_clock(void *data, int state_high) static void set_clock(void *data, int state_high)
{ {
struct intel_i2c_chan *chan = data; struct intel_gpio *gpio = data;
struct drm_i915_private *dev_priv = get_dev_priv(chan); struct drm_i915_private *dev_priv = gpio->dev_priv;
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
u32 reserved = 0, clock_bits; u32 reserved = 0, clock_bits;
/* On most chips, these bits must be preserved in software. */ /* On most chips, these bits must be preserved in software. */
if (!IS_I830(dev) && !IS_845G(dev)) 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); GPIO_CLOCK_PULLUP_DISABLE);
if (state_high) if (state_high)
...@@ -95,20 +102,21 @@ static void set_clock(void *data, int state_high) ...@@ -95,20 +102,21 @@ static void set_clock(void *data, int state_high)
else else
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
GPIO_CLOCK_VAL_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) static void set_data(void *data, int state_high)
{ {
struct intel_i2c_chan *chan = data; struct intel_gpio *gpio = data;
struct drm_i915_private *dev_priv = get_dev_priv(chan); struct drm_i915_private *dev_priv = gpio->dev_priv;
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
u32 reserved = 0, data_bits; u32 reserved = 0, data_bits;
/* On most chips, these bits must be preserved in software. */ /* On most chips, these bits must be preserved in software. */
if (!IS_I830(dev) && !IS_845G(dev)) 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); GPIO_CLOCK_PULLUP_DISABLE);
if (state_high) if (state_high)
...@@ -117,111 +125,258 @@ static void set_data(void *data, int 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 | data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
GPIO_DATA_VAL_MASK; GPIO_DATA_VAL_MASK;
I915_WRITE(chan->reg, reserved | data_bits); I915_WRITE(gpio->reg, reserved | data_bits);
POSTING_READ(chan->reg); POSTING_READ(gpio->reg);
} }
/* Clears the GMBUS setup. Our driver doesn't make use of the GMBUS I2C static struct i2c_adapter *
* engine, but if the BIOS leaves it enabled, then that can break our use intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin)
* 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)
{ {
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)) if (pin < 1 || pin > 7)
I915_WRITE(PCH_GMBUS0, 0); return NULL;
else
I915_WRITE(GMBUS0, 0);
}
/** gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL);
* intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg if (gpio == NULL)
* @dev: DRM device return NULL;
* @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;
chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL); gpio->reg = map_pin_to_reg[pin];
if (!chan) if (HAS_PCH_SPLIT(dev_priv->dev))
goto out_free; gpio->reg += PCH_GPIOA - GPIOA;
gpio->dev_priv = dev_priv;
chan->encoder = encoder; snprintf(gpio->adapter.name, I2C_NAME_SIZE, "GPIO %d", pin);
chan->reg = reg; gpio->adapter.owner = THIS_MODULE;
snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); gpio->adapter.algo_data = &gpio->algo;
chan->adapter.owner = THIS_MODULE; gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev;
chan->adapter.algo_data = &chan->algo; gpio->algo.setsda = set_data;
chan->adapter.dev.parent = &dev->pdev->dev; gpio->algo.setscl = set_clock;
chan->algo.setsda = set_data; gpio->algo.getsda = get_data;
chan->algo.setscl = set_clock; gpio->algo.getscl = get_clock;
chan->algo.getsda = get_data; gpio->algo.udelay = I2C_RISEFALL_TIME;
chan->algo.getscl = get_clock; gpio->algo.timeout = usecs_to_jiffies(2200);
chan->algo.udelay = I2C_RISEFALL_TIME; gpio->algo.data = gpio;
chan->algo.timeout = usecs_to_jiffies(2200);
chan->algo.data = chan; if (i2c_bit_add_bus(&gpio->adapter))
i2c_set_adapdata(&chan->adapter, chan);
if (i2c_bit_add_bus(&chan->adapter))
goto out_free; goto out_free;
intel_i2c_reset_gmbus(dev); intel_i2c_reset(dev_priv->dev);
/* JJJ: raise SCL and SDA? */ /* JJJ: raise SCL and SDA? */
intel_i2c_quirk_set(dev, true); intel_i2c_quirk_set(dev_priv, true);
set_data(chan, 1); set_data(gpio, 1);
udelay(I2C_RISEFALL_TIME); udelay(I2C_RISEFALL_TIME);
set_clock(chan, 1); set_clock(gpio, 1);
udelay(I2C_RISEFALL_TIME); 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: out_free:
kfree(chan); kfree(gpio);
return NULL; 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 * intel_gmbus_setup - instantiate all Intel i2c GMBuses
* @output: channel to free * @dev: DRM device
*
* Unregister the adapter from the i2c layer, then free the structure.
*/ */
void intel_i2c_destroy(struct i2c_adapter *adapter) int intel_setup_gmbus(struct drm_device *dev)
{ {
struct intel_i2c_chan *chan; 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;
if (!adapter) 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 drm_i915_private *dev_priv = dev->dev_private;
int i;
if (dev_priv->gmbus == NULL)
return; return;
chan = container_of(adapter, for (i = 0; i < GMBUS_NUM_PORTS; i++) {
struct intel_i2c_chan, struct intel_gmbus *bus = &dev_priv->gmbus[i];
adapter); if (bus->force_bitbanging) {
i2c_del_adapter(&chan->adapter); i2c_del_adapter(bus->force_bitbanging);
kfree(chan); kfree(bus->force_bitbanging);
}
i2c_del_adapter(&bus->adapter);
}
kfree(dev_priv->gmbus);
dev_priv->gmbus = NULL;
} }
...@@ -474,11 +474,12 @@ static int intel_lvds_get_modes(struct drm_connector *connector) ...@@ -474,11 +474,12 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
{ {
struct intel_lvds *intel_lvds = intel_attached_lvds(connector); struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *mode; struct drm_display_mode *mode;
if (intel_lvds->edid_good) { if (intel_lvds->edid_good) {
int ret = intel_ddc_get_modes(connector, int ret = intel_ddc_get_modes(connector,
intel_lvds->base.ddc_bus); &dev_priv->gmbus[GMBUS_PORT_PANEL].adapter);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -898,21 +899,12 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -898,21 +899,12 @@ void intel_lvds_init(struct drm_device *dev)
* if closed, act like it's not there for now * 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 * Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one. * preferred mode is the right one.
*/ */
intel_lvds->edid_good = true; 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; intel_lvds->edid_good = false;
if (!intel_lvds->edid_good) { if (!intel_lvds->edid_good) {
...@@ -999,8 +991,6 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -999,8 +991,6 @@ void intel_lvds_init(struct drm_device *dev)
failed: failed:
DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); 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_connector_cleanup(connector);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
kfree(intel_lvds); kfree(intel_lvds);
......
/* /*
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie> * 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> * Jesse Barnes <jesse.barnes@intel.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
...@@ -34,11 +34,11 @@ ...@@ -34,11 +34,11 @@
* intel_ddc_probe * 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 out_buf[] = { 0x0, 0x0};
u8 buf[2]; u8 buf[2];
int ret;
struct i2c_msg msgs[] = { struct i2c_msg msgs[] = {
{ {
.addr = 0x50, .addr = 0x50,
...@@ -54,13 +54,7 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder) ...@@ -54,13 +54,7 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder)
} }
}; };
intel_i2c_quirk_set(intel_encoder->base.dev, true); return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2;
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;
} }
/** /**
...@@ -76,9 +70,7 @@ int intel_ddc_get_modes(struct drm_connector *connector, ...@@ -76,9 +70,7 @@ int intel_ddc_get_modes(struct drm_connector *connector,
struct edid *edid; struct edid *edid;
int ret = 0; int ret = 0;
intel_i2c_quirk_set(connector->dev, true);
edid = drm_get_edid(connector, adapter); edid = drm_get_edid(connector, adapter);
intel_i2c_quirk_set(connector->dev, false);
if (edid) { if (edid) {
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid); ret = drm_add_edid_modes(connector, edid);
......
...@@ -65,6 +65,7 @@ static const char *tv_format_names[] = { ...@@ -65,6 +65,7 @@ static const char *tv_format_names[] = {
struct intel_sdvo { struct intel_sdvo {
struct intel_encoder base; struct intel_encoder base;
struct i2c_adapter *i2c;
u8 slave_addr; u8 slave_addr;
/* Register for the SDVO device: SDVOB or SDVOC */ /* 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) ...@@ -264,7 +265,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch)
}; };
int ret; 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]; *ch = buf[0];
return true; return true;
...@@ -286,7 +287,7 @@ static bool intel_sdvo_write_byte(struct intel_sdvo *intel_sdvo, int addr, u8 ch ...@@ -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} #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, ...@@ -566,7 +567,7 @@ static int intel_sdvo_set_control_bus_switch(struct intel_sdvo *intel_sdvo,
ret_value[0] = 0; ret_value[0] = 0;
ret_value[1] = 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) if (ret < 0)
return ret; return ret;
if (ret != 3) { if (ret != 3) {
...@@ -1375,6 +1376,19 @@ intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) ...@@ -1375,6 +1376,19 @@ intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
return (caps > 1); 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 * static struct drm_connector *
intel_find_analog_connector(struct drm_device *dev) intel_find_analog_connector(struct drm_device *dev)
{ {
...@@ -1418,28 +1432,12 @@ intel_analog_is_connected(struct drm_device *dev) ...@@ -1418,28 +1432,12 @@ intel_analog_is_connected(struct drm_device *dev)
static struct edid * static struct edid *
intel_sdvo_get_analog_edid(struct drm_connector *connector) intel_sdvo_get_analog_edid(struct drm_connector *connector)
{ {
struct intel_encoder *encoder = intel_attached_encoder(connector); struct drm_i915_private *dev_priv = connector->dev->dev_private;
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;
ddc = intel_i2c_create(encoder, ddc_reg, "SDVO/VGA DDC BUS"); if (!intel_analog_is_connected(connector->dev))
if (ddc == NULL)
return NULL; return NULL;
edid = drm_get_edid(connector, ddc); return drm_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
intel_i2c_destroy(ddc);
return edid;
} }
enum drm_connector_status enum drm_connector_status
...@@ -1449,28 +1447,26 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) ...@@ -1449,28 +1447,26 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
enum drm_connector_status status; enum drm_connector_status status;
struct edid *edid; 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)) { 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 * Don't use the 1 as the argument of DDC bus switch to get
* the EDID. It is used for SDVO SPD ROM. * the EDID. It is used for SDVO SPD ROM.
*/ */
for (ddc = intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) { for (ddc = intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) {
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; intel_sdvo->ddc_bus = ddc;
edid = drm_get_edid(connector, intel_sdvo->base.ddc_bus);
if (edid)
break; 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) ...@@ -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 intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
struct edid *edid; struct edid *edid;
int num_modes;
/* set the bus switch and get the modes */ /* set the bus switch and get the modes */
num_modes = intel_ddc_get_modes(connector, intel_sdvo->base.ddc_bus); edid = intel_sdvo_get_edid(connector, intel_sdvo->ddc_bus);
if (num_modes)
return;
/* /*
* Mac mini hack. On this device, the DVI-I connector shares one DDC * 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) ...@@ -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 * DDC fails, check to see if the analog output is disconnected, in
* which case we'll look there for the digital DDC data. * which case we'll look there for the digital DDC data.
*/ */
if (edid == NULL)
edid = intel_sdvo_get_analog_edid(connector); edid = intel_sdvo_get_analog_edid(connector);
if (edid != NULL) { if (edid != NULL) {
drm_mode_connector_update_edid_property(connector, edid); drm_mode_connector_update_edid_property(connector, edid);
drm_add_edid_modes(connector, edid); drm_add_edid_modes(connector, edid);
...@@ -1678,7 +1673,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) ...@@ -1678,7 +1673,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
* Assume that the preferred modes are * Assume that the preferred modes are
* arranged in priority order. * 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) if (list_empty(&connector->probed_modes) == false)
goto end; goto end;
...@@ -2004,30 +1999,6 @@ intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device) ...@@ -2004,30 +1999,6 @@ intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device)
&intel_sdvo->is_hdmi, 1); &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 static u8
intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) 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) ...@@ -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 drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_sdvo *intel_sdvo; struct intel_sdvo *intel_sdvo;
u8 ch[0x40];
int i; int i;
u32 i2c_reg, ddc_reg;
intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
if (!intel_sdvo) if (!intel_sdvo)
...@@ -2555,82 +2524,49 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) ...@@ -2555,82 +2524,49 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
/* encoder type will be decided later */ /* encoder type will be decided later */
drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0); drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0);
if (HAS_PCH_SPLIT(dev)) { intel_sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
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->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg); 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 */ /* Read the regs to test if we can talk to the device */
for (i = 0; i < 0x40; i++) { 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", DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n",
IS_SDVOB(sdvo_reg) ? 'B' : 'C'); IS_SDVOB(sdvo_reg) ? 'B' : 'C');
goto err_i2c; goto err;
} }
} }
/* setup the DDC bus. */ if (IS_SDVOB(sdvo_reg))
if (IS_SDVOB(sdvo_reg)) {
intel_encoder->ddc_bus =
intel_i2c_create(intel_encoder,
ddc_reg, "SDVOB DDC BUS");
dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
} else { else
intel_encoder->ddc_bus =
intel_i2c_create(intel_encoder,
ddc_reg, "SDVOC DDC BUS");
dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; 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); drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
/* In default case sdvo lvds is false */ /* In default case sdvo lvds is false */
if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
goto err_i2c; goto err;
if (intel_sdvo_output_setup(intel_sdvo, if (intel_sdvo_output_setup(intel_sdvo,
intel_sdvo->caps.output_flags) != true) { intel_sdvo->caps.output_flags) != true) {
DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",
IS_SDVOB(sdvo_reg) ? 'B' : 'C'); IS_SDVOB(sdvo_reg) ? 'B' : 'C');
goto err_i2c; goto err;
} }
intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
/* Set the input timing to the screen. Assume always input 0. */ /* Set the input timing to the screen. Assume always input 0. */
if (!intel_sdvo_set_target_input(intel_sdvo)) if (!intel_sdvo_set_target_input(intel_sdvo))
goto err_i2c; goto err;
if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,
&intel_sdvo->pixel_clock_min, &intel_sdvo->pixel_clock_min,
&intel_sdvo->pixel_clock_max)) &intel_sdvo->pixel_clock_max))
goto err_i2c; goto err;
DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
"clock range %dMHz - %dMHz, " "clock range %dMHz - %dMHz, "
...@@ -2650,12 +2586,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) ...@@ -2650,12 +2586,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
(SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
return true; return true;
err_i2c: err:
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:
drm_encoder_cleanup(&intel_encoder->base); drm_encoder_cleanup(&intel_encoder->base);
kfree(intel_sdvo); kfree(intel_sdvo);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册