|
@@ -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 */
|