Commit f8f20188 authored by Jean-François Moine's avatar Jean-François Moine Committed by Mauro Carvalho Chehab

[media] gspca - ov519: Propagate errors to higher level

Signed-off-by: default avatarJean-François Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 83db7688
...@@ -1869,10 +1869,13 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) ...@@ -1869,10 +1869,13 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
} }
/* Write a OV519 register */ /* Write a OV519 register */
static int reg_w(struct sd *sd, u16 index, u16 value) static void reg_w(struct sd *sd, u16 index, u16 value)
{ {
int ret, req = 0; int ret, req = 0;
if (sd->gspca_dev.usb_err < 0)
return;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
...@@ -1903,11 +1906,11 @@ static int reg_w(struct sd *sd, u16 index, u16 value) ...@@ -1903,11 +1906,11 @@ static int reg_w(struct sd *sd, u16 index, u16 value)
if (ret < 0) { if (ret < 0) {
err("Write reg 0x%04x -> [0x%02x] failed", err("Write reg 0x%04x -> [0x%02x] failed",
value, index); value, index);
return ret; sd->gspca_dev.usb_err = ret;
return;
} }
PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index); PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index);
return 0;
} }
/* Read from a OV519 register, note not valid for the w9968cf!! */ /* Read from a OV519 register, note not valid for the w9968cf!! */
...@@ -1917,6 +1920,9 @@ static int reg_r(struct sd *sd, u16 index) ...@@ -1917,6 +1920,9 @@ static int reg_r(struct sd *sd, u16 index)
int ret; int ret;
int req; int req;
if (sd->gspca_dev.usb_err < 0)
return -1;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
...@@ -1938,8 +1944,10 @@ static int reg_r(struct sd *sd, u16 index) ...@@ -1938,8 +1944,10 @@ static int reg_r(struct sd *sd, u16 index)
if (ret >= 0) { if (ret >= 0) {
ret = sd->gspca_dev.usb_buf[0]; ret = sd->gspca_dev.usb_buf[0];
PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret); PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret);
} else } else {
err("Read reg [0x%02x] failed", index); err("Read reg [0x%02x] failed", index);
sd->gspca_dev.usb_err = ret;
}
return ret; return ret;
} }
...@@ -1950,16 +1958,21 @@ static int reg_r8(struct sd *sd, ...@@ -1950,16 +1958,21 @@ static int reg_r8(struct sd *sd,
{ {
int ret; int ret;
if (sd->gspca_dev.usb_err < 0)
return -1;
ret = usb_control_msg(sd->gspca_dev.dev, ret = usb_control_msg(sd->gspca_dev.dev,
usb_rcvctrlpipe(sd->gspca_dev.dev, 0), usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
1, /* REQ_IO */ 1, /* REQ_IO */
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, sd->gspca_dev.usb_buf, 8, 500); 0, index, sd->gspca_dev.usb_buf, 8, 500);
if (ret >= 0) if (ret >= 0) {
ret = sd->gspca_dev.usb_buf[0]; ret = sd->gspca_dev.usb_buf[0];
else } else {
err("Read reg 8 [0x%02x] failed", index); err("Read reg 8 [0x%02x] failed", index);
sd->gspca_dev.usb_err = ret;
}
return ret; return ret;
} }
...@@ -1970,7 +1983,7 @@ static int reg_r8(struct sd *sd, ...@@ -1970,7 +1983,7 @@ static int reg_r8(struct sd *sd,
* that are in the same position as 0's in "mask" are preserved, regardless * that are in the same position as 0's in "mask" are preserved, regardless
* of their respective state in "value". * of their respective state in "value".
*/ */
static int reg_w_mask(struct sd *sd, static void reg_w_mask(struct sd *sd,
u16 index, u16 index,
u8 value, u8 value,
u8 mask) u8 mask)
...@@ -1982,22 +1995,25 @@ static int reg_w_mask(struct sd *sd, ...@@ -1982,22 +1995,25 @@ static int reg_w_mask(struct sd *sd,
value &= mask; /* Enforce mask on value */ value &= mask; /* Enforce mask on value */
ret = reg_r(sd, index); ret = reg_r(sd, index);
if (ret < 0) if (ret < 0)
return ret; return;
oldval = ret & ~mask; /* Clear the masked bits */ oldval = ret & ~mask; /* Clear the masked bits */
value |= oldval; /* Set the desired bits */ value |= oldval; /* Set the desired bits */
} }
return reg_w(sd, index, value); reg_w(sd, index, value);
} }
/* /*
* Writes multiple (n) byte value to a single register. Only valid with certain * Writes multiple (n) byte value to a single register. Only valid with certain
* registers (0x30 and 0xc4 - 0xce). * registers (0x30 and 0xc4 - 0xce).
*/ */
static int ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
{ {
int ret; int ret;
if (sd->gspca_dev.usb_err < 0)
return;
*((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
ret = usb_control_msg(sd->gspca_dev.dev, ret = usb_control_msg(sd->gspca_dev.dev,
...@@ -2008,13 +2024,11 @@ static int ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) ...@@ -2008,13 +2024,11 @@ static int ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
sd->gspca_dev.usb_buf, n, 500); sd->gspca_dev.usb_buf, n, 500);
if (ret < 0) { if (ret < 0) {
err("Write reg32 [%02x] %08x failed", index, value); err("Write reg32 [%02x] %08x failed", index, value);
return ret; sd->gspca_dev.usb_err = ret;
} }
return 0;
} }
static int ov511_i2c_w(struct sd *sd, u8 reg, u8 value) static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
{ {
int rc, retries; int rc, retries;
...@@ -2023,36 +2037,28 @@ static int ov511_i2c_w(struct sd *sd, u8 reg, u8 value) ...@@ -2023,36 +2037,28 @@ static int ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
/* Three byte write cycle */ /* Three byte write cycle */
for (retries = 6; ; ) { for (retries = 6; ; ) {
/* Select camera register */ /* Select camera register */
rc = reg_w(sd, R51x_I2C_SADDR_3, reg); reg_w(sd, R51x_I2C_SADDR_3, reg);
if (rc < 0)
return rc;
/* Write "value" to I2C data port of OV511 */ /* Write "value" to I2C data port of OV511 */
rc = reg_w(sd, R51x_I2C_DATA, value); reg_w(sd, R51x_I2C_DATA, value);
if (rc < 0)
return rc;
/* Initiate 3-byte write cycle */ /* Initiate 3-byte write cycle */
rc = reg_w(sd, R511_I2C_CTL, 0x01); reg_w(sd, R511_I2C_CTL, 0x01);
if (rc < 0)
return rc;
do { do {
rc = reg_r(sd, R511_I2C_CTL); rc = reg_r(sd, R511_I2C_CTL);
} while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
if (rc < 0) if (rc < 0)
return rc; return;
if ((rc & 2) == 0) /* Ack? */ if ((rc & 2) == 0) /* Ack? */
break; break;
if (--retries < 0) { if (--retries < 0) {
PDEBUG(D_USBO, "i2c write retries exhausted"); PDEBUG(D_USBO, "i2c write retries exhausted");
return -1; return;
} }
} }
return 0;
} }
static int ov511_i2c_r(struct sd *sd, u8 reg) static int ov511_i2c_r(struct sd *sd, u8 reg)
...@@ -2062,14 +2068,10 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) ...@@ -2062,14 +2068,10 @@ static int ov511_i2c_r(struct sd *sd, u8 reg)
/* Two byte write cycle */ /* Two byte write cycle */
for (retries = 6; ; ) { for (retries = 6; ; ) {
/* Select camera register */ /* Select camera register */
rc = reg_w(sd, R51x_I2C_SADDR_2, reg); reg_w(sd, R51x_I2C_SADDR_2, reg);
if (rc < 0)
return rc;
/* Initiate 2-byte write cycle */ /* Initiate 2-byte write cycle */
rc = reg_w(sd, R511_I2C_CTL, 0x03); reg_w(sd, R511_I2C_CTL, 0x03);
if (rc < 0)
return rc;
do { do {
rc = reg_r(sd, R511_I2C_CTL); rc = reg_r(sd, R511_I2C_CTL);
...@@ -2093,9 +2095,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) ...@@ -2093,9 +2095,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg)
/* Two byte read cycle */ /* Two byte read cycle */
for (retries = 6; ; ) { for (retries = 6; ; ) {
/* Initiate 2-byte read cycle */ /* Initiate 2-byte read cycle */
rc = reg_w(sd, R511_I2C_CTL, 0x05); reg_w(sd, R511_I2C_CTL, 0x05);
if (rc < 0)
return rc;
do { do {
rc = reg_r(sd, R511_I2C_CTL); rc = reg_r(sd, R511_I2C_CTL);
...@@ -2108,9 +2108,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) ...@@ -2108,9 +2108,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg)
break; break;
/* I2C abort */ /* I2C abort */
rc = reg_w(sd, R511_I2C_CTL, 0x10); reg_w(sd, R511_I2C_CTL, 0x10);
if (rc < 0)
return rc;
if (--retries < 0) { if (--retries < 0) {
PDEBUG(D_USBI, "i2c read retries exhausted"); PDEBUG(D_USBI, "i2c read retries exhausted");
...@@ -2123,9 +2121,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) ...@@ -2123,9 +2121,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg)
PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
/* This is needed to make i2c_w() work */ /* This is needed to make i2c_w() work */
rc = reg_w(sd, R511_I2C_CTL, 0x05); reg_w(sd, R511_I2C_CTL, 0x05);
if (rc < 0)
return rc;
return value; return value;
} }
...@@ -2135,32 +2131,24 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) ...@@ -2135,32 +2131,24 @@ static int ov511_i2c_r(struct sd *sd, u8 reg)
* This is normally only called from i2c_w(). Note that this function * This is normally only called from i2c_w(). Note that this function
* always succeeds regardless of whether the sensor is present and working. * always succeeds regardless of whether the sensor is present and working.
*/ */
static int ov518_i2c_w(struct sd *sd, static void ov518_i2c_w(struct sd *sd,
u8 reg, u8 reg,
u8 value) u8 value)
{ {
int rc;
PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
/* Select camera register */ /* Select camera register */
rc = reg_w(sd, R51x_I2C_SADDR_3, reg); reg_w(sd, R51x_I2C_SADDR_3, reg);
if (rc < 0)
return rc;
/* Write "value" to I2C data port of OV511 */ /* Write "value" to I2C data port of OV511 */
rc = reg_w(sd, R51x_I2C_DATA, value); reg_w(sd, R51x_I2C_DATA, value);
if (rc < 0)
return rc;
/* Initiate 3-byte write cycle */ /* Initiate 3-byte write cycle */
rc = reg_w(sd, R518_I2C_CTL, 0x01); reg_w(sd, R518_I2C_CTL, 0x01);
if (rc < 0)
return rc;
/* wait for write complete */ /* wait for write complete */
msleep(4); msleep(4);
return reg_r8(sd, R518_I2C_CTL); reg_r8(sd, R518_I2C_CTL);
} }
/* /*
...@@ -2172,31 +2160,28 @@ static int ov518_i2c_w(struct sd *sd, ...@@ -2172,31 +2160,28 @@ static int ov518_i2c_w(struct sd *sd,
*/ */
static int ov518_i2c_r(struct sd *sd, u8 reg) static int ov518_i2c_r(struct sd *sd, u8 reg)
{ {
int rc, value; int value;
/* Select camera register */ /* Select camera register */
rc = reg_w(sd, R51x_I2C_SADDR_2, reg); reg_w(sd, R51x_I2C_SADDR_2, reg);
if (rc < 0)
return rc;
/* Initiate 2-byte write cycle */ /* Initiate 2-byte write cycle */
rc = reg_w(sd, R518_I2C_CTL, 0x03); reg_w(sd, R518_I2C_CTL, 0x03);
if (rc < 0)
return rc;
/* Initiate 2-byte read cycle */ /* Initiate 2-byte read cycle */
rc = reg_w(sd, R518_I2C_CTL, 0x05); reg_w(sd, R518_I2C_CTL, 0x05);
if (rc < 0)
return rc;
value = reg_r(sd, R51x_I2C_DATA); value = reg_r(sd, R51x_I2C_DATA);
PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
return value; return value;
} }
static int ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
{ {
int ret; int ret;
if (sd->gspca_dev.usb_err < 0)
return;
ret = usb_control_msg(sd->gspca_dev.dev, ret = usb_control_msg(sd->gspca_dev.dev,
usb_sndctrlpipe(sd->gspca_dev.dev, 0), usb_sndctrlpipe(sd->gspca_dev.dev, 0),
0x02, 0x02,
...@@ -2205,17 +2190,19 @@ static int ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) ...@@ -2205,17 +2190,19 @@ static int ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
if (ret < 0) { if (ret < 0) {
err("i2c 0x%02x -> [0x%02x] failed", value, reg); err("i2c 0x%02x -> [0x%02x] failed", value, reg);
return ret; sd->gspca_dev.usb_err = ret;
} }
PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
return 0;
} }
static int ovfx2_i2c_r(struct sd *sd, u8 reg) static int ovfx2_i2c_r(struct sd *sd, u8 reg)
{ {
int ret; int ret;
if (sd->gspca_dev.usb_err < 0)
return -1;
ret = usb_control_msg(sd->gspca_dev.dev, ret = usb_control_msg(sd->gspca_dev.dev,
usb_rcvctrlpipe(sd->gspca_dev.dev, 0), usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
0x03, 0x03,
...@@ -2225,38 +2212,38 @@ static int ovfx2_i2c_r(struct sd *sd, u8 reg) ...@@ -2225,38 +2212,38 @@ static int ovfx2_i2c_r(struct sd *sd, u8 reg)
if (ret >= 0) { if (ret >= 0) {
ret = sd->gspca_dev.usb_buf[0]; ret = sd->gspca_dev.usb_buf[0];
PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret); PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret);
} else } else {
err("i2c read [0x%02x] failed", reg); err("i2c read [0x%02x] failed", reg);
sd->gspca_dev.usb_err = ret;
}
return ret; return ret;
} }
static int i2c_w(struct sd *sd, u8 reg, u8 value) static void i2c_w(struct sd *sd, u8 reg, u8 value)
{ {
int ret = -1;
if (sd->sensor_reg_cache[reg] == value) if (sd->sensor_reg_cache[reg] == value)
return 0; return;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
ret = ov511_i2c_w(sd, reg, value); ov511_i2c_w(sd, reg, value);
break; break;
case BRIDGE_OV518: case BRIDGE_OV518:
case BRIDGE_OV518PLUS: case BRIDGE_OV518PLUS:
case BRIDGE_OV519: case BRIDGE_OV519:
ret = ov518_i2c_w(sd, reg, value); ov518_i2c_w(sd, reg, value);
break; break;
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
ret = ovfx2_i2c_w(sd, reg, value); ovfx2_i2c_w(sd, reg, value);
break; break;
case BRIDGE_W9968CF: case BRIDGE_W9968CF:
ret = w9968cf_i2c_w(sd, reg, value); w9968cf_i2c_w(sd, reg, value);
break; break;
} }
if (ret >= 0) { if (sd->gspca_dev.usb_err >= 0) {
/* Up on sensor reset empty the register cache */ /* Up on sensor reset empty the register cache */
if (reg == 0x12 && (value & 0x80)) if (reg == 0x12 && (value & 0x80))
memset(sd->sensor_reg_cache, -1, memset(sd->sensor_reg_cache, -1,
...@@ -2264,8 +2251,6 @@ static int i2c_w(struct sd *sd, u8 reg, u8 value) ...@@ -2264,8 +2251,6 @@ static int i2c_w(struct sd *sd, u8 reg, u8 value)
else else
sd->sensor_reg_cache[reg] = value; sd->sensor_reg_cache[reg] = value;
} }
return ret;
} }
static int i2c_r(struct sd *sd, u8 reg) static int i2c_r(struct sd *sd, u8 reg)
...@@ -2304,7 +2289,7 @@ static int i2c_r(struct sd *sd, u8 reg) ...@@ -2304,7 +2289,7 @@ static int i2c_r(struct sd *sd, u8 reg)
* that are in the same position as 0's in "mask" are preserved, regardless * that are in the same position as 0's in "mask" are preserved, regardless
* of their respective state in "value". * of their respective state in "value".
*/ */
static int i2c_w_mask(struct sd *sd, static void i2c_w_mask(struct sd *sd,
u8 reg, u8 reg,
u8 value, u8 value,
u8 mask) u8 mask)
...@@ -2315,70 +2300,72 @@ static int i2c_w_mask(struct sd *sd, ...@@ -2315,70 +2300,72 @@ static int i2c_w_mask(struct sd *sd,
value &= mask; /* Enforce mask on value */ value &= mask; /* Enforce mask on value */
rc = i2c_r(sd, reg); rc = i2c_r(sd, reg);
if (rc < 0) if (rc < 0)
return rc; return;
oldval = rc & ~mask; /* Clear the masked bits */ oldval = rc & ~mask; /* Clear the masked bits */
value |= oldval; /* Set the desired bits */ value |= oldval; /* Set the desired bits */
return i2c_w(sd, reg, value); i2c_w(sd, reg, value);
} }
/* Temporarily stops OV511 from functioning. Must do this before changing /* Temporarily stops OV511 from functioning. Must do this before changing
* registers while the camera is streaming */ * registers while the camera is streaming */
static inline int ov51x_stop(struct sd *sd) static inline void ov51x_stop(struct sd *sd)
{ {
PDEBUG(D_STREAM, "stopping"); PDEBUG(D_STREAM, "stopping");
sd->stopped = 1; sd->stopped = 1;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
return reg_w(sd, R51x_SYS_RESET, 0x3d); reg_w(sd, R51x_SYS_RESET, 0x3d);
break;
case BRIDGE_OV518: case BRIDGE_OV518:
case BRIDGE_OV518PLUS: case BRIDGE_OV518PLUS:
return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
break;
case BRIDGE_OV519: case BRIDGE_OV519:
return reg_w(sd, OV519_R51_RESET1, 0x0f); reg_w(sd, OV519_R51_RESET1, 0x0f);
break;
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
return reg_w_mask(sd, 0x0f, 0x00, 0x02); reg_w_mask(sd, 0x0f, 0x00, 0x02);
break;
case BRIDGE_W9968CF: case BRIDGE_W9968CF:
return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
break;
} }
return 0;
} }
/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
* actually stopped (for performance). */ * actually stopped (for performance). */
static inline int ov51x_restart(struct sd *sd) static inline void ov51x_restart(struct sd *sd)
{ {
int rc;
PDEBUG(D_STREAM, "restarting"); PDEBUG(D_STREAM, "restarting");
if (!sd->stopped) if (!sd->stopped)
return 0; return;
sd->stopped = 0; sd->stopped = 0;
/* Reinitialize the stream */ /* Reinitialize the stream */
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
return reg_w(sd, R51x_SYS_RESET, 0x00); reg_w(sd, R51x_SYS_RESET, 0x00);
break;
case BRIDGE_OV518: case BRIDGE_OV518:
case BRIDGE_OV518PLUS: case BRIDGE_OV518PLUS:
rc = reg_w(sd, 0x2f, 0x80); reg_w(sd, 0x2f, 0x80);
if (rc < 0) reg_w(sd, R51x_SYS_RESET, 0x00);
return rc; break;
return reg_w(sd, R51x_SYS_RESET, 0x00);
case BRIDGE_OV519: case BRIDGE_OV519:
return reg_w(sd, OV519_R51_RESET1, 0x00); reg_w(sd, OV519_R51_RESET1, 0x00);
break;
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
return reg_w_mask(sd, 0x0f, 0x02, 0x02); reg_w_mask(sd, 0x0f, 0x02, 0x02);
break;
case BRIDGE_W9968CF: case BRIDGE_W9968CF:
return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
break;
} }
return 0;
} }
static int ov51x_set_slave_ids(struct sd *sd, u8 slave); static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
/* This does an initial reset of an OmniVision sensor and ensures that I2C /* This does an initial reset of an OmniVision sensor and ensures that I2C
* is synchronized. Returns <0 on failure. * is synchronized. Returns <0 on failure.
...@@ -2387,12 +2374,10 @@ static int init_ov_sensor(struct sd *sd, u8 slave) ...@@ -2387,12 +2374,10 @@ static int init_ov_sensor(struct sd *sd, u8 slave)
{ {
int i; int i;
if (ov51x_set_slave_ids(sd, slave) < 0) ov51x_set_slave_ids(sd, slave);
return -EIO;
/* Reset the sensor */ /* Reset the sensor */
if (i2c_w(sd, 0x12, 0x80) < 0) i2c_w(sd, 0x12, 0x80);
return -EIO;
/* Wait for it to initialize */ /* Wait for it to initialize */
msleep(150); msleep(150);
...@@ -2405,16 +2390,16 @@ static int init_ov_sensor(struct sd *sd, u8 slave) ...@@ -2405,16 +2390,16 @@ static int init_ov_sensor(struct sd *sd, u8 slave)
} }
/* Reset the sensor */ /* Reset the sensor */
if (i2c_w(sd, 0x12, 0x80) < 0) i2c_w(sd, 0x12, 0x80);
return -EIO;
/* Wait for it to initialize */ /* Wait for it to initialize */
msleep(150); msleep(150);
/* Dummy read to sync I2C */ /* Dummy read to sync I2C */
if (i2c_r(sd, 0x00) < 0) if (i2c_r(sd, 0x00) < 0)
return -EIO; return -1;
} }
return -EIO; return -1;
} }
/* Set the read and write slave IDs. The "slave" argument is the write slave, /* Set the read and write slave IDs. The "slave" argument is the write slave,
...@@ -2422,53 +2407,40 @@ static int init_ov_sensor(struct sd *sd, u8 slave) ...@@ -2422,53 +2407,40 @@ static int init_ov_sensor(struct sd *sd, u8 slave)
* This should not be called from outside the i2c I/O functions. * This should not be called from outside the i2c I/O functions.
* Sets I2C read and write slave IDs. Returns <0 for error * Sets I2C read and write slave IDs. Returns <0 for error
*/ */
static int ov51x_set_slave_ids(struct sd *sd, static void ov51x_set_slave_ids(struct sd *sd,
u8 slave) u8 slave)
{ {
int rc;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
return reg_w(sd, OVFX2_I2C_ADDR, slave); reg_w(sd, OVFX2_I2C_ADDR, slave);
return;
case BRIDGE_W9968CF: case BRIDGE_W9968CF:
sd->sensor_addr = slave; sd->sensor_addr = slave;
return 0; return;
} }
rc = reg_w(sd, R51x_I2C_W_SID, slave); reg_w(sd, R51x_I2C_W_SID, slave);
if (rc < 0) reg_w(sd, R51x_I2C_R_SID, slave + 1);
return rc;
return reg_w(sd, R51x_I2C_R_SID, slave + 1);
} }
static int write_regvals(struct sd *sd, static void write_regvals(struct sd *sd,
const struct ov_regvals *regvals, const struct ov_regvals *regvals,
int n) int n)
{ {
int rc;
while (--n >= 0) { while (--n >= 0) {
rc = reg_w(sd, regvals->reg, regvals->val); reg_w(sd, regvals->reg, regvals->val);
if (rc < 0)
return rc;
regvals++; regvals++;
} }
return 0;
} }
static int write_i2c_regvals(struct sd *sd, static void write_i2c_regvals(struct sd *sd,
const struct ov_i2c_regvals *regvals, const struct ov_i2c_regvals *regvals,
int n) int n)
{ {
int rc;
while (--n >= 0) { while (--n >= 0) {
rc = i2c_w(sd, regvals->reg, regvals->val); i2c_w(sd, regvals->reg, regvals->val);
if (rc < 0)
return rc;
regvals++; regvals++;
} }
return 0;
} }
/**************************************************************************** /****************************************************************************
...@@ -2478,13 +2450,13 @@ static int write_i2c_regvals(struct sd *sd, ...@@ -2478,13 +2450,13 @@ static int write_i2c_regvals(struct sd *sd,
***************************************************************************/ ***************************************************************************/
/* This initializes the OV2x10 / OV3610 / OV3620 */ /* This initializes the OV2x10 / OV3610 / OV3620 */
static int ov_hires_configure(struct sd *sd) static void ov_hires_configure(struct sd *sd)
{ {
int high, low; int high, low;
if (sd->bridge != BRIDGE_OVFX2) { if (sd->bridge != BRIDGE_OVFX2) {
err("error hires sensors only supported with ovfx2"); err("error hires sensors only supported with ovfx2");
return -1; return;
} }
PDEBUG(D_PROBE, "starting ov hires configuration"); PDEBUG(D_PROBE, "starting ov hires configuration");
...@@ -2502,18 +2474,13 @@ static int ov_hires_configure(struct sd *sd) ...@@ -2502,18 +2474,13 @@ static int ov_hires_configure(struct sd *sd)
} else { } else {
err("Error unknown sensor type: 0x%02x%02x", err("Error unknown sensor type: 0x%02x%02x",
high, low); high, low);
return -1;
} }
/* Set sensor-specific vars */
return 0;
} }
/* This initializes the OV8110, OV8610 sensor. The OV8110 uses /* This initializes the OV8110, OV8610 sensor. The OV8110 uses
* the same register settings as the OV8610, since they are very similar. * the same register settings as the OV8610, since they are very similar.
*/ */
static int ov8xx0_configure(struct sd *sd) static void ov8xx0_configure(struct sd *sd)
{ {
int rc; int rc;
...@@ -2523,23 +2490,18 @@ static int ov8xx0_configure(struct sd *sd) ...@@ -2523,23 +2490,18 @@ static int ov8xx0_configure(struct sd *sd)
rc = i2c_r(sd, OV7610_REG_COM_I); rc = i2c_r(sd, OV7610_REG_COM_I);
if (rc < 0) { if (rc < 0) {
PDEBUG(D_ERR, "Error detecting sensor type"); PDEBUG(D_ERR, "Error detecting sensor type");
return -1; return;
} }
if ((rc & 3) == 1) { if ((rc & 3) == 1)
sd->sensor = SEN_OV8610; sd->sensor = SEN_OV8610;
} else { else
err("Unknown image sensor version: %d", rc & 3); err("Unknown image sensor version: %d", rc & 3);
return -1;
}
/* Set sensor-specific vars */
return 0;
} }
/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
* the same register settings as the OV7610, since they are very similar. * the same register settings as the OV7610, since they are very similar.
*/ */
static int ov7xx0_configure(struct sd *sd) static void ov7xx0_configure(struct sd *sd)
{ {
int rc, high, low; int rc, high, low;
...@@ -2552,7 +2514,7 @@ static int ov7xx0_configure(struct sd *sd) ...@@ -2552,7 +2514,7 @@ static int ov7xx0_configure(struct sd *sd)
* it appears to be wrongly detected as a 7610 by default */ * it appears to be wrongly detected as a 7610 by default */
if (rc < 0) { if (rc < 0) {
PDEBUG(D_ERR, "Error detecting sensor type"); PDEBUG(D_ERR, "Error detecting sensor type");
return -1; return;
} }
if ((rc & 3) == 3) { if ((rc & 3) == 3) {
/* quick hack to make OV7670s work */ /* quick hack to make OV7670s work */
...@@ -2580,19 +2542,19 @@ static int ov7xx0_configure(struct sd *sd) ...@@ -2580,19 +2542,19 @@ static int ov7xx0_configure(struct sd *sd)
high = i2c_r(sd, 0x0a); high = i2c_r(sd, 0x0a);
if (high < 0) { if (high < 0) {
PDEBUG(D_ERR, "Error detecting camera chip PID"); PDEBUG(D_ERR, "Error detecting camera chip PID");
return high; return;
} }
low = i2c_r(sd, 0x0b); low = i2c_r(sd, 0x0b);
if (low < 0) { if (low < 0) {
PDEBUG(D_ERR, "Error detecting camera chip VER"); PDEBUG(D_ERR, "Error detecting camera chip VER");
return low; return;
} }
if (high == 0x76) { if (high == 0x76) {
switch (low) { switch (low) {
case 0x30: case 0x30:
err("Sensor is an OV7630/OV7635"); err("Sensor is an OV7630/OV7635");
err("7630 is not supported by this driver"); err("7630 is not supported by this driver");
return -1; return;
case 0x40: case 0x40:
PDEBUG(D_PROBE, "Sensor is an OV7645"); PDEBUG(D_PROBE, "Sensor is an OV7645");
sd->sensor = SEN_OV7640; /* FIXME */ sd->sensor = SEN_OV7640; /* FIXME */
...@@ -2607,7 +2569,7 @@ static int ov7xx0_configure(struct sd *sd) ...@@ -2607,7 +2569,7 @@ static int ov7xx0_configure(struct sd *sd)
break; break;
default: default:
PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
return -1; return;
} }
} else { } else {
PDEBUG(D_PROBE, "Sensor is an OV7620"); PDEBUG(D_PROBE, "Sensor is an OV7620");
...@@ -2615,15 +2577,11 @@ static int ov7xx0_configure(struct sd *sd) ...@@ -2615,15 +2577,11 @@ static int ov7xx0_configure(struct sd *sd)
} }
} else { } else {
err("Unknown image sensor version: %d", rc & 3); err("Unknown image sensor version: %d", rc & 3);
return -1;
} }
/* Set sensor-specific vars */
return 0;
} }
/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
static int ov6xx0_configure(struct sd *sd) static void ov6xx0_configure(struct sd *sd)
{ {
int rc; int rc;
PDEBUG(D_PROBE, "starting OV6xx0 configuration"); PDEBUG(D_PROBE, "starting OV6xx0 configuration");
...@@ -2632,7 +2590,7 @@ static int ov6xx0_configure(struct sd *sd) ...@@ -2632,7 +2590,7 @@ static int ov6xx0_configure(struct sd *sd)
rc = i2c_r(sd, OV7610_REG_COM_I); rc = i2c_r(sd, OV7610_REG_COM_I);
if (rc < 0) { if (rc < 0) {
PDEBUG(D_ERR, "Error detecting sensor type"); PDEBUG(D_ERR, "Error detecting sensor type");
return -1; return;
} }
/* Ugh. The first two bits are the version bits, but /* Ugh. The first two bits are the version bits, but
...@@ -2663,13 +2621,11 @@ static int ov6xx0_configure(struct sd *sd) ...@@ -2663,13 +2621,11 @@ static int ov6xx0_configure(struct sd *sd)
break; break;
default: default:
err("FATAL: Unknown sensor version: 0x%02x", rc); err("FATAL: Unknown sensor version: 0x%02x", rc);
return -1; return;
} }
/* Set sensor-specific vars */ /* Set sensor-specific vars */
sd->sif = 1; sd->sif = 1;
return 0;
} }
/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
...@@ -2723,7 +2679,7 @@ static void sd_reset_snapshot(struct gspca_dev *gspca_dev) ...@@ -2723,7 +2679,7 @@ static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
} }
} }
static int ov51x_upload_quan_tables(struct sd *sd) static void ov51x_upload_quan_tables(struct sd *sd)
{ {
const unsigned char yQuanTable511[] = { const unsigned char yQuanTable511[] = {
0, 1, 1, 2, 2, 3, 3, 4, 0, 1, 1, 2, 2, 3, 3, 4,
...@@ -2763,7 +2719,7 @@ static int ov51x_upload_quan_tables(struct sd *sd) ...@@ -2763,7 +2719,7 @@ static int ov51x_upload_quan_tables(struct sd *sd)
const unsigned char *pYTable, *pUVTable; const unsigned char *pYTable, *pUVTable;
unsigned char val0, val1; unsigned char val0, val1;
int i, size, rc, reg = R51x_COMP_LUT_BEGIN; int i, size, reg = R51x_COMP_LUT_BEGIN;
PDEBUG(D_PROBE, "Uploading quantization tables"); PDEBUG(D_PROBE, "Uploading quantization tables");
...@@ -2783,30 +2739,23 @@ static int ov51x_upload_quan_tables(struct sd *sd) ...@@ -2783,30 +2739,23 @@ static int ov51x_upload_quan_tables(struct sd *sd)
val0 &= 0x0f; val0 &= 0x0f;
val1 &= 0x0f; val1 &= 0x0f;
val0 |= val1 << 4; val0 |= val1 << 4;
rc = reg_w(sd, reg, val0); reg_w(sd, reg, val0);
if (rc < 0)
return rc;
val0 = *pUVTable++; val0 = *pUVTable++;
val1 = *pUVTable++; val1 = *pUVTable++;
val0 &= 0x0f; val0 &= 0x0f;
val1 &= 0x0f; val1 &= 0x0f;
val0 |= val1 << 4; val0 |= val1 << 4;
rc = reg_w(sd, reg + size, val0); reg_w(sd, reg + size, val0);
if (rc < 0)
return rc;
reg++; reg++;
} }
return 0;
} }
/* This initializes the OV511/OV511+ and the sensor */ /* This initializes the OV511/OV511+ and the sensor */
static int ov511_configure(struct gspca_dev *gspca_dev) static void ov511_configure(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int rc;
/* For 511 and 511+ */ /* For 511 and 511+ */
const struct ov_regvals init_511[] = { const struct ov_regvals init_511[] = {
...@@ -2852,42 +2801,27 @@ static int ov511_configure(struct gspca_dev *gspca_dev) ...@@ -2852,42 +2801,27 @@ static int ov511_configure(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID)); PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511)); write_regvals(sd, init_511, ARRAY_SIZE(init_511));
if (rc < 0)
return rc;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
if (rc < 0)
return rc;
break; break;
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
if (rc < 0)
return rc;
break; break;
} }
/* Init compression */ /* Init compression */
rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
if (rc < 0)
return rc;
rc = ov51x_upload_quan_tables(sd);
if (rc < 0) {
PDEBUG(D_ERR, "Error uploading quantization tables");
return rc;
}
return 0; ov51x_upload_quan_tables(sd);
} }
/* This initializes the OV518/OV518+ and the sensor */ /* This initializes the OV518/OV518+ and the sensor */
static int ov518_configure(struct gspca_dev *gspca_dev) static void ov518_configure(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int rc;
/* For 518 and 518+ */ /* For 518 and 518+ */
const struct ov_regvals init_518[] = { const struct ov_regvals init_518[] = {
...@@ -2937,42 +2871,26 @@ static int ov518_configure(struct gspca_dev *gspca_dev) ...@@ -2937,42 +2871,26 @@ static int ov518_configure(struct gspca_dev *gspca_dev)
PDEBUG(D_PROBE, "Device revision %d", PDEBUG(D_PROBE, "Device revision %d",
0x1f & reg_r(sd, R51x_SYS_CUST_ID)); 0x1f & reg_r(sd, R51x_SYS_CUST_ID));
rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518)); write_regvals(sd, init_518, ARRAY_SIZE(init_518));
if (rc < 0)
return rc;
/* Set LED GPIO pin to output mode */ /* Set LED GPIO pin to output mode */
rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
if (rc < 0)
return rc;
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV518: case BRIDGE_OV518:
rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
if (rc < 0)
return rc;
break; break;
case BRIDGE_OV518PLUS: case BRIDGE_OV518PLUS:
rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
if (rc < 0)
return rc;
break; break;
} }
rc = ov51x_upload_quan_tables(sd); ov51x_upload_quan_tables(sd);
if (rc < 0) {
PDEBUG(D_ERR, "Error uploading quantization tables");
return rc;
}
rc = reg_w(sd, 0x2f, 0x80);
if (rc < 0)
return rc;
return 0; reg_w(sd, 0x2f, 0x80);
} }
static int ov519_configure(struct sd *sd) static void ov519_configure(struct sd *sd)
{ {
static const struct ov_regvals init_519[] = { static const struct ov_regvals init_519[] = {
{ 0x5a, 0x6d }, /* EnableSystem */ { 0x5a, 0x6d }, /* EnableSystem */
...@@ -2990,10 +2908,10 @@ static int ov519_configure(struct sd *sd) ...@@ -2990,10 +2908,10 @@ static int ov519_configure(struct sd *sd)
/* windows reads 0x55 at this point*/ /* windows reads 0x55 at this point*/
}; };
return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); write_regvals(sd, init_519, ARRAY_SIZE(init_519));
} }
static int ovfx2_configure(struct sd *sd) static void ovfx2_configure(struct sd *sd)
{ {
static const struct ov_regvals init_fx2[] = { static const struct ov_regvals init_fx2[] = {
{ 0x00, 0x60 }, { 0x00, 0x60 },
...@@ -3007,7 +2925,7 @@ static int ovfx2_configure(struct sd *sd) ...@@ -3007,7 +2925,7 @@ static int ovfx2_configure(struct sd *sd)
sd->stopped = 1; sd->stopped = 1;
return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
} }
/* this function is called at probe time */ /* this function is called at probe time */
...@@ -3016,7 +2934,6 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -3016,7 +2934,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam = &gspca_dev->cam; struct cam *cam = &gspca_dev->cam;
int ret = 0;
sd->bridge = id->driver_info & BRIDGE_MASK; sd->bridge = id->driver_info & BRIDGE_MASK;
sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; sd->invert_led = id->driver_info & BRIDGE_INVERT_LED;
...@@ -3024,30 +2941,27 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -3024,30 +2941,27 @@ static int sd_config(struct gspca_dev *gspca_dev,
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
ret = ov511_configure(gspca_dev); ov511_configure(gspca_dev);
break; break;
case BRIDGE_OV518: case BRIDGE_OV518:
case BRIDGE_OV518PLUS: case BRIDGE_OV518PLUS:
ret = ov518_configure(gspca_dev); ov518_configure(gspca_dev);
break; break;
case BRIDGE_OV519: case BRIDGE_OV519:
ret = ov519_configure(sd); ov519_configure(sd);
break; break;
case BRIDGE_OVFX2: case BRIDGE_OVFX2:
ret = ovfx2_configure(sd); ovfx2_configure(sd);
cam->bulk_size = OVFX2_BULK_SIZE; cam->bulk_size = OVFX2_BULK_SIZE;
cam->bulk_nurbs = MAX_NURBS; cam->bulk_nurbs = MAX_NURBS;
cam->bulk = 1; cam->bulk = 1;
break; break;
case BRIDGE_W9968CF: case BRIDGE_W9968CF:
ret = w9968cf_configure(sd); w9968cf_configure(sd);
cam->reverse_alts = 1; cam->reverse_alts = 1;
break; break;
} }
if (ret)
goto error;
ov51x_led_control(sd, 0); /* turn LED off */ ov51x_led_control(sd, 0); /* turn LED off */
/* The OV519 must be more aggressive about sensor detection since /* The OV519 must be more aggressive about sensor detection since
...@@ -3057,28 +2971,19 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -3057,28 +2971,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
/* Test for 76xx */ /* Test for 76xx */
if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { if (init_ov_sensor(sd, OV7xx0_SID) >= 0) {
if (ov7xx0_configure(sd) < 0) { ov7xx0_configure(sd);
PDEBUG(D_ERR, "Failed to configure OV7xx0");
goto error;
}
/* Test for 6xx0 */ /* Test for 6xx0 */
} else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) {
if (ov6xx0_configure(sd) < 0) { ov6xx0_configure(sd);
PDEBUG(D_ERR, "Failed to configure OV6xx0");
goto error;
}
/* Test for 8xx0 */ /* Test for 8xx0 */
} else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) {
if (ov8xx0_configure(sd) < 0) { ov8xx0_configure(sd);
PDEBUG(D_ERR, "Failed to configure OV8xx0");
goto error;
}
/* Test for 3xxx / 2xxx */ /* Test for 3xxx / 2xxx */
} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
if (ov_hires_configure(sd) < 0) { ov_hires_configure(sd);
PDEBUG(D_ERR, "Failed to configure high res OV");
goto error;
}
} else { } else {
err("Can't determine sensor slave IDs"); err("Can't determine sensor slave IDs");
goto error; goto error;
...@@ -3139,8 +3044,7 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -3139,8 +3044,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->nmodes--; cam->nmodes--;
/* w9968cf needs initialisation once the sensor is known */ /* w9968cf needs initialisation once the sensor is known */
if (w9968cf_init(sd) < 0) w9968cf_init(sd);
goto error;
break; break;
} }
gspca_dev->cam.ctrls = sd->ctrls; gspca_dev->cam.ctrls = sd->ctrls;
...@@ -3148,7 +3052,7 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -3148,7 +3052,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
return 0; return gspca_dev->usb_err;
error: error:
PDEBUG(D_ERR, "OV519 Config failed"); PDEBUG(D_ERR, "OV519 Config failed");
return -EINVAL; return -EINVAL;
...@@ -3162,67 +3066,57 @@ static int sd_init(struct gspca_dev *gspca_dev) ...@@ -3162,67 +3066,57 @@ static int sd_init(struct gspca_dev *gspca_dev)
/* initialize the sensor */ /* initialize the sensor */
switch (sd->sensor) { switch (sd->sensor) {
case SEN_OV2610: case SEN_OV2610:
if (write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610))) write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610));
return -EIO;
/* Enable autogain, autoexpo, awb, bandfilter */ /* Enable autogain, autoexpo, awb, bandfilter */
if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) i2c_w_mask(sd, 0x13, 0x27, 0x27);
return -EIO;
break; break;
case SEN_OV3610: case SEN_OV3610:
if (write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b))) write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
return -EIO;
/* Enable autogain, autoexpo, awb, bandfilter */ /* Enable autogain, autoexpo, awb, bandfilter */
if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) i2c_w_mask(sd, 0x13, 0x27, 0x27);
return -EIO;
break; break;
case SEN_OV6620: case SEN_OV6620:
if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20));
return -EIO;
break; break;
case SEN_OV6630: case SEN_OV6630:
case SEN_OV66308AF: case SEN_OV66308AF:
sd->ctrls[CONTRAST].def = 200; sd->ctrls[CONTRAST].def = 200;
/* The default is too low for the ov6630 */ /* The default is too low for the ov6630 */
if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30));
return -EIO;
break; break;
default: default:
/* case SEN_OV7610: */ /* case SEN_OV7610: */
/* case SEN_OV76BE: */ /* case SEN_OV76BE: */
if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610));
return -EIO; i2c_w_mask(sd, 0x0e, 0x00, 0x40);
if (i2c_w_mask(sd, 0x0e, 0x00, 0x40))
return -EIO;
break; break;
case SEN_OV7620: case SEN_OV7620:
case SEN_OV7620AE: case SEN_OV7620AE:
if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620));
return -EIO;
break; break;
case SEN_OV7640: case SEN_OV7640:
case SEN_OV7648: case SEN_OV7648:
if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640));
return -EIO;
break; break;
case SEN_OV7670: case SEN_OV7670:
sd->ctrls[FREQ].max = 3; /* auto */ sd->ctrls[FREQ].max = 3; /* auto */
sd->ctrls[FREQ].def = 3; sd->ctrls[FREQ].def = 3;
if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670));
return -EIO;
break; break;
case SEN_OV8610: case SEN_OV8610:
if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
return -EIO;
break; break;
} }
return 0; return gspca_dev->usb_err;
} }
/* Set up the OV511/OV511+ with the given image parameters. /* Set up the OV511/OV511+ with the given image parameters.
* *
* Do not put any sensor-specific code in here (including I2C I/O functions) * Do not put any sensor-specific code in here (including I2C I/O functions)
*/ */
static int ov511_mode_init_regs(struct sd *sd) static void ov511_mode_init_regs(struct sd *sd)
{ {
int hsegs, vsegs, packet_size, fps, needed; int hsegs, vsegs, packet_size, fps, needed;
int interlaced = 0; int interlaced = 0;
...@@ -3233,7 +3127,8 @@ static int ov511_mode_init_regs(struct sd *sd) ...@@ -3233,7 +3127,8 @@ static int ov511_mode_init_regs(struct sd *sd)
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) { if (!alt) {
err("Couldn't get altsetting"); err("Couldn't get altsetting");
return -EIO; sd->gspca_dev.usb_err = -EIO;
return;
} }
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
...@@ -3336,8 +3231,6 @@ static int ov511_mode_init_regs(struct sd *sd) ...@@ -3336,8 +3231,6 @@ static int ov511_mode_init_regs(struct sd *sd)
reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
reg_w(sd, R51x_SYS_RESET, 0); reg_w(sd, R51x_SYS_RESET, 0);
return 0;
} }
/* Sets up the OV518/OV518+ with the given image parameters /* Sets up the OV518/OV518+ with the given image parameters
...@@ -3347,7 +3240,7 @@ static int ov511_mode_init_regs(struct sd *sd) ...@@ -3347,7 +3240,7 @@ static int ov511_mode_init_regs(struct sd *sd)
* *
* Do not put any sensor-specific code in here (including I2C I/O functions) * Do not put any sensor-specific code in here (including I2C I/O functions)
*/ */
static int ov518_mode_init_regs(struct sd *sd) static void ov518_mode_init_regs(struct sd *sd)
{ {
int hsegs, vsegs, packet_size; int hsegs, vsegs, packet_size;
struct usb_host_interface *alt; struct usb_host_interface *alt;
...@@ -3357,7 +3250,8 @@ static int ov518_mode_init_regs(struct sd *sd) ...@@ -3357,7 +3250,8 @@ static int ov518_mode_init_regs(struct sd *sd)
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) { if (!alt) {
err("Couldn't get altsetting"); err("Couldn't get altsetting");
return -EIO; sd->gspca_dev.usb_err = -EIO;
return;
} }
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
...@@ -3460,8 +3354,6 @@ static int ov518_mode_init_regs(struct sd *sd) ...@@ -3460,8 +3354,6 @@ static int ov518_mode_init_regs(struct sd *sd)
} }
reg_w(sd, 0x2f, 0x80); reg_w(sd, 0x2f, 0x80);
return 0;
} }
/* Sets up the OV519 with the given image parameters /* Sets up the OV519 with the given image parameters
...@@ -3471,7 +3363,7 @@ static int ov518_mode_init_regs(struct sd *sd) ...@@ -3471,7 +3363,7 @@ static int ov518_mode_init_regs(struct sd *sd)
* *
* Do not put any sensor-specific code in here (including I2C I/O functions) * Do not put any sensor-specific code in here (including I2C I/O functions)
*/ */
static int ov519_mode_init_regs(struct sd *sd) static void ov519_mode_init_regs(struct sd *sd)
{ {
static const struct ov_regvals mode_init_519_ov7670[] = { static const struct ov_regvals mode_init_519_ov7670[] = {
{ 0x5d, 0x03 }, /* Turn off suspend mode */ { 0x5d, 0x03 }, /* Turn off suspend mode */
...@@ -3519,18 +3411,15 @@ static int ov519_mode_init_regs(struct sd *sd) ...@@ -3519,18 +3411,15 @@ static int ov519_mode_init_regs(struct sd *sd)
/******** Set the mode ********/ /******** Set the mode ********/
if (sd->sensor != SEN_OV7670) { if (sd->sensor != SEN_OV7670) {
if (write_regvals(sd, mode_init_519, write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519));
ARRAY_SIZE(mode_init_519)))
return -EIO;
if (sd->sensor == SEN_OV7640 || if (sd->sensor == SEN_OV7640 ||
sd->sensor == SEN_OV7648) { sd->sensor == SEN_OV7648) {
/* Select 8-bit input mode */ /* Select 8-bit input mode */
reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
} }
} else { } else {
if (write_regvals(sd, mode_init_519_ov7670, write_regvals(sd, mode_init_519_ov7670,
ARRAY_SIZE(mode_init_519_ov7670))) ARRAY_SIZE(mode_init_519_ov7670));
return -EIO;
} }
reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4);
...@@ -3626,10 +3515,9 @@ static int ov519_mode_init_regs(struct sd *sd) ...@@ -3626,10 +3515,9 @@ static int ov519_mode_init_regs(struct sd *sd)
} }
break; break;
} }
return 0;
} }
static int mode_init_ov_sensor_regs(struct sd *sd) static void mode_init_ov_sensor_regs(struct sd *sd)
{ {
struct gspca_dev *gspca_dev; struct gspca_dev *gspca_dev;
int qvga, xstart, xend, ystart, yend; int qvga, xstart, xend, ystart, yend;
...@@ -3648,7 +3536,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) ...@@ -3648,7 +3536,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
return 0; return;
case SEN_OV3610: case SEN_OV3610:
if (qvga) { if (qvga) {
xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
...@@ -3672,7 +3560,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) ...@@ -3672,7 +3560,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
i2c_w(sd, 0x18, xend >> 4); i2c_w(sd, 0x18, xend >> 4);
i2c_w(sd, 0x19, ystart >> 3); i2c_w(sd, 0x19, ystart >> 3);
i2c_w(sd, 0x1a, yend >> 3); i2c_w(sd, 0x1a, yend >> 3);
return 0; return;
case SEN_OV8610: case SEN_OV8610:
/* For OV8610 qvga means qsvga */ /* For OV8610 qvga means qsvga */
i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
...@@ -3766,13 +3654,11 @@ static int mode_init_ov_sensor_regs(struct sd *sd) ...@@ -3766,13 +3654,11 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
break; break;
default: default:
return -EINVAL; return;
} }
/******** Clock programming ********/ /******** Clock programming ********/
i2c_w(sd, 0x11, sd->clockdiv); i2c_w(sd, 0x11, sd->clockdiv);
return 0;
} }
static void sethvflip(struct gspca_dev *gspca_dev) static void sethvflip(struct gspca_dev *gspca_dev)
...@@ -3791,18 +3677,18 @@ static void sethvflip(struct gspca_dev *gspca_dev) ...@@ -3791,18 +3677,18 @@ static void sethvflip(struct gspca_dev *gspca_dev)
ov51x_restart(sd); ov51x_restart(sd);
} }
static int set_ov_sensor_window(struct sd *sd) static void set_ov_sensor_window(struct sd *sd)
{ {
struct gspca_dev *gspca_dev; struct gspca_dev *gspca_dev;
int qvga, crop; int qvga, crop;
int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
int ret;
/* mode setup is fully handled in mode_init_ov_sensor_regs for these */ /* mode setup is fully handled in mode_init_ov_sensor_regs for these */
if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 ||
sd->sensor == SEN_OV7670) sd->sensor == SEN_OV7670) {
return mode_init_ov_sensor_regs(sd); mode_init_ov_sensor_regs(sd);
return;
}
gspca_dev = &sd->gspca_dev; gspca_dev = &sd->gspca_dev;
qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2;
...@@ -3852,7 +3738,7 @@ static int set_ov_sensor_window(struct sd *sd) ...@@ -3852,7 +3738,7 @@ static int set_ov_sensor_window(struct sd *sd)
vwsbase = vwebase = 0x03; vwsbase = vwebase = 0x03;
break; break;
default: default:
return -EINVAL; return;
} }
switch (sd->sensor) { switch (sd->sensor) {
...@@ -3887,23 +3773,18 @@ static int set_ov_sensor_window(struct sd *sd) ...@@ -3887,23 +3773,18 @@ static int set_ov_sensor_window(struct sd *sd)
} }
} }
ret = mode_init_ov_sensor_regs(sd); mode_init_ov_sensor_regs(sd);
if (ret < 0)
return ret;
i2c_w(sd, 0x17, hwsbase); i2c_w(sd, 0x17, hwsbase);
i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
i2c_w(sd, 0x19, vwsbase); i2c_w(sd, 0x19, vwsbase);
i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
return 0;
} }
/* -- start the camera -- */ /* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int ret = 0;
/* Default for most bridges, allow bridge_mode_init_regs to override */ /* Default for most bridges, allow bridge_mode_init_regs to override */
sd->sensor_width = sd->gspca_dev.width; sd->sensor_width = sd->gspca_dev.width;
...@@ -3912,26 +3793,22 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -3912,26 +3793,22 @@ static int sd_start(struct gspca_dev *gspca_dev)
switch (sd->bridge) { switch (sd->bridge) {
case BRIDGE_OV511: case BRIDGE_OV511:
case BRIDGE_OV511PLUS: case BRIDGE_OV511PLUS:
ret = ov511_mode_init_regs(sd); ov511_mode_init_regs(sd);
break; break;
case BRIDGE_OV518: case BRIDGE_OV518:
case BRIDGE_OV518PLUS: case BRIDGE_OV518PLUS:
ret = ov518_mode_init_regs(sd); ov518_mode_init_regs(sd);
break; break;
case BRIDGE_OV519: case BRIDGE_OV519:
ret = ov519_mode_init_regs(sd); ov519_mode_init_regs(sd);
break; break;
/* case BRIDGE_OVFX2: nothing to do */ /* case BRIDGE_OVFX2: nothing to do */
case BRIDGE_W9968CF: case BRIDGE_W9968CF:
ret = w9968cf_mode_init_regs(sd); w9968cf_mode_init_regs(sd);
break; break;
} }
if (ret < 0)
goto out;
ret = set_ov_sensor_window(sd); set_ov_sensor_window(sd);
if (ret < 0)
goto out;
setcontrast(gspca_dev); setcontrast(gspca_dev);
setbrightness(gspca_dev); setbrightness(gspca_dev);
...@@ -3947,14 +3824,9 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -3947,14 +3824,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
sd->first_frame = 3; sd->first_frame = 3;
ret = ov51x_restart(sd); ov51x_restart(sd);
if (ret < 0)
goto out;
ov51x_led_control(sd, 1); ov51x_led_control(sd, 1);
return 0; return gspca_dev->usb_err;
out:
PDEBUG(D_ERR, "camera start error:%d", ret);
return ret;
} }
static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev)
......
...@@ -59,18 +59,21 @@ static const struct v4l2_pix_format w9968cf_vga_mode[] = { ...@@ -59,18 +59,21 @@ static const struct v4l2_pix_format w9968cf_vga_mode[] = {
.colorspace = V4L2_COLORSPACE_JPEG}, .colorspace = V4L2_COLORSPACE_JPEG},
}; };
static int reg_w(struct sd *sd, u16 index, u16 value); static void reg_w(struct sd *sd, u16 index, u16 value);
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
Write 64-bit data to the fast serial bus registers. Write 64-bit data to the fast serial bus registers.
Return 0 on success, -1 otherwise. Return 0 on success, -1 otherwise.
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
static int w9968cf_write_fsb(struct sd *sd, u16* data) static void w9968cf_write_fsb(struct sd *sd, u16* data)
{ {
struct usb_device *udev = sd->gspca_dev.dev; struct usb_device *udev = sd->gspca_dev.dev;
u16 value; u16 value;
int ret; int ret;
if (sd->gspca_dev.usb_err < 0)
return;
value = *data++; value = *data++;
memcpy(sd->gspca_dev.usb_buf, data, 6); memcpy(sd->gspca_dev.usb_buf, data, 6);
...@@ -79,20 +82,21 @@ static int w9968cf_write_fsb(struct sd *sd, u16* data) ...@@ -79,20 +82,21 @@ static int w9968cf_write_fsb(struct sd *sd, u16* data)
value, 0x06, sd->gspca_dev.usb_buf, 6, 500); value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
if (ret < 0) { if (ret < 0) {
err("Write FSB registers failed (%d)", ret); err("Write FSB registers failed (%d)", ret);
return ret; sd->gspca_dev.usb_err = ret;
} }
return 0;
} }
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
Write data to the serial bus control register. Write data to the serial bus control register.
Return 0 on success, a negative number otherwise. Return 0 on success, a negative number otherwise.
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
static int w9968cf_write_sb(struct sd *sd, u16 value) static void w9968cf_write_sb(struct sd *sd, u16 value)
{ {
int ret; int ret;
if (sd->gspca_dev.usb_err < 0)
return;
/* We don't use reg_w here, as that would cause all writes when /* We don't use reg_w here, as that would cause all writes when
bitbanging i2c to be logged, making the logs impossible to read */ bitbanging i2c to be logged, making the logs impossible to read */
ret = usb_control_msg(sd->gspca_dev.dev, ret = usb_control_msg(sd->gspca_dev.dev,
...@@ -105,10 +109,8 @@ static int w9968cf_write_sb(struct sd *sd, u16 value) ...@@ -105,10 +109,8 @@ static int w9968cf_write_sb(struct sd *sd, u16 value)
if (ret < 0) { if (ret < 0) {
err("Write SB reg [01] %04x failed", value); err("Write SB reg [01] %04x failed", value);
return ret; sd->gspca_dev.usb_err = ret;
} }
return 0;
} }
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
...@@ -119,6 +121,9 @@ static int w9968cf_read_sb(struct sd *sd) ...@@ -119,6 +121,9 @@ static int w9968cf_read_sb(struct sd *sd)
{ {
int ret; int ret;
if (sd->gspca_dev.usb_err < 0)
return -1;
/* We don't use reg_r here, as the w9968cf is special and has 16 /* We don't use reg_r here, as the w9968cf is special and has 16
bit registers instead of 8 bit */ bit registers instead of 8 bit */
ret = usb_control_msg(sd->gspca_dev.dev, ret = usb_control_msg(sd->gspca_dev.dev,
...@@ -126,11 +131,13 @@ static int w9968cf_read_sb(struct sd *sd) ...@@ -126,11 +131,13 @@ static int w9968cf_read_sb(struct sd *sd)
1, 1,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, 0x01, sd->gspca_dev.usb_buf, 2, 500); 0, 0x01, sd->gspca_dev.usb_buf, 2, 500);
if (ret >= 0) if (ret >= 0) {
ret = sd->gspca_dev.usb_buf[0] | ret = sd->gspca_dev.usb_buf[0] |
(sd->gspca_dev.usb_buf[1] << 8); (sd->gspca_dev.usb_buf[1] << 8);
else } else {
err("Read SB reg [01] failed"); err("Read SB reg [01] failed");
sd->gspca_dev.usb_err = ret;
}
udelay(W9968CF_I2C_BUS_DELAY); udelay(W9968CF_I2C_BUS_DELAY);
...@@ -142,12 +149,12 @@ static int w9968cf_read_sb(struct sd *sd) ...@@ -142,12 +149,12 @@ static int w9968cf_read_sb(struct sd *sd)
This function is called by w9968cf_start_transfer(). This function is called by w9968cf_start_transfer().
Return 0 on success, a negative number otherwise. Return 0 on success, a negative number otherwise.
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
static int w9968cf_upload_quantizationtables(struct sd *sd) static void w9968cf_upload_quantizationtables(struct sd *sd)
{ {
u16 a, b; u16 a, b;
int ret = 0, i, j; int i, j;
ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */
for (i = 0, j = 0; i < 32; i++, j += 2) { for (i = 0, j = 0; i < 32; i++, j += 2) {
a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8); a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8);
...@@ -155,9 +162,7 @@ static int w9968cf_upload_quantizationtables(struct sd *sd) ...@@ -155,9 +162,7 @@ static int w9968cf_upload_quantizationtables(struct sd *sd)
reg_w(sd, 0x40 + i, a); reg_w(sd, 0x40 + i, a);
reg_w(sd, 0x60 + i, b); reg_w(sd, 0x60 + i, b);
} }
ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */
return ret;
} }
/**************************************************************************** /****************************************************************************
...@@ -168,50 +173,39 @@ static int w9968cf_upload_quantizationtables(struct sd *sd) ...@@ -168,50 +173,39 @@ static int w9968cf_upload_quantizationtables(struct sd *sd)
* i2c_adap_read_byte() * * i2c_adap_read_byte() *
****************************************************************************/ ****************************************************************************/
static int w9968cf_smbus_start(struct sd *sd) static void w9968cf_smbus_start(struct sd *sd)
{ {
int ret = 0; w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
return ret;
} }
static int w9968cf_smbus_stop(struct sd *sd) static void w9968cf_smbus_stop(struct sd *sd)
{ {
int ret = 0; w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
return ret;
} }
static int w9968cf_smbus_write_byte(struct sd *sd, u8 v) static void w9968cf_smbus_write_byte(struct sd *sd, u8 v)
{ {
u8 bit; u8 bit;
int ret = 0, sda; int sda;
for (bit = 0 ; bit < 8 ; bit++) { for (bit = 0 ; bit < 8 ; bit++) {
sda = (v & 0x80) ? 2 : 0; sda = (v & 0x80) ? 2 : 0;
v <<= 1; v <<= 1;
/* SDE=1, SDA=sda, SCL=0 */ /* SDE=1, SDA=sda, SCL=0 */
ret += w9968cf_write_sb(sd, 0x10 | sda); w9968cf_write_sb(sd, 0x10 | sda);
/* SDE=1, SDA=sda, SCL=1 */ /* SDE=1, SDA=sda, SCL=1 */
ret += w9968cf_write_sb(sd, 0x11 | sda); w9968cf_write_sb(sd, 0x11 | sda);
/* SDE=1, SDA=sda, SCL=0 */ /* SDE=1, SDA=sda, SCL=0 */
ret += w9968cf_write_sb(sd, 0x10 | sda); w9968cf_write_sb(sd, 0x10 | sda);
} }
return ret;
} }
static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v)
{ {
u8 bit; u8 bit;
int ret = 0;
/* No need to ensure SDA is high as we are always called after /* No need to ensure SDA is high as we are always called after
read_ack which ends with SDA high */ read_ack which ends with SDA high */
...@@ -219,51 +213,40 @@ static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) ...@@ -219,51 +213,40 @@ static int w9968cf_smbus_read_byte(struct sd *sd, u8* v)
for (bit = 0 ; bit < 8 ; bit++) { for (bit = 0 ; bit < 8 ; bit++) {
*v <<= 1; *v <<= 1;
/* SDE=1, SDA=1, SCL=1 */ /* SDE=1, SDA=1, SCL=1 */
ret += w9968cf_write_sb(sd, 0x0013); w9968cf_write_sb(sd, 0x0013);
*v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0;
/* SDE=1, SDA=1, SCL=0 */ /* SDE=1, SDA=1, SCL=0 */
ret += w9968cf_write_sb(sd, 0x0012); w9968cf_write_sb(sd, 0x0012);
} }
return ret;
} }
static int w9968cf_smbus_write_nack(struct sd *sd) static void w9968cf_smbus_write_nack(struct sd *sd)
{ {
int ret = 0;
/* No need to ensure SDA is high as we are always called after /* No need to ensure SDA is high as we are always called after
read_byte which ends with SDA high */ read_byte which ends with SDA high */
ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
return ret;
} }
static int w9968cf_smbus_read_ack(struct sd *sd) static void w9968cf_smbus_read_ack(struct sd *sd)
{ {
int ret = 0, sda; int sda;
/* Ensure SDA is high before raising clock to avoid a spurious stop */ /* Ensure SDA is high before raising clock to avoid a spurious stop */
ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
sda = w9968cf_read_sb(sd); sda = w9968cf_read_sb(sd);
ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
if (sda < 0) if (sda >= 0 && (sda & 0x08)) {
ret += sda;
else if (sda & 0x08) {
PDEBUG(D_USBI, "Did not receive i2c ACK"); PDEBUG(D_USBI, "Did not receive i2c ACK");
ret += -1; sd->gspca_dev.usb_err = -EIO;
} }
return ret;
} }
/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
{ {
u16* data = (u16 *)sd->gspca_dev.usb_buf; u16* data = (u16 *)sd->gspca_dev.usb_buf;
int ret = 0;
data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0);
data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0;
...@@ -276,7 +259,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) ...@@ -276,7 +259,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0);
data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0;
ret += w9968cf_write_fsb(sd, data); w9968cf_write_fsb(sd, data);
data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0);
data[0] |= (reg & 0x40) ? 0x0540 : 0x0; data[0] |= (reg & 0x40) ? 0x0540 : 0x0;
...@@ -290,7 +273,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) ...@@ -290,7 +273,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
data[2] |= (reg & 0x01) ? 0x5400 : 0x0; data[2] |= (reg & 0x01) ? 0x5400 : 0x0;
data[3] = 0x001d; data[3] = 0x001d;
ret += w9968cf_write_fsb(sd, data); w9968cf_write_fsb(sd, data);
data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0);
data[0] |= (value & 0x40) ? 0x0540 : 0x0; data[0] |= (value & 0x40) ? 0x0540 : 0x0;
...@@ -304,14 +287,9 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) ...@@ -304,14 +287,9 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
data[2] |= (value & 0x01) ? 0x5400 : 0x0; data[2] |= (value & 0x01) ? 0x5400 : 0x0;
data[3] = 0xfe1d; data[3] = 0xfe1d;
ret += w9968cf_write_fsb(sd, data); w9968cf_write_fsb(sd, data);
if (!ret)
PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
else
PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg);
return ret; PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
} }
/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
...@@ -321,28 +299,28 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) ...@@ -321,28 +299,28 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg)
u8 value; u8 value;
/* Fast serial bus data control disable */ /* Fast serial bus data control disable */
ret += w9968cf_write_sb(sd, 0x0013); /* don't change ! */ w9968cf_write_sb(sd, 0x0013); /* don't change ! */
ret += w9968cf_smbus_start(sd); w9968cf_smbus_start(sd);
ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr); w9968cf_smbus_write_byte(sd, sd->sensor_addr);
ret += w9968cf_smbus_read_ack(sd); w9968cf_smbus_read_ack(sd);
ret += w9968cf_smbus_write_byte(sd, reg); w9968cf_smbus_write_byte(sd, reg);
ret += w9968cf_smbus_read_ack(sd); w9968cf_smbus_read_ack(sd);
ret += w9968cf_smbus_stop(sd); w9968cf_smbus_stop(sd);
ret += w9968cf_smbus_start(sd); w9968cf_smbus_start(sd);
ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1);
ret += w9968cf_smbus_read_ack(sd); w9968cf_smbus_read_ack(sd);
ret += w9968cf_smbus_read_byte(sd, &value); w9968cf_smbus_read_byte(sd, &value);
/* signal we don't want to read anymore, the v4l1 driver used to /* signal we don't want to read anymore, the v4l1 driver used to
send an ack here which is very wrong! (and then fixed send an ack here which is very wrong! (and then fixed
the issues this gave by retrying reads) */ the issues this gave by retrying reads) */
ret += w9968cf_smbus_write_nack(sd); w9968cf_smbus_write_nack(sd);
ret += w9968cf_smbus_stop(sd); w9968cf_smbus_stop(sd);
/* Fast serial bus data control re-enable */ /* Fast serial bus data control re-enable */
ret += w9968cf_write_sb(sd, 0x0030); w9968cf_write_sb(sd, 0x0030);
if (!ret) { if (sd->gspca_dev.usb_err >= 0) {
ret = value; ret = value;
PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
} else } else
...@@ -355,29 +333,21 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) ...@@ -355,29 +333,21 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg)
Turn on the LED on some webcams. A beep should be heard too. Turn on the LED on some webcams. A beep should be heard too.
Return 0 on success, a negative number otherwise. Return 0 on success, a negative number otherwise.
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
static int w9968cf_configure(struct sd *sd) static void w9968cf_configure(struct sd *sd)
{ {
int ret = 0; reg_w(sd, 0x00, 0xff00); /* power-down */
reg_w(sd, 0x00, 0xbf17); /* reset everything */
ret += reg_w(sd, 0x00, 0xff00); /* power-down */ reg_w(sd, 0x00, 0xbf10); /* normal operation */
ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */
ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */
ret += reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */
ret += reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */
ret += reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */
ret += reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */
if (ret)
PDEBUG(D_ERR, "Couldn't turn on the LED");
sd->stopped = 1; sd->stopped = 1;
return ret;
} }
static int w9968cf_init(struct sd *sd) static void w9968cf_init(struct sd *sd)
{ {
int ret = 0;
unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2),
y0 = 0x0000, y0 = 0x0000,
u0 = y0 + hw_bufsize / 2, u0 = y0 + hw_bufsize / 2,
...@@ -386,43 +356,41 @@ static int w9968cf_init(struct sd *sd) ...@@ -386,43 +356,41 @@ static int w9968cf_init(struct sd *sd)
u1 = y1 + hw_bufsize / 2, u1 = y1 + hw_bufsize / 2,
v1 = u1 + hw_bufsize / 4; v1 = u1 + hw_bufsize / 4;
ret += reg_w(sd, 0x00, 0xff00); /* power off */ reg_w(sd, 0x00, 0xff00); /* power off */
ret += reg_w(sd, 0x00, 0xbf10); /* power on */ reg_w(sd, 0x00, 0xbf10); /* power on */
ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */
ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
ret += reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ reg_w(sd, 0x03, 0x405d); /* DRAM timings */
ret += reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
ret += reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */
ret += reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */
ret += reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */
ret += reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */
ret += reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */
ret += reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */
ret += reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */
ret += reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */
ret += reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */
ret += reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */
ret += reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */
ret += reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */
reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */
reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */
reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */
reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */
ret += reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */
ret += reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */
ret += reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
ret += reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */
ret += reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */
ret += reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */
return ret; reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */
reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/
reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */
reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */
} }
static int w9968cf_set_crop_window(struct sd *sd) static void w9968cf_set_crop_window(struct sd *sd)
{ {
int ret = 0, start_cropx, start_cropy, x, y, fw, fh, cw, ch, int start_cropx, start_cropy, x, y, fw, fh, cw, ch,
max_width, max_height; max_width, max_height;
if (sd->sif) { if (sd->sif) {
...@@ -464,42 +432,40 @@ static int w9968cf_set_crop_window(struct sd *sd) ...@@ -464,42 +432,40 @@ static int w9968cf_set_crop_window(struct sd *sd)
x = (max_width - cw) / 2; x = (max_width - cw) / 2;
y = (max_height - ch) / 2; y = (max_height - ch) / 2;
ret += reg_w(sd, 0x10, start_cropx + x); reg_w(sd, 0x10, start_cropx + x);
ret += reg_w(sd, 0x11, start_cropy + y); reg_w(sd, 0x11, start_cropy + y);
ret += reg_w(sd, 0x12, start_cropx + x + cw); reg_w(sd, 0x12, start_cropx + x + cw);
ret += reg_w(sd, 0x13, start_cropy + y + ch); reg_w(sd, 0x13, start_cropy + y + ch);
return ret;
} }
static int w9968cf_mode_init_regs(struct sd *sd) static void w9968cf_mode_init_regs(struct sd *sd)
{ {
int ret = 0, val, vs_polarity, hs_polarity; int val, vs_polarity, hs_polarity;
ret += w9968cf_set_crop_window(sd); w9968cf_set_crop_window(sd);
ret += reg_w(sd, 0x14, sd->gspca_dev.width); reg_w(sd, 0x14, sd->gspca_dev.width);
ret += reg_w(sd, 0x15, sd->gspca_dev.height); reg_w(sd, 0x15, sd->gspca_dev.height);
/* JPEG width & height */ /* JPEG width & height */
ret += reg_w(sd, 0x30, sd->gspca_dev.width); reg_w(sd, 0x30, sd->gspca_dev.width);
ret += reg_w(sd, 0x31, sd->gspca_dev.height); reg_w(sd, 0x31, sd->gspca_dev.height);
/* Y & UV frame buffer strides (in WORD) */ /* Y & UV frame buffer strides (in WORD) */
if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
V4L2_PIX_FMT_JPEG) { V4L2_PIX_FMT_JPEG) {
ret += reg_w(sd, 0x2c, sd->gspca_dev.width / 2); reg_w(sd, 0x2c, sd->gspca_dev.width / 2);
ret += reg_w(sd, 0x2d, sd->gspca_dev.width / 4); reg_w(sd, 0x2d, sd->gspca_dev.width / 4);
} else } else
ret += reg_w(sd, 0x2c, sd->gspca_dev.width); reg_w(sd, 0x2c, sd->gspca_dev.width);
ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ reg_w(sd, 0x00, 0xbf17); /* reset everything */
ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ reg_w(sd, 0x00, 0xbf10); /* normal operation */
/* Transfer size in WORDS (for UYVY format only) */ /* Transfer size in WORDS (for UYVY format only) */
val = sd->gspca_dev.width * sd->gspca_dev.height; val = sd->gspca_dev.width * sd->gspca_dev.height;
ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ reg_w(sd, 0x3d, val & 0xffff); /* low bits */
ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ reg_w(sd, 0x3e, val >> 16); /* high bits */
if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
V4L2_PIX_FMT_JPEG) { V4L2_PIX_FMT_JPEG) {
...@@ -507,7 +473,7 @@ static int w9968cf_mode_init_regs(struct sd *sd) ...@@ -507,7 +473,7 @@ static int w9968cf_mode_init_regs(struct sd *sd)
jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
sd->gspca_dev.width, 0x22); /* JPEG 420 */ sd->gspca_dev.width, 0x22); /* JPEG 420 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality); jpeg_set_qual(sd->jpeg_hdr, sd->quality);
ret += w9968cf_upload_quantizationtables(sd); w9968cf_upload_quantizationtables(sd);
} }
/* Video Capture Control Register */ /* Video Capture Control Register */
...@@ -539,11 +505,9 @@ static int w9968cf_mode_init_regs(struct sd *sd) ...@@ -539,11 +505,9 @@ static int w9968cf_mode_init_regs(struct sd *sd)
val |= 0x8000; /* capt. enable */ val |= 0x8000; /* capt. enable */
ret += reg_w(sd, 0x16, val); reg_w(sd, 0x16, val);
sd->gspca_dev.empty_packet = 0; sd->gspca_dev.empty_packet = 0;
return ret;
} }
static void w9968cf_stop0(struct sd *sd) static void w9968cf_stop0(struct sd *sd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment