Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 357894
b: refs/heads/master
c: 28c70f1
h: refs/heads/master
v: v3
  • Loading branch information
Daniel Vetter committed Dec 6, 2012
1 parent b5a3616 commit c62096f
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 515ac2bb95f609bc4a0d2ad5f7011b3264b2bb21
refs/heads/master: 28c70f162a315bdcfbe0bf940a740ef8bfb918d6
3 changes: 3 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ typedef struct drm_i915_private {

struct intel_gmbus gmbus[GMBUS_NUM_PORTS];


/** gmbus_mutex protects against concurrent usage of the single hw gmbus
* controller on different i2c buses. */
struct mutex gmbus_mutex;
Expand All @@ -650,6 +651,8 @@ typedef struct drm_i915_private {
*/
uint32_t gpio_mmio_base;

wait_queue_head_t gmbus_wait_queue;

struct pci_dev *bridge_dev;
struct intel_ring_buffer ring[I915_NUM_RINGS];
uint32_t next_seqno;
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,11 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,

static void gmbus_irq_handler(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private;

DRM_DEBUG_DRIVER("GMBUS interrupt\n");

wake_up_all(&dev_priv->gmbus_wait_queue);
}

static irqreturn_t valleyview_irq_handler(int irq, void *arg)
Expand Down
45 changes: 34 additions & 11 deletions trunk/drivers/gpu/drm/i915/intel_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ intel_i2c_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);
I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0);
}

static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
Expand Down Expand Up @@ -204,20 +205,38 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin)

static int
gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
u32 gmbus2_status)
u32 gmbus2_status,
u32 gmbus4_irq_en)
{
int ret;
int i;
int reg_offset = dev_priv->gpio_mmio_base;
u32 gmbus2;
u32 gmbus2 = 0;
DEFINE_WAIT(wait);

/* Important: The hw handles only the first bit, so set only one! Since
* we also need to check for NAKs besides the hw ready/idle signal, we
* need to wake up periodically and check that ourselves. */
I915_WRITE(GMBUS4 + reg_offset, gmbus4_irq_en);

ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) &
(GMBUS_SATOER | gmbus2_status),
50);
for (i = 0; i < msecs_to_jiffies(50) + 1; i++) {
prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait,
TASK_UNINTERRUPTIBLE);

gmbus2 = I915_READ(GMBUS2 + reg_offset);
if (gmbus2 & (GMBUS_SATOER | gmbus2_status))
break;

schedule_timeout(1);
}
finish_wait(&dev_priv->gmbus_wait_queue, &wait);

I915_WRITE(GMBUS4 + reg_offset, 0);

if (gmbus2 & GMBUS_SATOER)
return -ENXIO;

return ret;
if (gmbus2 & gmbus2_status)
return 0;
return -ETIMEDOUT;
}

static int
Expand All @@ -238,7 +257,8 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
int ret;
u32 val, loop = 0;

ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY);
ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY,
GMBUS_HW_RDY_EN);
if (ret)
return ret;

Expand Down Expand Up @@ -282,7 +302,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)

I915_WRITE(GMBUS3 + reg_offset, val);

ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY);
ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY,
GMBUS_HW_RDY_EN);
if (ret)
return ret;
}
Expand Down Expand Up @@ -367,7 +388,8 @@ gmbus_xfer(struct i2c_adapter *adapter,
if (ret == -ENXIO)
goto clear_err;

ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE);
ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE,
GMBUS_HW_WAIT_EN);
if (ret == -ENXIO)
goto clear_err;
if (ret)
Expand Down Expand Up @@ -473,6 +495,7 @@ int intel_setup_gmbus(struct drm_device *dev)
dev_priv->gpio_mmio_base = 0;

mutex_init(&dev_priv->gmbus_mutex);
init_waitqueue_head(&dev_priv->gmbus_wait_queue);

for (i = 0; i < GMBUS_NUM_PORTS; i++) {
struct intel_gmbus *bus = &dev_priv->gmbus[i];
Expand Down

0 comments on commit c62096f

Please sign in to comment.