📄 ov511.c
字号:
ov51x_clear_snapshot(struct usb_ov511 *ov)
{
if (ov->bclass == BCL_OV511) {
reg_w(ov, R51x_SYS_SNAP, 0x00);
reg_w(ov, R51x_SYS_SNAP, 0x02);
reg_w(ov, R51x_SYS_SNAP, 0x00);
} else if (ov->bclass == BCL_OV518) {
warn("snapshot reset not supported yet on OV518(+)");
} else {
err("clear snap: invalid bridge type");
}
}
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
/* Checks the status of the snapshot button. Returns 1 if it was pressed since
* it was last cleared, and zero in all other cases (including errors) */
static int
ov51x_check_snapshot(struct usb_ov511 *ov)
{
int ret, status = 0;
if (ov->bclass == BCL_OV511) {
ret = reg_r(ov, R51x_SYS_SNAP);
if (ret < 0) {
err("Error checking snspshot status (%d)", ret);
} else if (ret & 0x08) {
status = 1;
}
} else if (ov->bclass == BCL_OV518) {
warn("snapshot check not supported yet on OV518(+)");
} else {
err("check snap: invalid bridge type");
}
return status;
}
#endif
/* This does an initial reset of an OmniVision sensor and ensures that I2C
* is synchronized. Returns <0 for failure.
*/
static int
init_ov_sensor(struct usb_ov511 *ov)
{
int i, success;
/* Reset the sensor */
if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
/* Wait for it to initialize */
schedule_timeout(1 + 150 * HZ / 1000);
for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
(i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
success = 1;
continue;
}
/* Reset the sensor */
if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
/* Wait for it to initialize */
schedule_timeout(1 + 150 * HZ / 1000);
/* Dummy read to sync I2C */
if (i2c_r(ov, 0x00) < 0) return -EIO;
}
if (!success)
return -EIO;
PDEBUG(1, "I2C synced in %d attempt(s)", i);
return 0;
}
static int
ov511_set_packet_size(struct usb_ov511 *ov, int size)
{
int alt, mult;
if (ov51x_stop(ov) < 0)
return -EIO;
mult = size >> 5;
if (ov->bridge == BRG_OV511) {
if (size == 0) alt = OV511_ALT_SIZE_0;
else if (size == 257) alt = OV511_ALT_SIZE_257;
else if (size == 513) alt = OV511_ALT_SIZE_513;
else if (size == 769) alt = OV511_ALT_SIZE_769;
else if (size == 993) alt = OV511_ALT_SIZE_993;
else {
err("Set packet size: invalid size (%d)", size);
return -EINVAL;
}
} else if (ov->bridge == BRG_OV511PLUS) {
if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
else if (size == 257) alt = OV511PLUS_ALT_SIZE_257;
else if (size == 385) alt = OV511PLUS_ALT_SIZE_385;
else if (size == 513) alt = OV511PLUS_ALT_SIZE_513;
else if (size == 769) alt = OV511PLUS_ALT_SIZE_769;
else if (size == 961) alt = OV511PLUS_ALT_SIZE_961;
else {
err("Set packet size: invalid size (%d)", size);
return -EINVAL;
}
} else {
err("Set packet size: Invalid bridge type");
return -EINVAL;
}
PDEBUG(3, "%d, mult=%d, alt=%d", size, mult, alt);
if (reg_w(ov, R51x_FIFO_PSIZE, mult) < 0)
return -EIO;
if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {
err("Set packet size: set interface error");
return -EBUSY;
}
if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
return -EIO;
ov->packet_size = size;
if (ov51x_restart(ov) < 0)
return -EIO;
return 0;
}
/* Note: Unlike the OV511/OV511+, the size argument does NOT include the
* optional packet number byte. The actual size *is* stored in ov->packet_size,
* though. */
static int
ov518_set_packet_size(struct usb_ov511 *ov, int size)
{
int alt;
if (ov51x_stop(ov) < 0)
return -EIO;
if (ov->bclass == BCL_OV518) {
if (size == 0) alt = OV518_ALT_SIZE_0;
else if (size == 128) alt = OV518_ALT_SIZE_128;
else if (size == 256) alt = OV518_ALT_SIZE_256;
else if (size == 384) alt = OV518_ALT_SIZE_384;
else if (size == 512) alt = OV518_ALT_SIZE_512;
else if (size == 640) alt = OV518_ALT_SIZE_640;
else if (size == 768) alt = OV518_ALT_SIZE_768;
else if (size == 896) alt = OV518_ALT_SIZE_896;
else {
err("Set packet size: invalid size (%d)", size);
return -EINVAL;
}
} else {
err("Set packet size: Invalid bridge type");
return -EINVAL;
}
PDEBUG(3, "%d, alt=%d", size, alt);
ov->packet_size = size;
if (size > 0) {
/* Program ISO FIFO size reg (packet number isn't included) */
ov518_reg_w32(ov, 0x30, size, 2);
if (ov->packet_numbering)
++ov->packet_size;
}
if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {
err("Set packet size: set interface error");
return -EBUSY;
}
/* Initialize the stream */
if (reg_w(ov, 0x2f, 0x80) < 0)
return -EIO;
if (ov51x_restart(ov) < 0)
return -EIO;
if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
return -EIO;
return 0;
}
/* Upload compression params and quantization tables. Returns 0 for success. */
static int
ov511_init_compression(struct usb_ov511 *ov)
{
int rc = 0;
if (!ov->compress_inited) {
reg_w(ov, 0x70, phy);
reg_w(ov, 0x71, phuv);
reg_w(ov, 0x72, pvy);
reg_w(ov, 0x73, pvuv);
reg_w(ov, 0x74, qhy);
reg_w(ov, 0x75, qhuv);
reg_w(ov, 0x76, qvy);
reg_w(ov, 0x77, qvuv);
if (ov511_upload_quan_tables(ov) < 0) {
err("Error uploading quantization tables");
rc = -EIO;
goto out;
}
}
ov->compress_inited = 1;
out:
return rc;
}
/* Upload compression params and quantization tables. Returns 0 for success. */
static int
ov518_init_compression(struct usb_ov511 *ov)
{
int rc = 0;
if (!ov->compress_inited) {
if (ov518_upload_quan_tables(ov) < 0) {
err("Error uploading quantization tables");
rc = -EIO;
goto out;
}
}
ov->compress_inited = 1;
out:
return rc;
}
/* -------------------------------------------------------------------------- */
/* Sets sensor's contrast setting to "val" */
static int
sensor_set_contrast(struct usb_ov511 *ov, unsigned short val)
{
int rc;
PDEBUG(3, "%d", val);
if (ov->stop_during_set)
if (ov51x_stop(ov) < 0)
return -EIO;
switch (ov->sensor) {
case SEN_OV7610:
case SEN_OV6620:
{
rc = i2c_w(ov, OV7610_REG_CNT, val >> 8);
if (rc < 0)
goto out;
break;
}
case SEN_OV6630:
{
rc = i2c_w_mask(ov, OV7610_REG_CNT, val >> 12, 0x0f);
if (rc < 0)
goto out;
break;
}
case SEN_OV7620:
{
unsigned char ctab[] = {
0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
};
/* Use Y gamma control instead. Bit 0 enables it. */
rc = i2c_w(ov, 0x64, ctab[val>>12]);
if (rc < 0)
goto out;
break;
}
case SEN_SAA7111A:
{
rc = i2c_w(ov, 0x0b, val >> 9);
if (rc < 0)
goto out;
break;
}
default:
{
PDEBUG(3, "Unsupported with this sensor");
rc = -EPERM;
goto out;
}
}
rc = 0; /* Success */
ov->contrast = val;
out:
if (ov51x_restart(ov) < 0)
return -EIO;
return rc;
}
/* Gets sensor's contrast setting */
static int
sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val)
{
int rc;
switch (ov->sensor) {
case SEN_OV7610:
case SEN_OV6620:
rc = i2c_r(ov, OV7610_REG_CNT);
if (rc < 0)
return rc;
else
*val = rc << 8;
break;
case SEN_OV6630:
rc = i2c_r(ov, OV7610_REG_CNT);
if (rc < 0)
return rc;
else
*val = rc << 12;
break;
case SEN_OV7620:
/* Use Y gamma reg instead. Bit 0 is the enable bit. */
rc = i2c_r(ov, 0x64);
if (rc < 0)
return rc;
else
*val = (rc & 0xfe) << 8;
break;
case SEN_SAA7111A:
*val = ov->contrast;
break;
default:
PDEBUG(3, "Unsupported with this sensor");
return -EPERM;
}
PDEBUG(3, "%d", *val);
ov->contrast = *val;
return 0;
}
/* -------------------------------------------------------------------------- */
/* Sets sensor's brightness setting to "val" */
static int
sensor_set_brightness(struct usb_ov511 *ov, unsigned short val)
{
int rc;
PDEBUG(4, "%d", val);
if (ov->stop_during_set)
if (ov51x_stop(ov) < 0)
return -EIO;
switch (ov->sensor) {
case SEN_OV7610:
case SEN_OV76BE:
case SEN_OV6620:
case SEN_OV6630:
rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
if (rc < 0)
goto out;
break;
case SEN_OV7620:
/* 7620 doesn't like manual changes when in auto mode */
if (!ov->auto_brt) {
rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
if (rc < 0)
goto out;
}
break;
case SEN_SAA7111A:
rc = i2c_w(ov, 0x0a, val >> 8);
if (rc < 0)
goto out;
break;
default:
PDEBUG(3, "Unsupported with this sensor");
rc = -EPERM;
goto out;
}
rc = 0; /* Success */
ov->brightness = val;
out:
if (ov51x_restart(ov) < 0)
return -EIO;
return rc;
}
/* Gets sensor's brightness setting */
static int
sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val)
{
int rc;
switch (ov->sensor) {
case SEN_OV7610:
case SEN_OV76BE:
case SEN_OV7620:
case SEN_OV6620:
case SEN_OV6630:
rc = i2c_r(ov, OV7610_REG_BRT);
if (rc < 0)
return rc;
else
*val = rc << 8;
break;
case SEN_SAA7111A:
*val = ov->brightness;
break;
default:
PDEBUG(3, "Unsupported with this sensor");
return -EPERM;
}
PDEBUG(3, "%d", *val);
ov->brightness = *val;
return 0;
}
/* -------------------------------------------------------------------------- */
/* Sets sensor's saturation (color intensity) setting to "val" */
static int
sensor_set_saturation(struct usb_ov511 *ov, unsigned short val)
{
int rc;
PDEBUG(3, "%d", val);
if (ov->stop_during_set)
if (ov51x_stop(ov) < 0)
return -EIO;
switch (ov->sensor) {
case SEN_OV7610:
case SEN_OV76BE:
case SEN_OV6620:
case SEN_OV6630:
rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
if (rc < 0)
goto out;
break;
case SEN_OV7620:
// /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
// rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e);
// if (rc < 0)
// goto out;
rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
if (rc < 0)
goto out;
break;
case SEN_SAA7111A:
rc = i2c_w(ov, 0x0c, val >> 9);
if (rc < 0)
goto out;
break;
default:
PDEBUG(3, "Unsupported with this sensor");
rc = -EPERM;
goto out;
}
rc = 0; /* Success */
ov->colour = val;
out:
if (ov51x_restart(ov) < 0)
return -EIO;
return rc;
}
/* Gets sensor's saturation (color intensity) setting */
static int
sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val)
{
int rc;
switch (ov->sensor) {
case SEN_OV7610:
case SEN_OV76BE:
case SEN_OV6620:
case SEN_OV6630:
rc = i2c_r(ov, OV7610_REG_SAT);
if (rc < 0)
return rc;
else
*val = rc << 8;
break;
case SEN_OV7620:
// /* Use UV gamma reg instead. Bits 0 & 7 are reserved. */
// rc = i2c_r(ov, 0x62);
// if (rc < 0)
// return rc;
// else
// *val = (rc & 0x7e) << 9;
rc = i2c_r(ov, OV7610_REG_SAT);
if (rc < 0)
return rc;
else
*val = rc << 8;
break;
case SEN_SAA7111A:
*val = ov->colour;
break;
default:
PDEBUG(3, "Unsupported with this sensor");
return -EPERM;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -