V4L/DVB: gspca - vc032x: Add more controls for poxxxx

The added controls are exposure, gain, autogain and backlight compensation.

Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Jean-François Moine 2010-07-26 07:53:57 -03:00 committed by Mauro Carvalho Chehab
parent 6e80cc51b4
commit 486cb2d5b0
1 changed files with 272 additions and 34 deletions

View File

@ -39,6 +39,10 @@ struct sd {
u8 vflip;
u8 lightfreq;
s8 sharpness;
u16 exposure;
u8 gain;
u8 autogain;
u8 backlight;
u8 image_offset;
@ -77,6 +81,14 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val);
static const struct ctrl sd_ctrls[] = {
#define BRIGHTNESS_IDX 0
@ -185,6 +197,66 @@ static const struct ctrl sd_ctrls[] = {
.set = sd_setsharpness,
.get = sd_getsharpness,
},
#define GAIN_IDX 7
{
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Gain",
.minimum = 0,
.maximum = 78,
.step = 1,
#define GAIN_DEF 0
.default_value = GAIN_DEF,
},
.set = sd_setgain,
.get = sd_getgain,
},
#define EXPOSURE_IDX 8
{
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Exposure",
#define EXPOSURE_DEF 450
.minimum = 0,
.maximum = 4095,
.step = 1,
.default_value = EXPOSURE_DEF,
},
.set = sd_setexposure,
.get = sd_getexposure,
},
#define AUTOGAIN_IDX 9
{
{
.id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Automatic Gain and Exposure",
.minimum = 0,
.maximum = 1,
.step = 1,
#define AUTOGAIN_DEF 1
.default_value = AUTOGAIN_DEF,
},
.set = sd_setautogain,
.get = sd_getautogain,
},
#define BACKLIGHT_IDX 10
{
{
.id = V4L2_CID_BACKLIGHT_COMPENSATION,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Backlight Compensation",
.minimum = 0,
.maximum = 15,
.step = 1,
#define BACKLIGHT_DEF 15
.default_value = BACKLIGHT_DEF,
},
.set = sd_setbacklight,
.get = sd_getbacklight,
},
};
/* table of the disabled controls */
@ -192,33 +264,51 @@ static u32 ctrl_dis[] = {
/* SENSOR_HV7131R 0 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
| (1 << SHARPNESS_IDX),
| (1 << SHARPNESS_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_MI0360 1 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
| (1 << SHARPNESS_IDX),
| (1 << SHARPNESS_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_MI1310_SOC 2 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_MI1320 3 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_MI1320_SOC 4 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_OV7660 5 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
| (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_OV7670 6 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << SHARPNESS_IDX),
| (1 << SHARPNESS_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_PO1200 7 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << LIGHTFREQ_IDX),
| (1 << LIGHTFREQ_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_PO3130NC 8 */
(1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
| (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
| (1 << SHARPNESS_IDX),
| (1 << SHARPNESS_IDX)
| (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
| (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
/* SENSOR_POxxxx 9 */
(1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX),
};
@ -2825,7 +2915,9 @@ static const u8 poxxxx_init_common[][4] = {
{0x00, 0x1e, 0xc6, 0xaa},
{0x00, 0x00, 0x40, 0xdd},
{0x00, 0x1d, 0x05, 0xaa},
{}
};
static const u8 poxxxx_gamma[][4] = {
{0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */
{0x00, 0x73, 0x00, 0xaa},
{0x00, 0x74, 0x0a, 0xaa},
@ -2867,19 +2959,9 @@ static const u8 poxxxx_init_common[][4] = {
{0x00, 0x7c, 0xba, 0xaa},
{0x00, 0x7d, 0xd4, 0xaa},
{0x00, 0x7e, 0xea, 0xaa},
{0x00, 0xaa, 0xff, 0xaa}, /* back light comp */
{0x00, 0xc4, 0x03, 0xaa},
{0x00, 0xc5, 0x19, 0xaa},
{0x00, 0xc6, 0x03, 0xaa},
{0x00, 0xc7, 0x91, 0xaa},
{0x00, 0xc8, 0x01, 0xaa},
{0x00, 0xc9, 0xdd, 0xaa},
{0x00, 0xca, 0x02, 0xaa},
{0x00, 0xcb, 0x37, 0xaa},
/* read d1 */
{0x00, 0xd1, 0x3c, 0xaa},
{}
};
static const u8 poxxxx_init_start_3[][4] = {
{0x00, 0xb8, 0x28, 0xaa},
{0x00, 0xb9, 0x1e, 0xaa},
{0x00, 0xb6, 0x14, 0xaa},
@ -2959,9 +3041,6 @@ static const u8 poxxxx_init_end_1[][4] = {
{0x00, 0xb3, 0x08, 0xaa},
{0x00, 0xb4, 0x0b, 0xaa},
{0x00, 0xb5, 0x0d, 0xaa},
{0x00, 0x59, 0x7e, 0xaa}, /* sharpness */
{0x00, 0x16, 0x00, 0xaa}, /* white balance */
{0x00, 0x18, 0x00, 0xaa},
{}
};
static const u8 poxxxx_init_end_2[][4] = {
@ -3409,6 +3488,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->vflip = VFLIP_DEF;
sd->lightfreq = FREQ_DEF;
sd->sharpness = SHARPNESS_DEF;
sd->gain = GAIN_DEF;
sd->exposure = EXPOSURE_DEF;
sd->autogain = AUTOGAIN_DEF;
sd->backlight = BACKLIGHT_DEF;
gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
@ -3551,6 +3634,82 @@ static void setsharpness(struct gspca_dev *gspca_dev)
break;
}
}
static void setgain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
if (gspca_dev->ctrl_dis & (1 << GAIN_IDX))
return;
i2c_write(gspca_dev, 0x15, &sd->gain, 1);
}
static void setexposure(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 data;
if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
return;
data = sd->exposure >> 8;
i2c_write(gspca_dev, 0x1a, &data, 1);
data = sd->exposure;
i2c_write(gspca_dev, 0x1b, &data, 1);
}
static void setautogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
static const u8 data[2] = {0x28, 0x3c};
if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
return;
i2c_write(gspca_dev, 0xd1, &data[sd->autogain], 1);
}
static void setgamma(struct gspca_dev *gspca_dev)
{
/*fixme:to do */
usb_exchange(gspca_dev, poxxxx_gamma);
}
static void setbacklight(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
u16 v;
u8 data;
data = (sd->backlight << 4) | 0x0f;
i2c_write(gspca_dev, 0xaa, &data, 1);
v = 613 + 12 * sd->backlight;
data = v >> 8;
i2c_write(gspca_dev, 0xc4, &data, 1);
data = v;
i2c_write(gspca_dev, 0xc5, &data, 1);
v = 1093 - 12 * sd->backlight;
data = v >> 8;
i2c_write(gspca_dev, 0xc6, &data, 1);
data = v;
i2c_write(gspca_dev, 0xc7, &data, 1);
v = 342 + 9 * sd->backlight;
data = v >> 8;
i2c_write(gspca_dev, 0xc8, &data, 1);
data = v;
i2c_write(gspca_dev, 0xc9, &data, 1);
v = 702 - 9 * sd->backlight;
data = v >> 8;
i2c_write(gspca_dev, 0xca, &data, 1);
data = v;
i2c_write(gspca_dev, 0xcb, &data, 1);
}
static void setwb(struct gspca_dev *gspca_dev)
{
/*fixme:to do - valid when reg d1 = 0x1c - (reg16 + reg15 = 0xa3)*/
static const u8 data[2] = {0x00, 0x00};
i2c_write(gspca_dev, 0x16, &data[0], 1);
i2c_write(gspca_dev, 0x18, &data[1], 1);
}
static int sd_start(struct gspca_dev *gspca_dev)
{
@ -3662,6 +3821,16 @@ static int sd_start(struct gspca_dev *gspca_dev)
default:
/* case SENSOR_POxxxx: */
usb_exchange(gspca_dev, poxxxx_init_common);
setgamma(gspca_dev);
setbacklight(gspca_dev);
setbrightness(gspca_dev);
setcontrast(gspca_dev);
setcolors(gspca_dev);
setsharpness(gspca_dev);
setautogain(gspca_dev);
setexposure(gspca_dev);
setgain(gspca_dev);
usb_exchange(gspca_dev, poxxxx_init_start_3);
if (mode)
init = poxxxx_initQVGA;
else
@ -3693,7 +3862,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
break;
}
msleep(100);
setsharpness(gspca_dev);
sethvflip(gspca_dev);
setlightfreq(gspca_dev);
}
@ -3704,14 +3872,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff);
break;
case SENSOR_POxxxx:
setcolors(gspca_dev);
setbrightness(gspca_dev);
setcontrast(gspca_dev);
/* led on */
msleep(80);
reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
usb_exchange(gspca_dev, poxxxx_init_end_2);
setwb(gspca_dev);
msleep(80); /* led on */
reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
break;
}
return gspca_dev->usb_err;
@ -3911,6 +4075,80 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->gain = val;
if (gspca_dev->streaming)
setgain(gspca_dev);
return gspca_dev->usb_err;
}
static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->gain;
return 0;
}
static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->exposure = val;
if (gspca_dev->streaming)
setexposure(gspca_dev);
return gspca_dev->usb_err;
}
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->exposure;
return 0;
}
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val;
if (gspca_dev->streaming)
setautogain(gspca_dev);
return gspca_dev->usb_err;
}
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->autogain;
return 0;
}
static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->backlight = val;
if (gspca_dev->streaming)
setbacklight(gspca_dev);
return gspca_dev->usb_err;
}
static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->backlight;
return 0;
}
static int sd_querymenu(struct gspca_dev *gspca_dev,
struct v4l2_querymenu *menu)
{