📄 ov511.c
字号:
}
PDEBUG(3, "%d", *val);
ov->colour = *val;
return 0;
}
/* -------------------------------------------------------------------------- */
/* Sets sensor's hue (red/blue balance) setting to "val" */
static int
sensor_set_hue(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:
case SEN_OV6630:
rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8));
if (rc < 0)
goto out;
rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8);
if (rc < 0)
goto out;
break;
case SEN_OV7620:
// Hue control is causing problems. I will enable it once it's fixed.
#if 0
rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb);
if (rc < 0)
goto out;
rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb);
if (rc < 0)
goto out;
#endif
break;
case SEN_SAA7111A:
rc = i2c_w(ov, 0x0d, (val + 32768) >> 8);
if (rc < 0)
goto out;
break;
default:
PDEBUG(3, "Unsupported with this sensor");
rc = -EPERM;
goto out;
}
rc = 0; /* Success */
ov->hue = val;
out:
if (ov51x_restart(ov) < 0)
return -EIO;
return rc;
}
/* Gets sensor's hue (red/blue balance) setting */
static int
sensor_get_hue(struct usb_ov511 *ov, unsigned short *val)
{
int rc;
switch (ov->sensor) {
case SEN_OV7610:
case SEN_OV6620:
case SEN_OV6630:
rc = i2c_r(ov, OV7610_REG_BLUE);
if (rc < 0)
return rc;
else
*val = rc << 8;
break;
case SEN_OV7620:
rc = i2c_r(ov, 0x7a);
if (rc < 0)
return rc;
else
*val = rc << 8;
break;
case SEN_SAA7111A:
*val = ov->hue;
break;
default:
PDEBUG(3, "Unsupported with this sensor");
return -EPERM;
}
PDEBUG(3, "%d", *val);
ov->hue = *val;
return 0;
}
/* -------------------------------------------------------------------------- */
static inline int
sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p)
{
int rc;
PDEBUG(4, "sensor_set_picture");
ov->whiteness = p->whiteness;
/* Don't return error if a setting is unsupported, or rest of settings
* will not be performed */
rc = sensor_set_contrast(ov, p->contrast);
if (FATAL_ERROR(rc))
return rc;
rc = sensor_set_brightness(ov, p->brightness);
if (FATAL_ERROR(rc))
return rc;
rc = sensor_set_saturation(ov, p->colour);
if (FATAL_ERROR(rc))
return rc;
rc = sensor_set_hue(ov, p->hue);
if (FATAL_ERROR(rc))
return rc;
return 0;
}
static inline int
sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
{
int rc;
PDEBUG(4, "sensor_get_picture");
/* Don't return error if a setting is unsupported, or rest of settings
* will not be performed */
rc = sensor_get_contrast(ov, &(p->contrast));
if (FATAL_ERROR(rc))
return rc;
rc = sensor_get_brightness(ov, &(p->brightness));
if (FATAL_ERROR(rc))
return rc;
rc = sensor_get_saturation(ov, &(p->colour));
if (FATAL_ERROR(rc))
return rc;
rc = sensor_get_hue(ov, &(p->hue));
if (FATAL_ERROR(rc))
return rc;
p->whiteness = 105 << 8;
return 0;
}
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
// FIXME: Exposure range is only 0x00-0x7f in interlace mode
/* Sets current exposure for sensor. This only has an effect if auto-exposure
* is off */
static inline int
sensor_set_exposure(struct usb_ov511 *ov, unsigned char val)
{
int rc;
PDEBUG(3, "%d", val);
if (ov->stop_during_set)
if (ov51x_stop(ov) < 0)
return -EIO;
switch (ov->sensor) {
case SEN_OV6620:
case SEN_OV6630:
case SEN_OV7610:
case SEN_OV7620:
case SEN_OV76BE:
case SEN_OV8600:
rc = i2c_w(ov, 0x10, val);
if (rc < 0)
goto out;
break;
case SEN_KS0127:
case SEN_KS0127B:
case SEN_SAA7111A:
PDEBUG(3, "Unsupported with this sensor");
return -EPERM;
default:
err("Sensor not supported for set_exposure");
return -EINVAL;
}
rc = 0; /* Success */
ov->exposure = val;
out:
if (ov51x_restart(ov) < 0)
return -EIO;
return rc;
}
/* Gets current exposure level from sensor, regardless of whether it is under
* manual control. */
static int
sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val)
{
int rc;
switch (ov->sensor) {
case SEN_OV7610:
case SEN_OV6620:
case SEN_OV6630:
case SEN_OV7620:
case SEN_OV76BE:
case SEN_OV8600:
rc = i2c_r(ov, 0x10);
if (rc < 0)
return rc;
else
*val = rc;
break;
case SEN_KS0127:
case SEN_KS0127B:
case SEN_SAA7111A:
val = 0;
PDEBUG(3, "Unsupported with this sensor");
return -EPERM;
default:
err("Sensor not supported for get_exposure");
return -EINVAL;
}
PDEBUG(3, "%d", *val);
ov->exposure = *val;
return 0;
}
#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */
static inline void
ov51x_led_control(struct usb_ov511 *ov, int enable)
{
PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
if (ov->bridge == BRG_OV511PLUS)
reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0);
else if (ov->bclass == BCL_OV518)
reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02);
return;
}
/* Matches the sensor's internal frame rate to the lighting frequency.
* Valid frequencies are:
* 50 - 50Hz, for European and Asian lighting
* 60 - 60Hz, for American lighting
*
* Tested with: OV7610, OV7620, OV76BE, OV6620
* Unsupported: KS0127, KS0127B, SAA7111A
* Returns: 0 for success
*/
static int
sensor_set_light_freq(struct usb_ov511 *ov, int freq)
{
int sixty;
PDEBUG(4, "%d Hz", freq);
if (freq == 60)
sixty = 1;
else if (freq == 50)
sixty = 0;
else {
err("Invalid light freq (%d Hz)", freq);
return -EINVAL;
}
switch (ov->sensor) {
case SEN_OV7610:
i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
i2c_w(ov, 0x2b, sixty?0x00:0xac);
i2c_w_mask(ov, 0x13, 0x10, 0x10);
i2c_w_mask(ov, 0x13, 0x00, 0x10);
break;
case SEN_OV7620:
case SEN_OV76BE:
case SEN_OV8600:
i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
i2c_w(ov, 0x2b, sixty?0x00:0xac);
i2c_w_mask(ov, 0x76, 0x01, 0x01);
break;
case SEN_OV6620:
case SEN_OV6630:
i2c_w(ov, 0x2b, sixty?0xa8:0x28);
i2c_w(ov, 0x2a, sixty?0x84:0xa4);
break;
case SEN_KS0127:
case SEN_KS0127B:
case SEN_SAA7111A:
PDEBUG(5, "Unsupported with this sensor");
return -EPERM;
default:
err("Sensor not supported for set_light_freq");
return -EINVAL;
}
ov->lightfreq = freq;
return 0;
}
/* If enable is true, turn on the sensor's banding filter, otherwise turn it
* off. This filter tries to reduce the pattern of horizontal light/dark bands
* caused by some (usually fluorescent) lighting. The light frequency must be
* set either before or after enabling it with ov51x_set_light_freq().
*
* Tested with: OV7610, OV7620, OV76BE, OV6620.
* Unsupported: KS0127, KS0127B, SAA7111A
* Returns: 0 for success
*/
static inline int
sensor_set_banding_filter(struct usb_ov511 *ov, int enable)
{
int rc;
PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
|| ov->sensor == SEN_SAA7111A) {
PDEBUG(5, "Unsupported with this sensor");
return -EPERM;
}
rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04);
if (rc < 0)
return rc;
ov->bandfilt = enable;
return 0;
}
/* If enable is true, turn on the sensor's auto brightness control, otherwise
* turn it off.
*
* Unsupported: KS0127, KS0127B, SAA7111A
* Returns: 0 for success
*/
static inline int
sensor_set_auto_brightness(struct usb_ov511 *ov, int enable)
{
int rc;
PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
|| ov->sensor == SEN_SAA7111A) {
PDEBUG(5, "Unsupported with this sensor");
return -EPERM;
}
rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10);
if (rc < 0)
return rc;
ov->auto_brt = enable;
return 0;
}
/* If enable is true, turn on the sensor's auto exposure control, otherwise
* turn it off.
*
* Unsupported: KS0127, KS0127B, SAA7111A
* Returns: 0 for success
*/
static inline int
sensor_set_auto_exposure(struct usb_ov511 *ov, int enable)
{
PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
switch (ov->sensor) {
case SEN_OV7610:
i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80);
break;
case SEN_OV6620:
case SEN_OV7620:
case SEN_OV76BE:
case SEN_OV8600:
i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01);
break;
case SEN_OV6630:
i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10);
break;
case SEN_KS0127:
case SEN_KS0127B:
case SEN_SAA7111A:
PDEBUG(5, "Unsupported with this sensor");
return -EPERM;
default:
err("Sensor not supported for set_auto_exposure");
return -EINVAL;
}
ov->auto_exp = enable;
return 0;
}
/* Modifies the sensor's exposure algorithm to allow proper exposure of objects
* that are illuminated from behind.
*
* Tested with: OV6620, OV7620
* Unsupported: OV7610, OV76BE, KS0127, KS0127B, SAA7111A
* Returns: 0 for success
*/
static int
sensor_set_backlight(struct usb_ov511 *ov, int enable)
{
PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
switch (ov->sensor) {
case SEN_OV7620:
case SEN_OV8600:
i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0);
i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
break;
case SEN_OV6620:
i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0);
i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80);
break;
case SEN_OV6630:
i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0);
i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
break;
case SEN_OV7610:
case SEN_OV76BE:
case SEN_KS0127:
case SEN_KS0127B:
case SEN_SAA7111A:
PDEBUG(5, "Unsupported with this sensor");
return -EPERM;
default:
err("Sensor not supported for set_backlight");
return -EINVAL;
}
ov->backlight = enable;
return 0;
}
static inline int
sensor_set_mirror(struct usb_ov511 *ov, int enable)
{
PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
switch (ov->sensor) {
case SEN_OV6620:
case SEN_OV6630:
case SEN_OV7610:
case SEN_OV7620:
case SEN_OV76BE:
case SEN_OV8600:
i2c_w_mask(ov, 0x12, enable?0x40:0x00, 0x40);
break;
case SEN_KS0127:
case SEN_KS0127B:
case SEN_SAA7111A:
PDEBUG(5, "Unsupported with this sensor");
return -EPERM;
default:
err("Sensor not supported for set_mirror");
return -EINVAL;
}
ov->mirror = enable;
return 0;
}
/* Returns number of bits per pixel (regardless of where they are located;
* planar or not), or zero for unsupported format.
*/
static inline int
get_depth(int palette)
{
switch (palette) {
case VIDEO_PALETTE_GREY: return 8;
case VIDEO_PALETTE_YUV420: return 12;
case VIDEO_PALETTE_YUV420P: return 12; /* Planar */
#ifdef OV511_ALLOW_CONVERSION
case VIDEO_PALETTE_RGB565: return 16;
case VIDEO_PALETTE_RGB24: return 24;
case VIDEO_PALETTE_YUV422: return 16;
case VIDEO_PALETTE_YUYV: return 16;
case VIDEO_PALETTE_YUV422P: return 16; /* Planar */
#endif
default: return 0; /* Invalid format */
}
}
/* Bytes per frame. Used by read(). R
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -