Skip to content

Commit

Permalink
drm/i915/intel_i2c: gmbus disabled and reserved ports are invalid
Browse files Browse the repository at this point in the history
There is no GMBUS "disabled" port 0, nor "reserved" port 7.
For the other 6 ports there is a fixed 1:1 mapping between pin pairs and
gmbus ports, which means every real gmbus port has a gpio pin.

Given these realizations, clean up gmbus initialization.

Tested on Sandybridge (gen 6, PCH == CougarPoint) hardware.

Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Daniel Kurtz authored and Daniel Vetter committed Mar 28, 2012
1 parent 3bd7d90 commit 2ed06c9
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 46 deletions.
3 changes: 1 addition & 2 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,6 @@ struct intel_fbc_work;
struct intel_gmbus {
struct i2c_adapter adapter;
bool force_bit;
bool has_gpio;
u32 reg0;
u32 gpio_reg;
struct i2c_algo_bit_data bit_algo;
Expand Down Expand Up @@ -1344,7 +1343,7 @@ extern int intel_setup_gmbus(struct drm_device *dev);
extern void intel_teardown_gmbus(struct drm_device *dev);
extern inline bool intel_gmbus_is_port_valid(unsigned port)
{
return (port >= GMBUS_PORT_DISABLED && port <= GMBUS_PORT_RESERVED);
return (port >= GMBUS_PORT_SSC && port <= GMBUS_PORT_DPD);
}

extern struct i2c_adapter *intel_gmbus_get_adapter(
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@
#define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */
#define GMBUS_PORT_DPD 6 /* HDMID */
#define GMBUS_PORT_RESERVED 7 /* 7 reserved */
#define GMBUS_NUM_PORTS 8
#define GMBUS_NUM_PORTS (GMBUS_PORT_DPD - GMBUS_PORT_SSC + 1)
#define GMBUS1 0x5104 /* command/status */
#define GMBUS_SW_CLR_INT (1<<31)
#define GMBUS_SW_RDY (1<<30)
Expand Down
70 changes: 27 additions & 43 deletions drivers/gpu/drm/i915/intel_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@
#include "i915_drm.h"
#include "i915_drv.h"

struct gmbus_port {
const char *name;
int reg;
};

static const struct gmbus_port gmbus_ports[] = {
{ "ssc", GPIOB },
{ "vga", GPIOA },
{ "panel", GPIOC },
{ "dpc", GPIOD },
{ "dpb", GPIOE },
{ "dpd", GPIOF },
};

/* Intel GPIO access functions */

#define I2C_RISEFALL_TIME 10
Expand Down Expand Up @@ -166,29 +180,16 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter)
intel_i2c_quirk_set(dev_priv, false);
}

static bool
static void
intel_gpio_setup(struct intel_gmbus *bus, u32 pin)
{
struct drm_i915_private *dev_priv = bus->dev_priv;
static const int map_pin_to_reg[] = {
0,
GPIOB,
GPIOA,
GPIOC,
GPIOD,
GPIOE,
GPIOF,
0,
};
struct i2c_algo_bit_data *algo;

if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin])
return false;

algo = &bus->bit_algo;

bus->gpio_reg = map_pin_to_reg[pin];
bus->gpio_reg += dev_priv->gpio_mmio_base;
/* -1 to map pin pair to gmbus index */
bus->gpio_reg = dev_priv->gpio_mmio_base + gmbus_ports[pin - 1].reg;

bus->adapter.algo_data = algo;
algo->setsda = set_data;
Expand All @@ -200,8 +201,6 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin)
algo->udelay = I2C_RISEFALL_TIME;
algo->timeout = usecs_to_jiffies(2200);
algo->data = bus;

return true;
}

static int
Expand Down Expand Up @@ -351,15 +350,9 @@ gmbus_xfer(struct i2c_adapter *adapter,
bus->adapter.name, bus->reg0 & 0xff);
I915_WRITE(GMBUS0 + reg_offset, 0);

/* Hardware may not support GMBUS over these pins?
* Try GPIO bitbanging instead.
*/
if (!bus->has_gpio) {
ret = -EIO;
} else {
bus->force_bit = true;
ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
}
/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
bus->force_bit = true;
ret = i2c_bit_algo.master_xfer(adapter, msgs, num);

out:
mutex_unlock(&dev_priv->gmbus_mutex);
Expand All @@ -386,16 +379,6 @@ static const struct i2c_algorithm gmbus_algorithm = {
*/
int intel_setup_gmbus(struct drm_device *dev)
{
static const char *names[GMBUS_NUM_PORTS] = {
"disabled",
"ssc",
"vga",
"panel",
"dpc",
"dpb",
"dpd",
"reserved",
};
struct drm_i915_private *dev_priv = dev->dev_private;
int ret, i;

Expand All @@ -413,13 +396,14 @@ int intel_setup_gmbus(struct drm_device *dev)

for (i = 0; i < GMBUS_NUM_PORTS; i++) {
struct intel_gmbus *bus = &dev_priv->gmbus[i];
u32 port = i + 1; /* +1 to map gmbus index to pin pair */

bus->adapter.owner = THIS_MODULE;
bus->adapter.class = I2C_CLASS_DDC;
snprintf(bus->adapter.name,
sizeof(bus->adapter.name),
"i915 gmbus %s",
names[i]);
gmbus_ports[i].name);

bus->adapter.dev.parent = &dev->pdev->dev;
bus->dev_priv = dev_priv;
Expand All @@ -430,9 +414,9 @@ int intel_setup_gmbus(struct drm_device *dev)
goto err;

/* By default use a conservative clock rate */
bus->reg0 = i | GMBUS_RATE_100KHZ;
bus->reg0 = port | GMBUS_RATE_100KHZ;

bus->has_gpio = intel_gpio_setup(bus, i);
intel_gpio_setup(bus, port);
}

intel_i2c_reset(dev_priv->dev);
Expand All @@ -453,8 +437,9 @@ struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv,
unsigned port)
{
WARN_ON(!intel_gmbus_is_port_valid(port));
/* -1 to map pin pair to gmbus index */
return (intel_gmbus_is_port_valid(port)) ?
&dev_priv->gmbus[port].adapter : NULL;
&dev_priv->gmbus[port - 1].adapter : NULL;
}

void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed)
Expand All @@ -468,8 +453,7 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);

if (bus->has_gpio)
bus->force_bit = force_bit;
bus->force_bit = force_bit;
}

void intel_teardown_gmbus(struct drm_device *dev)
Expand Down

0 comments on commit 2ed06c9

Please sign in to comment.