[media] gspca_ov534: Convert to the control framework
Signed-off-by: Antonio Ospite <ospite@studenti.unina.it> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
463023b062
commit
1bd7d6adc6
@ -35,6 +35,7 @@
|
||||
#include "gspca.h"
|
||||
|
||||
#include <linux/fixp-arith.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
|
||||
#define OV534_REG_ADDRESS 0xf1 /* sensor address */
|
||||
#define OV534_REG_SUBADDR 0xf2
|
||||
@ -53,29 +54,28 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
|
||||
MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* controls */
|
||||
enum e_ctrl {
|
||||
HUE,
|
||||
SATURATION,
|
||||
BRIGHTNESS,
|
||||
CONTRAST,
|
||||
GAIN,
|
||||
EXPOSURE,
|
||||
AGC,
|
||||
AWB,
|
||||
AEC,
|
||||
SHARPNESS,
|
||||
HFLIP,
|
||||
VFLIP,
|
||||
LIGHTFREQ,
|
||||
NCTRLS /* number of controls */
|
||||
};
|
||||
|
||||
/* specific webcam descriptor */
|
||||
struct sd {
|
||||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||||
|
||||
struct gspca_ctrl ctrls[NCTRLS];
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
struct v4l2_ctrl *hue;
|
||||
struct v4l2_ctrl *saturation;
|
||||
struct v4l2_ctrl *brightness;
|
||||
struct v4l2_ctrl *contrast;
|
||||
struct { /* gain control cluster */
|
||||
struct v4l2_ctrl *autogain;
|
||||
struct v4l2_ctrl *gain;
|
||||
};
|
||||
struct v4l2_ctrl *autowhitebalance;
|
||||
struct { /* exposure control cluster */
|
||||
struct v4l2_ctrl *autoexposure;
|
||||
struct v4l2_ctrl *exposure;
|
||||
};
|
||||
struct v4l2_ctrl *sharpness;
|
||||
struct v4l2_ctrl *hflip;
|
||||
struct v4l2_ctrl *vflip;
|
||||
struct v4l2_ctrl *plfreq;
|
||||
|
||||
__u32 last_pts;
|
||||
u16 last_fid;
|
||||
@ -89,181 +89,9 @@ enum sensors {
|
||||
NSENSORS
|
||||
};
|
||||
|
||||
/* V4L2 controls supported by the driver */
|
||||
static void sethue(struct gspca_dev *gspca_dev);
|
||||
static void setsaturation(struct gspca_dev *gspca_dev);
|
||||
static void setbrightness(struct gspca_dev *gspca_dev);
|
||||
static void setcontrast(struct gspca_dev *gspca_dev);
|
||||
static void setgain(struct gspca_dev *gspca_dev);
|
||||
static void setexposure(struct gspca_dev *gspca_dev);
|
||||
static void setagc(struct gspca_dev *gspca_dev);
|
||||
static void setawb(struct gspca_dev *gspca_dev);
|
||||
static void setaec(struct gspca_dev *gspca_dev);
|
||||
static void setsharpness(struct gspca_dev *gspca_dev);
|
||||
static void sethvflip(struct gspca_dev *gspca_dev);
|
||||
static void setlightfreq(struct gspca_dev *gspca_dev);
|
||||
|
||||
static int sd_start(struct gspca_dev *gspca_dev);
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev);
|
||||
|
||||
static const struct ctrl sd_ctrls[] = {
|
||||
[HUE] = {
|
||||
{
|
||||
.id = V4L2_CID_HUE,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Hue",
|
||||
.minimum = -90,
|
||||
.maximum = 90,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
},
|
||||
.set_control = sethue
|
||||
},
|
||||
[SATURATION] = {
|
||||
{
|
||||
.id = V4L2_CID_SATURATION,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Saturation",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 64,
|
||||
},
|
||||
.set_control = setsaturation
|
||||
},
|
||||
[BRIGHTNESS] = {
|
||||
{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
},
|
||||
.set_control = setbrightness
|
||||
},
|
||||
[CONTRAST] = {
|
||||
{
|
||||
.id = V4L2_CID_CONTRAST,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Contrast",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 32,
|
||||
},
|
||||
.set_control = setcontrast
|
||||
},
|
||||
[GAIN] = {
|
||||
{
|
||||
.id = V4L2_CID_GAIN,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Main Gain",
|
||||
.minimum = 0,
|
||||
.maximum = 63,
|
||||
.step = 1,
|
||||
.default_value = 20,
|
||||
},
|
||||
.set_control = setgain
|
||||
},
|
||||
[EXPOSURE] = {
|
||||
{
|
||||
.id = V4L2_CID_EXPOSURE,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Exposure",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 120,
|
||||
},
|
||||
.set_control = setexposure
|
||||
},
|
||||
[AGC] = {
|
||||
{
|
||||
.id = V4L2_CID_AUTOGAIN,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "Auto Gain",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
},
|
||||
.set_control = setagc
|
||||
},
|
||||
[AWB] = {
|
||||
{
|
||||
.id = V4L2_CID_AUTO_WHITE_BALANCE,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "Auto White Balance",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
},
|
||||
.set_control = setawb
|
||||
},
|
||||
[AEC] = {
|
||||
{
|
||||
.id = V4L2_CID_EXPOSURE_AUTO,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "Auto Exposure",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
},
|
||||
.set_control = setaec
|
||||
},
|
||||
[SHARPNESS] = {
|
||||
{
|
||||
.id = V4L2_CID_SHARPNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Sharpness",
|
||||
.minimum = 0,
|
||||
.maximum = 63,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
},
|
||||
.set_control = setsharpness
|
||||
},
|
||||
[HFLIP] = {
|
||||
{
|
||||
.id = V4L2_CID_HFLIP,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "HFlip",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
},
|
||||
.set_control = sethvflip
|
||||
},
|
||||
[VFLIP] = {
|
||||
{
|
||||
.id = V4L2_CID_VFLIP,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "VFlip",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
},
|
||||
.set_control = sethvflip
|
||||
},
|
||||
[LIGHTFREQ] = {
|
||||
{
|
||||
.id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||||
.type = V4L2_CTRL_TYPE_MENU,
|
||||
.name = "Light Frequency Filter",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
},
|
||||
.set_control = setlightfreq
|
||||
},
|
||||
};
|
||||
|
||||
static const struct v4l2_pix_format ov772x_mode[] = {
|
||||
{320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
|
||||
@ -972,12 +800,10 @@ static void set_frame_rate(struct gspca_dev *gspca_dev)
|
||||
PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
|
||||
}
|
||||
|
||||
static void sethue(struct gspca_dev *gspca_dev)
|
||||
static void sethue(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int val;
|
||||
|
||||
val = sd->ctrls[HUE].val;
|
||||
if (sd->sensor == SENSOR_OV767x) {
|
||||
/* TBD */
|
||||
} else {
|
||||
@ -1014,12 +840,10 @@ static void sethue(struct gspca_dev *gspca_dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void setsaturation(struct gspca_dev *gspca_dev)
|
||||
static void setsaturation(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int val;
|
||||
|
||||
val = sd->ctrls[SATURATION].val;
|
||||
if (sd->sensor == SENSOR_OV767x) {
|
||||
int i;
|
||||
static u8 color_tb[][6] = {
|
||||
@ -1040,12 +864,10 @@ static void setsaturation(struct gspca_dev *gspca_dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void setbrightness(struct gspca_dev *gspca_dev)
|
||||
static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int val;
|
||||
|
||||
val = sd->ctrls[BRIGHTNESS].val;
|
||||
if (sd->sensor == SENSOR_OV767x) {
|
||||
if (val < 0)
|
||||
val = 0x80 - val;
|
||||
@ -1055,27 +877,18 @@ static void setbrightness(struct gspca_dev *gspca_dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void setcontrast(struct gspca_dev *gspca_dev)
|
||||
static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
u8 val;
|
||||
|
||||
val = sd->ctrls[CONTRAST].val;
|
||||
if (sd->sensor == SENSOR_OV767x)
|
||||
sccb_reg_write(gspca_dev, 0x56, val); /* contras */
|
||||
else
|
||||
sccb_reg_write(gspca_dev, 0x9c, val);
|
||||
}
|
||||
|
||||
static void setgain(struct gspca_dev *gspca_dev)
|
||||
static void setgain(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
u8 val;
|
||||
|
||||
if (sd->ctrls[AGC].val)
|
||||
return;
|
||||
|
||||
val = sd->ctrls[GAIN].val;
|
||||
switch (val & 0x30) {
|
||||
case 0x00:
|
||||
val &= 0x0f;
|
||||
@ -1097,15 +910,15 @@ static void setgain(struct gspca_dev *gspca_dev)
|
||||
sccb_reg_write(gspca_dev, 0x00, val);
|
||||
}
|
||||
|
||||
static void setexposure(struct gspca_dev *gspca_dev)
|
||||
static s32 getgain(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
return sccb_reg_read(gspca_dev, 0x00);
|
||||
}
|
||||
|
||||
static void setexposure(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
u8 val;
|
||||
|
||||
if (sd->ctrls[AEC].val)
|
||||
return;
|
||||
|
||||
val = sd->ctrls[EXPOSURE].val;
|
||||
if (sd->sensor == SENSOR_OV767x) {
|
||||
|
||||
/* set only aec[9:2] */
|
||||
@ -1123,11 +936,23 @@ static void setexposure(struct gspca_dev *gspca_dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void setagc(struct gspca_dev *gspca_dev)
|
||||
static s32 getexposure(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
if (sd->ctrls[AGC].val) {
|
||||
if (sd->sensor == SENSOR_OV767x) {
|
||||
/* get only aec[9:2] */
|
||||
return sccb_reg_read(gspca_dev, 0x10); /* aech */
|
||||
} else {
|
||||
u8 hi = sccb_reg_read(gspca_dev, 0x08);
|
||||
u8 lo = sccb_reg_read(gspca_dev, 0x10);
|
||||
return (hi << 8 | lo) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void setagc(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
if (val) {
|
||||
sccb_reg_write(gspca_dev, 0x13,
|
||||
sccb_reg_read(gspca_dev, 0x13) | 0x04);
|
||||
sccb_reg_write(gspca_dev, 0x64,
|
||||
@ -1137,16 +962,14 @@ static void setagc(struct gspca_dev *gspca_dev)
|
||||
sccb_reg_read(gspca_dev, 0x13) & ~0x04);
|
||||
sccb_reg_write(gspca_dev, 0x64,
|
||||
sccb_reg_read(gspca_dev, 0x64) & ~0x03);
|
||||
|
||||
setgain(gspca_dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void setawb(struct gspca_dev *gspca_dev)
|
||||
static void setawb(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
if (sd->ctrls[AWB].val) {
|
||||
if (val) {
|
||||
sccb_reg_write(gspca_dev, 0x13,
|
||||
sccb_reg_read(gspca_dev, 0x13) | 0x02);
|
||||
if (sd->sensor == SENSOR_OV772x)
|
||||
@ -1161,7 +984,7 @@ static void setawb(struct gspca_dev *gspca_dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void setaec(struct gspca_dev *gspca_dev)
|
||||
static void setaec(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
u8 data;
|
||||
@ -1169,31 +992,25 @@ static void setaec(struct gspca_dev *gspca_dev)
|
||||
data = sd->sensor == SENSOR_OV767x ?
|
||||
0x05 : /* agc + aec */
|
||||
0x01; /* agc */
|
||||
if (sd->ctrls[AEC].val)
|
||||
switch (val) {
|
||||
case V4L2_EXPOSURE_AUTO:
|
||||
sccb_reg_write(gspca_dev, 0x13,
|
||||
sccb_reg_read(gspca_dev, 0x13) | data);
|
||||
else {
|
||||
break;
|
||||
case V4L2_EXPOSURE_MANUAL:
|
||||
sccb_reg_write(gspca_dev, 0x13,
|
||||
sccb_reg_read(gspca_dev, 0x13) & ~data);
|
||||
if (sd->sensor == SENSOR_OV767x)
|
||||
sd->ctrls[EXPOSURE].val =
|
||||
sccb_reg_read(gspca_dev, 10); /* aech */
|
||||
else
|
||||
setexposure(gspca_dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void setsharpness(struct gspca_dev *gspca_dev)
|
||||
static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
u8 val;
|
||||
|
||||
val = sd->ctrls[SHARPNESS].val;
|
||||
sccb_reg_write(gspca_dev, 0x91, val); /* Auto de-noise threshold */
|
||||
sccb_reg_write(gspca_dev, 0x8e, val); /* De-noise threshold */
|
||||
}
|
||||
|
||||
static void sethvflip(struct gspca_dev *gspca_dev)
|
||||
static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
u8 val;
|
||||
@ -1201,28 +1018,27 @@ static void sethvflip(struct gspca_dev *gspca_dev)
|
||||
if (sd->sensor == SENSOR_OV767x) {
|
||||
val = sccb_reg_read(gspca_dev, 0x1e); /* mvfp */
|
||||
val &= ~0x30;
|
||||
if (sd->ctrls[HFLIP].val)
|
||||
if (hflip)
|
||||
val |= 0x20;
|
||||
if (sd->ctrls[VFLIP].val)
|
||||
if (vflip)
|
||||
val |= 0x10;
|
||||
sccb_reg_write(gspca_dev, 0x1e, val);
|
||||
} else {
|
||||
val = sccb_reg_read(gspca_dev, 0x0c);
|
||||
val &= ~0xc0;
|
||||
if (sd->ctrls[HFLIP].val == 0)
|
||||
if (hflip == 0)
|
||||
val |= 0x40;
|
||||
if (sd->ctrls[VFLIP].val == 0)
|
||||
if (vflip == 0)
|
||||
val |= 0x80;
|
||||
sccb_reg_write(gspca_dev, 0x0c, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void setlightfreq(struct gspca_dev *gspca_dev)
|
||||
static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
u8 val;
|
||||
|
||||
val = sd->ctrls[LIGHTFREQ].val ? 0x9e : 0x00;
|
||||
val = val ? 0x9e : 0x00;
|
||||
if (sd->sensor == SENSOR_OV767x) {
|
||||
sccb_reg_write(gspca_dev, 0x2a, 0x00);
|
||||
if (val)
|
||||
@ -1241,8 +1057,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||||
|
||||
cam = &gspca_dev->cam;
|
||||
|
||||
cam->ctrls = sd->ctrls;
|
||||
|
||||
cam->cam_mode = ov772x_mode;
|
||||
cam->nmodes = ARRAY_SIZE(ov772x_mode);
|
||||
|
||||
@ -1251,6 +1065,195 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov534_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
|
||||
struct gspca_dev *gspca_dev = &sd->gspca_dev;
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUTOGAIN:
|
||||
gspca_dev->usb_err = 0;
|
||||
if (ctrl->val && sd->gain && gspca_dev->streaming)
|
||||
sd->gain->val = getgain(gspca_dev);
|
||||
return gspca_dev->usb_err;
|
||||
|
||||
case V4L2_CID_EXPOSURE_AUTO:
|
||||
gspca_dev->usb_err = 0;
|
||||
if (ctrl->val == V4L2_EXPOSURE_AUTO && sd->exposure &&
|
||||
gspca_dev->streaming)
|
||||
sd->exposure->val = getexposure(gspca_dev);
|
||||
return gspca_dev->usb_err;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ov534_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
|
||||
struct gspca_dev *gspca_dev = &sd->gspca_dev;
|
||||
|
||||
gspca_dev->usb_err = 0;
|
||||
if (!gspca_dev->streaming)
|
||||
return 0;
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_HUE:
|
||||
sethue(gspca_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_SATURATION:
|
||||
setsaturation(gspca_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_BRIGHTNESS:
|
||||
setbrightness(gspca_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_CONTRAST:
|
||||
setcontrast(gspca_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_AUTOGAIN:
|
||||
/* case V4L2_CID_GAIN: */
|
||||
setagc(gspca_dev, ctrl->val);
|
||||
if (!gspca_dev->usb_err && !ctrl->val && sd->gain)
|
||||
setgain(gspca_dev, sd->gain->val);
|
||||
break;
|
||||
case V4L2_CID_AUTO_WHITE_BALANCE:
|
||||
setawb(gspca_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_EXPOSURE_AUTO:
|
||||
/* case V4L2_CID_EXPOSURE: */
|
||||
setaec(gspca_dev, ctrl->val);
|
||||
if (!gspca_dev->usb_err && ctrl->val == V4L2_EXPOSURE_MANUAL &&
|
||||
sd->exposure)
|
||||
setexposure(gspca_dev, sd->exposure->val);
|
||||
break;
|
||||
case V4L2_CID_SHARPNESS:
|
||||
setsharpness(gspca_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_HFLIP:
|
||||
sethvflip(gspca_dev, ctrl->val, sd->vflip->val);
|
||||
break;
|
||||
case V4L2_CID_VFLIP:
|
||||
sethvflip(gspca_dev, sd->hflip->val, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_POWER_LINE_FREQUENCY:
|
||||
setlightfreq(gspca_dev, ctrl->val);
|
||||
break;
|
||||
}
|
||||
return gspca_dev->usb_err;
|
||||
}
|
||||
|
||||
static const struct v4l2_ctrl_ops ov534_ctrl_ops = {
|
||||
.g_volatile_ctrl = ov534_g_volatile_ctrl,
|
||||
.s_ctrl = ov534_s_ctrl,
|
||||
};
|
||||
|
||||
static int sd_init_controls(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct v4l2_ctrl_handler *hdl = &sd->ctrl_handler;
|
||||
/* parameters with different values between the supported sensors */
|
||||
int saturation_min;
|
||||
int saturation_max;
|
||||
int saturation_def;
|
||||
int brightness_min;
|
||||
int brightness_max;
|
||||
int brightness_def;
|
||||
int contrast_max;
|
||||
int contrast_def;
|
||||
int exposure_min;
|
||||
int exposure_max;
|
||||
int exposure_def;
|
||||
int hflip_def;
|
||||
|
||||
if (sd->sensor == SENSOR_OV767x) {
|
||||
saturation_min = 0,
|
||||
saturation_max = 6,
|
||||
saturation_def = 3,
|
||||
brightness_min = -127;
|
||||
brightness_max = 127;
|
||||
brightness_def = 0;
|
||||
contrast_max = 0x80;
|
||||
contrast_def = 0x40;
|
||||
exposure_min = 0x08;
|
||||
exposure_max = 0x60;
|
||||
exposure_def = 0x13;
|
||||
hflip_def = 1;
|
||||
} else {
|
||||
saturation_min = 0,
|
||||
saturation_max = 255,
|
||||
saturation_def = 64,
|
||||
brightness_min = 0;
|
||||
brightness_max = 255;
|
||||
brightness_def = 0;
|
||||
contrast_max = 255;
|
||||
contrast_def = 32;
|
||||
exposure_min = 0;
|
||||
exposure_max = 255;
|
||||
exposure_def = 120;
|
||||
hflip_def = 0;
|
||||
}
|
||||
|
||||
gspca_dev->vdev.ctrl_handler = hdl;
|
||||
|
||||
v4l2_ctrl_handler_init(hdl, 13);
|
||||
|
||||
if (sd->sensor == SENSOR_OV772x)
|
||||
sd->hue = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_HUE, -90, 90, 1, 0);
|
||||
|
||||
sd->saturation = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_SATURATION, saturation_min, saturation_max, 1,
|
||||
saturation_def);
|
||||
sd->brightness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_BRIGHTNESS, brightness_min, brightness_max, 1,
|
||||
brightness_def);
|
||||
sd->contrast = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_CONTRAST, 0, contrast_max, 1, contrast_def);
|
||||
|
||||
if (sd->sensor == SENSOR_OV772x) {
|
||||
sd->autogain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
|
||||
sd->gain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_GAIN, 0, 63, 1, 20);
|
||||
}
|
||||
|
||||
sd->autoexposure = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_EXPOSURE_AUTO,
|
||||
V4L2_EXPOSURE_MANUAL, 0,
|
||||
V4L2_EXPOSURE_AUTO);
|
||||
sd->exposure = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_EXPOSURE, exposure_min, exposure_max, 1,
|
||||
exposure_def);
|
||||
|
||||
sd->autowhitebalance = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
|
||||
|
||||
if (sd->sensor == SENSOR_OV772x)
|
||||
sd->sharpness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_SHARPNESS, 0, 63, 1, 0);
|
||||
|
||||
sd->hflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_HFLIP, 0, 1, 1, hflip_def);
|
||||
sd->vflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_VFLIP, 0, 1, 1, 0);
|
||||
sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops,
|
||||
V4L2_CID_POWER_LINE_FREQUENCY,
|
||||
V4L2_CID_POWER_LINE_FREQUENCY_50HZ, 0,
|
||||
V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
|
||||
|
||||
if (hdl->error) {
|
||||
pr_err("Could not initialize controls\n");
|
||||
return hdl->error;
|
||||
}
|
||||
|
||||
if (sd->sensor == SENSOR_OV772x)
|
||||
v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true);
|
||||
|
||||
v4l2_ctrl_auto_cluster(2, &sd->autoexposure, V4L2_EXPOSURE_MANUAL,
|
||||
true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this function is called at probe and resume time */
|
||||
static int sd_init(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
@ -1286,24 +1289,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||||
|
||||
if ((sensor_id & 0xfff0) == 0x7670) {
|
||||
sd->sensor = SENSOR_OV767x;
|
||||
gspca_dev->ctrl_dis = (1 << HUE) |
|
||||
(1 << GAIN) |
|
||||
(1 << AGC) |
|
||||
(1 << SHARPNESS); /* auto */
|
||||
sd->ctrls[SATURATION].min = 0,
|
||||
sd->ctrls[SATURATION].max = 6,
|
||||
sd->ctrls[SATURATION].def = 3,
|
||||
sd->ctrls[BRIGHTNESS].min = -127;
|
||||
sd->ctrls[BRIGHTNESS].max = 127;
|
||||
sd->ctrls[BRIGHTNESS].def = 0;
|
||||
sd->ctrls[CONTRAST].max = 0x80;
|
||||
sd->ctrls[CONTRAST].def = 0x40;
|
||||
sd->ctrls[EXPOSURE].min = 0x08;
|
||||
sd->ctrls[EXPOSURE].max = 0x60;
|
||||
sd->ctrls[EXPOSURE].def = 0x13;
|
||||
sd->ctrls[SHARPNESS].max = 9;
|
||||
sd->ctrls[SHARPNESS].def = 4;
|
||||
sd->ctrls[HFLIP].def = 1;
|
||||
gspca_dev->cam.cam_mode = ov767x_mode;
|
||||
gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
|
||||
} else {
|
||||
@ -1366,22 +1351,23 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
||||
|
||||
set_frame_rate(gspca_dev);
|
||||
|
||||
if (!(gspca_dev->ctrl_dis & (1 << HUE)))
|
||||
sethue(gspca_dev);
|
||||
setsaturation(gspca_dev);
|
||||
if (!(gspca_dev->ctrl_dis & (1 << AGC)))
|
||||
setagc(gspca_dev);
|
||||
setawb(gspca_dev);
|
||||
setaec(gspca_dev);
|
||||
if (!(gspca_dev->ctrl_dis & (1 << GAIN)))
|
||||
setgain(gspca_dev);
|
||||
setexposure(gspca_dev);
|
||||
setbrightness(gspca_dev);
|
||||
setcontrast(gspca_dev);
|
||||
if (!(gspca_dev->ctrl_dis & (1 << SHARPNESS)))
|
||||
setsharpness(gspca_dev);
|
||||
sethvflip(gspca_dev);
|
||||
setlightfreq(gspca_dev);
|
||||
if (sd->hue)
|
||||
sethue(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue));
|
||||
setsaturation(gspca_dev, v4l2_ctrl_g_ctrl(sd->saturation));
|
||||
if (sd->autogain)
|
||||
setagc(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
|
||||
setawb(gspca_dev, v4l2_ctrl_g_ctrl(sd->autowhitebalance));
|
||||
setaec(gspca_dev, v4l2_ctrl_g_ctrl(sd->autoexposure));
|
||||
if (sd->gain)
|
||||
setgain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
|
||||
setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
|
||||
setbrightness(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness));
|
||||
setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
|
||||
if (sd->sharpness)
|
||||
setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
|
||||
sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
|
||||
v4l2_ctrl_g_ctrl(sd->vflip));
|
||||
setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq));
|
||||
|
||||
ov534_set_led(gspca_dev, 1);
|
||||
ov534_reg_write(gspca_dev, 0xe0, 0x00);
|
||||
@ -1483,25 +1469,6 @@ scan_next:
|
||||
} while (remaining_len > 0);
|
||||
}
|
||||
|
||||
static int sd_querymenu(struct gspca_dev *gspca_dev,
|
||||
struct v4l2_querymenu *menu)
|
||||
{
|
||||
switch (menu->id) {
|
||||
case V4L2_CID_POWER_LINE_FREQUENCY:
|
||||
switch (menu->index) {
|
||||
case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
|
||||
strcpy((char *) menu->name, "Disabled");
|
||||
return 0;
|
||||
case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
|
||||
strcpy((char *) menu->name, "50 Hz");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get stream parameters (framerate) */
|
||||
static void sd_get_streamparm(struct gspca_dev *gspca_dev,
|
||||
struct v4l2_streamparm *parm)
|
||||
@ -1536,14 +1503,12 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev,
|
||||
/* sub-driver description */
|
||||
static const struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
.ctrls = sd_ctrls,
|
||||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||||
.config = sd_config,
|
||||
.init = sd_init,
|
||||
.init_controls = sd_init_controls,
|
||||
.start = sd_start,
|
||||
.stopN = sd_stopN,
|
||||
.pkt_scan = sd_pkt_scan,
|
||||
.querymenu = sd_querymenu,
|
||||
.get_streamparm = sd_get_streamparm,
|
||||
.set_streamparm = sd_set_streamparm,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user