diff options
author | Daniel Kurtz <djkurtz@chromium.org> | 2012-03-27 14:36:15 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-03-28 09:02:53 -0400 |
commit | 2ed06c93a1fce057808894d73167aae03c76deaf (patch) | |
tree | 163c39d4fffc678c507604a67fed8f1c778a9ec6 | |
parent | 3bd7d90938f1fe77de5991dc4b727843c4980b2a (diff) |
drm/i915/intel_i2c: gmbus disabled and reserved ports are invalid
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>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 70 |
3 files changed, 29 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 44e6430af3d4..c5ad7b96b065 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -303,7 +303,6 @@ struct intel_fbc_work; | |||
303 | struct intel_gmbus { | 303 | struct intel_gmbus { |
304 | struct i2c_adapter adapter; | 304 | struct i2c_adapter adapter; |
305 | bool force_bit; | 305 | bool force_bit; |
306 | bool has_gpio; | ||
307 | u32 reg0; | 306 | u32 reg0; |
308 | u32 gpio_reg; | 307 | u32 gpio_reg; |
309 | struct i2c_algo_bit_data bit_algo; | 308 | struct i2c_algo_bit_data bit_algo; |
@@ -1344,7 +1343,7 @@ extern int intel_setup_gmbus(struct drm_device *dev); | |||
1344 | extern void intel_teardown_gmbus(struct drm_device *dev); | 1343 | extern void intel_teardown_gmbus(struct drm_device *dev); |
1345 | extern inline bool intel_gmbus_is_port_valid(unsigned port) | 1344 | extern inline bool intel_gmbus_is_port_valid(unsigned port) |
1346 | { | 1345 | { |
1347 | return (port >= GMBUS_PORT_DISABLED && port <= GMBUS_PORT_RESERVED); | 1346 | return (port >= GMBUS_PORT_SSC && port <= GMBUS_PORT_DPD); |
1348 | } | 1347 | } |
1349 | 1348 | ||
1350 | extern struct i2c_adapter *intel_gmbus_get_adapter( | 1349 | extern struct i2c_adapter *intel_gmbus_get_adapter( |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index accd8ee48f9d..a8d218ca7d1d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -744,7 +744,7 @@ | |||
744 | #define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ | 744 | #define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ |
745 | #define GMBUS_PORT_DPD 6 /* HDMID */ | 745 | #define GMBUS_PORT_DPD 6 /* HDMID */ |
746 | #define GMBUS_PORT_RESERVED 7 /* 7 reserved */ | 746 | #define GMBUS_PORT_RESERVED 7 /* 7 reserved */ |
747 | #define GMBUS_NUM_PORTS 8 | 747 | #define GMBUS_NUM_PORTS (GMBUS_PORT_DPD - GMBUS_PORT_SSC + 1) |
748 | #define GMBUS1 0x5104 /* command/status */ | 748 | #define GMBUS1 0x5104 /* command/status */ |
749 | #define GMBUS_SW_CLR_INT (1<<31) | 749 | #define GMBUS_SW_CLR_INT (1<<31) |
750 | #define GMBUS_SW_RDY (1<<30) | 750 | #define GMBUS_SW_RDY (1<<30) |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 2f65d01340ff..dcde6f64777a 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
@@ -35,6 +35,20 @@ | |||
35 | #include "i915_drm.h" | 35 | #include "i915_drm.h" |
36 | #include "i915_drv.h" | 36 | #include "i915_drv.h" |
37 | 37 | ||
38 | struct gmbus_port { | ||
39 | const char *name; | ||
40 | int reg; | ||
41 | }; | ||
42 | |||
43 | static const struct gmbus_port gmbus_ports[] = { | ||
44 | { "ssc", GPIOB }, | ||
45 | { "vga", GPIOA }, | ||
46 | { "panel", GPIOC }, | ||
47 | { "dpc", GPIOD }, | ||
48 | { "dpb", GPIOE }, | ||
49 | { "dpd", GPIOF }, | ||
50 | }; | ||
51 | |||
38 | /* Intel GPIO access functions */ | 52 | /* Intel GPIO access functions */ |
39 | 53 | ||
40 | #define I2C_RISEFALL_TIME 10 | 54 | #define I2C_RISEFALL_TIME 10 |
@@ -166,29 +180,16 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter) | |||
166 | intel_i2c_quirk_set(dev_priv, false); | 180 | intel_i2c_quirk_set(dev_priv, false); |
167 | } | 181 | } |
168 | 182 | ||
169 | static bool | 183 | static void |
170 | intel_gpio_setup(struct intel_gmbus *bus, u32 pin) | 184 | intel_gpio_setup(struct intel_gmbus *bus, u32 pin) |
171 | { | 185 | { |
172 | struct drm_i915_private *dev_priv = bus->dev_priv; | 186 | struct drm_i915_private *dev_priv = bus->dev_priv; |
173 | static const int map_pin_to_reg[] = { | ||
174 | 0, | ||
175 | GPIOB, | ||
176 | GPIOA, | ||
177 | GPIOC, | ||
178 | GPIOD, | ||
179 | GPIOE, | ||
180 | GPIOF, | ||
181 | 0, | ||
182 | }; | ||
183 | struct i2c_algo_bit_data *algo; | 187 | struct i2c_algo_bit_data *algo; |
184 | 188 | ||
185 | if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin]) | ||
186 | return false; | ||
187 | |||
188 | algo = &bus->bit_algo; | 189 | algo = &bus->bit_algo; |
189 | 190 | ||
190 | bus->gpio_reg = map_pin_to_reg[pin]; | 191 | /* -1 to map pin pair to gmbus index */ |
191 | bus->gpio_reg += dev_priv->gpio_mmio_base; | 192 | bus->gpio_reg = dev_priv->gpio_mmio_base + gmbus_ports[pin - 1].reg; |
192 | 193 | ||
193 | bus->adapter.algo_data = algo; | 194 | bus->adapter.algo_data = algo; |
194 | algo->setsda = set_data; | 195 | algo->setsda = set_data; |
@@ -200,8 +201,6 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin) | |||
200 | algo->udelay = I2C_RISEFALL_TIME; | 201 | algo->udelay = I2C_RISEFALL_TIME; |
201 | algo->timeout = usecs_to_jiffies(2200); | 202 | algo->timeout = usecs_to_jiffies(2200); |
202 | algo->data = bus; | 203 | algo->data = bus; |
203 | |||
204 | return true; | ||
205 | } | 204 | } |
206 | 205 | ||
207 | static int | 206 | static int |
@@ -351,15 +350,9 @@ timeout: | |||
351 | bus->adapter.name, bus->reg0 & 0xff); | 350 | bus->adapter.name, bus->reg0 & 0xff); |
352 | I915_WRITE(GMBUS0 + reg_offset, 0); | 351 | I915_WRITE(GMBUS0 + reg_offset, 0); |
353 | 352 | ||
354 | /* Hardware may not support GMBUS over these pins? | 353 | /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ |
355 | * Try GPIO bitbanging instead. | 354 | bus->force_bit = true; |
356 | */ | 355 | ret = i2c_bit_algo.master_xfer(adapter, msgs, num); |
357 | if (!bus->has_gpio) { | ||
358 | ret = -EIO; | ||
359 | } else { | ||
360 | bus->force_bit = true; | ||
361 | ret = i2c_bit_algo.master_xfer(adapter, msgs, num); | ||
362 | } | ||
363 | 356 | ||
364 | out: | 357 | out: |
365 | mutex_unlock(&dev_priv->gmbus_mutex); | 358 | mutex_unlock(&dev_priv->gmbus_mutex); |
@@ -386,16 +379,6 @@ static const struct i2c_algorithm gmbus_algorithm = { | |||
386 | */ | 379 | */ |
387 | int intel_setup_gmbus(struct drm_device *dev) | 380 | int intel_setup_gmbus(struct drm_device *dev) |
388 | { | 381 | { |
389 | static const char *names[GMBUS_NUM_PORTS] = { | ||
390 | "disabled", | ||
391 | "ssc", | ||
392 | "vga", | ||
393 | "panel", | ||
394 | "dpc", | ||
395 | "dpb", | ||
396 | "dpd", | ||
397 | "reserved", | ||
398 | }; | ||
399 | struct drm_i915_private *dev_priv = dev->dev_private; | 382 | struct drm_i915_private *dev_priv = dev->dev_private; |
400 | int ret, i; | 383 | int ret, i; |
401 | 384 | ||
@@ -413,13 +396,14 @@ int intel_setup_gmbus(struct drm_device *dev) | |||
413 | 396 | ||
414 | for (i = 0; i < GMBUS_NUM_PORTS; i++) { | 397 | for (i = 0; i < GMBUS_NUM_PORTS; i++) { |
415 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; | 398 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; |
399 | u32 port = i + 1; /* +1 to map gmbus index to pin pair */ | ||
416 | 400 | ||
417 | bus->adapter.owner = THIS_MODULE; | 401 | bus->adapter.owner = THIS_MODULE; |
418 | bus->adapter.class = I2C_CLASS_DDC; | 402 | bus->adapter.class = I2C_CLASS_DDC; |
419 | snprintf(bus->adapter.name, | 403 | snprintf(bus->adapter.name, |
420 | sizeof(bus->adapter.name), | 404 | sizeof(bus->adapter.name), |
421 | "i915 gmbus %s", | 405 | "i915 gmbus %s", |
422 | names[i]); | 406 | gmbus_ports[i].name); |
423 | 407 | ||
424 | bus->adapter.dev.parent = &dev->pdev->dev; | 408 | bus->adapter.dev.parent = &dev->pdev->dev; |
425 | bus->dev_priv = dev_priv; | 409 | bus->dev_priv = dev_priv; |
@@ -430,9 +414,9 @@ int intel_setup_gmbus(struct drm_device *dev) | |||
430 | goto err; | 414 | goto err; |
431 | 415 | ||
432 | /* By default use a conservative clock rate */ | 416 | /* By default use a conservative clock rate */ |
433 | bus->reg0 = i | GMBUS_RATE_100KHZ; | 417 | bus->reg0 = port | GMBUS_RATE_100KHZ; |
434 | 418 | ||
435 | bus->has_gpio = intel_gpio_setup(bus, i); | 419 | intel_gpio_setup(bus, port); |
436 | } | 420 | } |
437 | 421 | ||
438 | intel_i2c_reset(dev_priv->dev); | 422 | intel_i2c_reset(dev_priv->dev); |
@@ -453,8 +437,9 @@ struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, | |||
453 | unsigned port) | 437 | unsigned port) |
454 | { | 438 | { |
455 | WARN_ON(!intel_gmbus_is_port_valid(port)); | 439 | WARN_ON(!intel_gmbus_is_port_valid(port)); |
440 | /* -1 to map pin pair to gmbus index */ | ||
456 | return (intel_gmbus_is_port_valid(port)) ? | 441 | return (intel_gmbus_is_port_valid(port)) ? |
457 | &dev_priv->gmbus[port].adapter : NULL; | 442 | &dev_priv->gmbus[port - 1].adapter : NULL; |
458 | } | 443 | } |
459 | 444 | ||
460 | void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) | 445 | void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) |
@@ -468,8 +453,7 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) | |||
468 | { | 453 | { |
469 | struct intel_gmbus *bus = to_intel_gmbus(adapter); | 454 | struct intel_gmbus *bus = to_intel_gmbus(adapter); |
470 | 455 | ||
471 | if (bus->has_gpio) | 456 | bus->force_bit = force_bit; |
472 | bus->force_bit = force_bit; | ||
473 | } | 457 | } |
474 | 458 | ||
475 | void intel_teardown_gmbus(struct drm_device *dev) | 459 | void intel_teardown_gmbus(struct drm_device *dev) |