fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / media / common / saa7146_i2c.c
index 8aabdd8..8c85efc 100644 (file)
@@ -189,13 +189,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                saa7146_write(dev, I2C_TRANSFER, *dword);
 
                dev->i2c_op = 1;
+               SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
                SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
 
-               wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
-               if (signal_pending (current)) {
-                       /* a signal arrived */
-                       return -ERESTARTSYS;
+               timeout = HZ/100 + 1; /* 10ms */
+               timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
+               if (timeout == -ERESTARTSYS || dev->i2c_op) {
+                       SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+                       SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+                       if (timeout == -ERESTARTSYS)
+                               /* a signal arrived */
+                               return -ERESTARTSYS;
+
+                       printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n");
+                       return -EIO;
                }
                status = saa7146_read(dev, I2C_STATUS);
        } else {
@@ -217,11 +225,9 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                }
                /* wait until we get a transfer done or error */
                timeout = jiffies + HZ/100 + 1; /* 10ms */
+               /* first read usually delivers bogus results... */
+               saa7146_i2c_status(dev);
                while(1) {
-                       /**
-                        *  first read usually delivers bogus results...
-                        */
-                       saa7146_i2c_status(dev);
                        status = saa7146_i2c_status(dev);
                        if ((status & 0x3) != 1)
                                break;
@@ -232,10 +238,10 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                                DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
                                return -EIO;
                        }
-                       if ((++trial < 20) && short_delay)
+                       if (++trial < 50 && short_delay)
                                udelay(10);
                        else
-                       msleep(1);
+                               msleep(1);
                }
        }
 
@@ -279,7 +285,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, in
        int address_err = 0;
        int short_delay = 0;
 
-       if (down_interruptible (&dev->i2c_lock))
+       if (mutex_lock_interruptible(&dev->i2c_lock))
                return -ERESTARTSYS;
 
        for(i=0;i<num;i++) {
@@ -366,7 +372,7 @@ out:
                }
        }
 
-       up(&dev->i2c_lock);
+       mutex_unlock(&dev->i2c_lock);
        return err;
 }