V4L/DVB (12226): gspca - spca508: Extend the write_vector routine.
authorJean-Francois Moine <moinejf@free.fr>
Fri, 12 Jun 2009 06:49:39 +0000 (03:49 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 12 Sep 2009 15:17:33 +0000 (12:17 -0300)
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/gspca/spca508.c

index 2ed2669bac3ed178bdcfde8b36e50b7470ee3111..9696c4caf5c931d70f2be9d42c71b516e093dd35 100644 (file)
@@ -1304,19 +1304,70 @@ static int reg_read(struct gspca_dev *gspca_dev,
        return gspca_dev->usb_buf[0];
 }
 
+/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */
+static int ssi_w(struct gspca_dev *gspca_dev,
+               u16 reg, u16 val)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret, retry;
+
+       ret = reg_write(dev, 0x8802, reg >> 8);
+       if (ret < 0)
+               goto out;
+       ret = reg_write(dev, 0x8801, reg & 0x00ff);
+       if (ret < 0)
+               goto out;
+       if ((reg & 0xff00) == 0x1000) {         /* if 2 bytes */
+               ret = reg_write(dev, 0x8805, val & 0x00ff);
+               if (ret < 0)
+                       goto out;
+               val >>= 8;
+       }
+       ret = reg_write(dev, 0x8800, val);
+       if (ret < 0)
+               goto out;
+
+       /* poll until not busy */
+       retry = 10;
+       for (;;) {
+               ret = reg_read(gspca_dev, 0x8803);
+               if (ret < 0)
+                       break;
+               if (gspca_dev->usb_buf[0] == 0)
+                       break;
+               if (--retry <= 0) {
+                       PDEBUG(D_ERR, "ssi_w busy %02x",
+                                       gspca_dev->usb_buf[0]);
+                       ret = -1;
+                       break;
+               }
+               msleep(8);
+       }
+
+out:
+       return ret;
+}
+
 static int write_vector(struct gspca_dev *gspca_dev,
                        const u16 (*data)[2])
 {
        struct usb_device *dev = gspca_dev->dev;
-       int ret;
+       int ret = 0;
 
        while ((*data)[1] != 0) {
-               ret = reg_write(dev, (*data)[1], (*data)[0]);
+               if ((*data)[1] & 0x8000) {
+                       if ((*data)[1] == 0xdd00)       /* delay */
+                               msleep((*data)[0]);
+                       else
+                               ret = reg_write(dev, (*data)[1], (*data)[0]);
+               } else {
+                       ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
+               }
                if (ret < 0)
-                       return ret;
+                       break;
                data++;
        }
-       return 0;
+       return ret;
 }
 
 /* this function is called at probe time */