Commit 0cfe9de2 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] gspca-topro: convert to the control framework

Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 930806cb
...@@ -120,24 +120,13 @@ static const u8 jpeg_head[] = { ...@@ -120,24 +120,13 @@ static const u8 jpeg_head[] = {
#define JPEG_HDR_SZ 521 #define JPEG_HDR_SZ 521
}; };
enum e_ctrl {
EXPOSURE,
QUALITY,
SHARPNESS,
RGAIN,
GAIN,
BGAIN,
GAMMA,
AUTOGAIN,
NCTRLS /* number of controls */
};
#define AUTOGAIN_DEF 1
struct sd { struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */ struct gspca_dev gspca_dev; /* !! must be the first item */
struct v4l2_ctrl *jpegqual;
struct gspca_ctrl ctrls[NCTRLS]; struct v4l2_ctrl *sharpness;
struct v4l2_ctrl *gamma;
struct v4l2_ctrl *blue;
struct v4l2_ctrl *red;
u8 framerate; u8 framerate;
u8 quality; /* webcam current JPEG quality (0..16) */ u8 quality; /* webcam current JPEG quality (0..16) */
...@@ -1415,32 +1404,33 @@ static void soi763a_6810_init(struct gspca_dev *gspca_dev) ...@@ -1415,32 +1404,33 @@ static void soi763a_6810_init(struct gspca_dev *gspca_dev)
} }
/* set the gain and exposure */ /* set the gain and exposure */
static void setexposure(struct gspca_dev *gspca_dev) static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain,
s32 blue, s32 red)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
if (sd->sensor == SENSOR_CX0342) { if (sd->sensor == SENSOR_CX0342) {
int expo; expo = (expo << 2) - 1;
expo = (sd->ctrls[EXPOSURE].val << 2) - 1;
i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo); i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo);
i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8); i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8);
if (sd->bridge == BRIDGE_TP6800) if (sd->bridge == BRIDGE_TP6800)
i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H, i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H,
sd->ctrls[GAIN].val >> 8); gain >> 8);
i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, sd->ctrls[GAIN].val); i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, gain);
if (sd->bridge == BRIDGE_TP6800) if (sd->bridge == BRIDGE_TP6800)
i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H, i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H,
sd->ctrls[GAIN].val >> 8); gain >> 8);
i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, sd->ctrls[GAIN].val); i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, gain);
if (sd->bridge == BRIDGE_TP6800) if (sd->sensor == SENSOR_CX0342) {
i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, if (sd->bridge == BRIDGE_TP6800)
sd->ctrls[BGAIN].val >> 8); i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, sd->ctrls[BGAIN].val); blue >> 8);
if (sd->bridge == BRIDGE_TP6800) i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, blue);
i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, if (sd->bridge == BRIDGE_TP6800)
sd->ctrls[RGAIN].val >> 8); i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, sd->ctrls[RGAIN].val); red >> 8);
i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, red);
}
i2c_w(gspca_dev, CX0342_SYS_CTRL_0, i2c_w(gspca_dev, CX0342_SYS_CTRL_0,
sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81); sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81);
return; return;
...@@ -1448,10 +1438,10 @@ static void setexposure(struct gspca_dev *gspca_dev) ...@@ -1448,10 +1438,10 @@ static void setexposure(struct gspca_dev *gspca_dev)
/* soi763a */ /* soi763a */
i2c_w(gspca_dev, 0x10, /* AEC_H (exposure time) */ i2c_w(gspca_dev, 0x10, /* AEC_H (exposure time) */
sd->ctrls[EXPOSURE].val); expo);
/* i2c_w(gspca_dev, 0x76, 0x02); * AEC_L ([1:0] */ /* i2c_w(gspca_dev, 0x76, 0x02); * AEC_L ([1:0] */
i2c_w(gspca_dev, 0x00, /* gain */ i2c_w(gspca_dev, 0x00, /* gain */
sd->ctrls[GAIN].val); gain);
} }
/* set the JPEG quantization tables */ /* set the JPEG quantization tables */
...@@ -1472,12 +1462,10 @@ static void set_dqt(struct gspca_dev *gspca_dev, u8 q) ...@@ -1472,12 +1462,10 @@ static void set_dqt(struct gspca_dev *gspca_dev, u8 q)
} }
/* set the JPEG compression quality factor */ /* set the JPEG compression quality factor */
static void setquality(struct gspca_dev *gspca_dev) static void setquality(struct gspca_dev *gspca_dev, s32 q)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
u16 q;
q = sd->ctrls[QUALITY].val;
if (q != 16) if (q != 16)
q = 15 - q; q = 15 - q;
...@@ -1508,10 +1496,9 @@ static const u8 color_gain[NSENSORS][18] = { ...@@ -1508,10 +1496,9 @@ static const u8 color_gain[NSENSORS][18] = {
0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03}, /* V R/G/B */ 0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03}, /* V R/G/B */
}; };
static void setgamma(struct gspca_dev *gspca_dev) static void setgamma(struct gspca_dev *gspca_dev, s32 gamma)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int gamma;
#define NGAMMA 6 #define NGAMMA 6
static const u8 gamma_tb[NGAMMA][3][1024] = { static const u8 gamma_tb[NGAMMA][3][1024] = {
{ /* gamma 0 - from tp6800 + soi763a */ { /* gamma 0 - from tp6800 + soi763a */
...@@ -3836,7 +3823,6 @@ static void setgamma(struct gspca_dev *gspca_dev) ...@@ -3836,7 +3823,6 @@ static void setgamma(struct gspca_dev *gspca_dev)
if (sd->bridge == BRIDGE_TP6810) if (sd->bridge == BRIDGE_TP6810)
reg_w(gspca_dev, 0x02, 0x28); reg_w(gspca_dev, 0x02, 0x28);
/* msleep(50); */ /* msleep(50); */
gamma = sd->ctrls[GAMMA].val;
bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024); bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024);
bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024); bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024);
bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024); bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024);
...@@ -3864,43 +3850,35 @@ static void setgamma(struct gspca_dev *gspca_dev) ...@@ -3864,43 +3850,35 @@ static void setgamma(struct gspca_dev *gspca_dev)
/* msleep(50); */ /* msleep(50); */
} }
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; struct sd *sd = (struct sd *) gspca_dev;
u8 val;
if (sd->bridge == BRIDGE_TP6800) { if (sd->bridge == BRIDGE_TP6800) {
val = sd->ctrls[SHARPNESS].val val |= 0x08; /* grid compensation enable */
| 0x08; /* grid compensation enable */
if (gspca_dev->width == 640) if (gspca_dev->width == 640)
reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
else else
val |= 0x04; /* scaling down enable */ val |= 0x04; /* scaling down enable */
reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val); reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val);
} else { } else {
val = (sd->ctrls[SHARPNESS].val << 5) | 0x08; val = (val << 5) | 0x08;
reg_w(gspca_dev, 0x59, val); reg_w(gspca_dev, 0x59, val);
} }
} }
static void setautogain(struct gspca_dev *gspca_dev) static void setautogain(struct gspca_dev *gspca_dev, s32 val)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
if (gspca_dev->ctrl_dis & (1 << AUTOGAIN)) sd->ag_cnt = val ? AG_CNT_START : -1;
return;
if (sd->ctrls[AUTOGAIN].val) {
sd->ag_cnt = AG_CNT_START;
gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
} else {
sd->ag_cnt = -1;
gspca_dev->ctrl_inac &= ~((1 << EXPOSURE) | (1 << GAIN));
}
} }
/* set the resolution for sensor cx0342 */ /* set the resolution for sensor cx0342 */
static void set_resolution(struct gspca_dev *gspca_dev) static void set_resolution(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev;
reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00); reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
if (gspca_dev->width == 320) { if (gspca_dev->width == 320) {
reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06); reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
...@@ -3926,8 +3904,9 @@ static void set_resolution(struct gspca_dev *gspca_dev) ...@@ -3926,8 +3904,9 @@ static void set_resolution(struct gspca_dev *gspca_dev)
i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01); i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342], bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
ARRAY_SIZE(color_gain[0])); ARRAY_SIZE(color_gain[0]));
setgamma(gspca_dev); setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
setquality(gspca_dev); if (sd->sensor == SENSOR_SOI763A)
setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
} }
/* convert the frame rate to a tp68x0 value */ /* convert the frame rate to a tp68x0 value */
...@@ -3963,7 +3942,7 @@ static int get_fr_idx(struct gspca_dev *gspca_dev) ...@@ -3963,7 +3942,7 @@ static int get_fr_idx(struct gspca_dev *gspca_dev)
return i; return i;
} }
static void setframerate(struct gspca_dev *gspca_dev) static void setframerate(struct gspca_dev *gspca_dev, s32 val)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
u8 fr_idx; u8 fr_idx;
...@@ -3974,7 +3953,7 @@ static void setframerate(struct gspca_dev *gspca_dev) ...@@ -3974,7 +3953,7 @@ static void setframerate(struct gspca_dev *gspca_dev)
reg_r(gspca_dev, 0x7b); reg_r(gspca_dev, 0x7b);
reg_w(gspca_dev, 0x7b, reg_w(gspca_dev, 0x7b,
sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90); sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90);
if (sd->ctrls[EXPOSURE].val >= 128) if (val >= 128)
fr_idx = 0xf0; /* lower frame rate */ fr_idx = 0xf0; /* lower frame rate */
} }
...@@ -3984,43 +3963,43 @@ static void setframerate(struct gspca_dev *gspca_dev) ...@@ -3984,43 +3963,43 @@ static void setframerate(struct gspca_dev *gspca_dev)
i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01); i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
} }
static void setrgain(struct gspca_dev *gspca_dev) static void setrgain(struct gspca_dev *gspca_dev, s32 rgain)
{ {
struct sd *sd = (struct sd *) gspca_dev;
int rgain;
rgain = sd->ctrls[RGAIN].val;
i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8); i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8);
i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain); i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain);
i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80); i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
} }
static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) static int sd_setgain(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
s32 val = gspca_dev->gain->val;
if (sd->sensor == SENSOR_CX0342) { if (sd->sensor == SENSOR_CX0342) {
sd->ctrls[BGAIN].val = sd->ctrls[BGAIN].val s32 old = gspca_dev->gain->cur.val ?
* val / sd->ctrls[GAIN].val; gspca_dev->gain->cur.val : 1;
if (sd->ctrls[BGAIN].val > 4095)
sd->ctrls[BGAIN].val = 4095; sd->blue->val = sd->blue->val * val / old;
sd->ctrls[RGAIN].val = sd->ctrls[RGAIN].val if (sd->blue->val > 4095)
* val / sd->ctrls[GAIN].val; sd->blue->val = 4095;
if (sd->ctrls[RGAIN].val > 4095) sd->red->val = sd->red->val * val / old;
sd->ctrls[RGAIN].val = 4095; if (sd->red->val > 4095)
sd->red->val = 4095;
}
if (gspca_dev->streaming) {
if (sd->sensor == SENSOR_CX0342)
setexposure(gspca_dev, gspca_dev->exposure->val,
gspca_dev->gain->val,
sd->blue->val, sd->red->val);
else
setexposure(gspca_dev, gspca_dev->exposure->val,
gspca_dev->gain->val, 0, 0);
} }
sd->ctrls[GAIN].val = val;
if (gspca_dev->streaming)
setexposure(gspca_dev);
return gspca_dev->usb_err; return gspca_dev->usb_err;
} }
static void setbgain(struct gspca_dev *gspca_dev) static void setbgain(struct gspca_dev *gspca_dev, s32 bgain)
{ {
struct sd *sd = (struct sd *) gspca_dev;
int bgain;
bgain = sd->ctrls[BGAIN].val;
i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8); i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8);
i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain); i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain);
i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80); i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
...@@ -4040,7 +4019,6 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -4040,7 +4019,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
framerates : framerates_6810; framerates : framerates_6810;
sd->framerate = 30; /* default: 30 fps */ sd->framerate = 30; /* default: 30 fps */
gspca_dev->cam.ctrls = sd->ctrls;
return 0; return 0;
} }
...@@ -4108,32 +4086,16 @@ static int sd_init(struct gspca_dev *gspca_dev) ...@@ -4108,32 +4086,16 @@ static int sd_init(struct gspca_dev *gspca_dev)
} }
if (sd->sensor == SENSOR_SOI763A) { if (sd->sensor == SENSOR_SOI763A) {
pr_info("Sensor soi763a\n"); pr_info("Sensor soi763a\n");
sd->ctrls[GAMMA].def = sd->bridge == BRIDGE_TP6800 ? 0 : 1;
sd->ctrls[GAIN].max = 15;
sd->ctrls[GAIN].def = 3;
gspca_dev->ctrl_dis = (1 << RGAIN) | (1 << BGAIN);
if (sd->bridge == BRIDGE_TP6810) { if (sd->bridge == BRIDGE_TP6810) {
soi763a_6810_init(gspca_dev); soi763a_6810_init(gspca_dev);
#if AUTOGAIN_DEF
gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
#endif
} else {
gspca_dev->ctrl_dis |= (1 << AUTOGAIN);
} }
} else { } else {
pr_info("Sensor cx0342\n"); pr_info("Sensor cx0342\n");
if (sd->bridge == BRIDGE_TP6810) { if (sd->bridge == BRIDGE_TP6810) {
cx0342_6810_init(gspca_dev); cx0342_6810_init(gspca_dev);
#if AUTOGAIN_DEF
gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
#endif
} else {
gspca_dev->ctrl_dis |= (1 << AUTOGAIN);
} }
} }
if (sd->bridge == BRIDGE_TP6810)
sd->ctrls[QUALITY].def = 0; /* auto quality */
set_dqt(gspca_dev, 0); set_dqt(gspca_dev, 0);
return 0; return 0;
} }
...@@ -4207,8 +4169,9 @@ static void set_led(struct gspca_dev *gspca_dev, int on) ...@@ -4207,8 +4169,9 @@ static void set_led(struct gspca_dev *gspca_dev, int on)
static void cx0342_6800_start(struct gspca_dev *gspca_dev) static void cx0342_6800_start(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev;
static const struct cmd reg_init[] = { static const struct cmd reg_init[] = {
/*fixme: is this usefull?*/ /* fixme: is this useful? */
{TP6800_R17_GPIO_IO, 0x9f}, {TP6800_R17_GPIO_IO, 0x9f},
{TP6800_R16_GPIO_PD, 0x40}, {TP6800_R16_GPIO_PD, 0x40},
{TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */ {TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */
...@@ -4279,13 +4242,21 @@ static void cx0342_6800_start(struct gspca_dev *gspca_dev) ...@@ -4279,13 +4242,21 @@ static void cx0342_6800_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00); reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00); i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01); i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
setexposure(gspca_dev); if (sd->sensor == SENSOR_CX0342)
setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain),
v4l2_ctrl_g_ctrl(sd->blue),
v4l2_ctrl_g_ctrl(sd->red));
else
setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
set_led(gspca_dev, 1); set_led(gspca_dev, 1);
set_resolution(gspca_dev); set_resolution(gspca_dev);
} }
static void cx0342_6810_start(struct gspca_dev *gspca_dev) static void cx0342_6810_start(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev;
static const struct cmd sensor_init_2[] = { static const struct cmd sensor_init_2[] = {
{CX0342_EXPO_LINE_L, 0x6f}, {CX0342_EXPO_LINE_L, 0x6f},
{CX0342_EXPO_LINE_H, 0x02}, {CX0342_EXPO_LINE_H, 0x02},
...@@ -4366,10 +4337,10 @@ static void cx0342_6810_start(struct gspca_dev *gspca_dev) ...@@ -4366,10 +4337,10 @@ static void cx0342_6810_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x07, 0x85); reg_w(gspca_dev, 0x07, 0x85);
reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */
} }
setgamma(gspca_dev); setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
reg_w_buf(gspca_dev, tp6810_bridge_start, reg_w_buf(gspca_dev, tp6810_bridge_start,
ARRAY_SIZE(tp6810_bridge_start)); ARRAY_SIZE(tp6810_bridge_start));
setsharpness(gspca_dev); setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342], bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
ARRAY_SIZE(color_gain[0])); ARRAY_SIZE(color_gain[0]));
reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87); reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
...@@ -4380,11 +4351,12 @@ static void cx0342_6810_start(struct gspca_dev *gspca_dev) ...@@ -4380,11 +4351,12 @@ static void cx0342_6810_start(struct gspca_dev *gspca_dev)
i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5)); i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5));
set_led(gspca_dev, 1); set_led(gspca_dev, 1);
/* setquality(gspca_dev); */ /* setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual)); */
} }
static void soi763a_6800_start(struct gspca_dev *gspca_dev) static void soi763a_6800_start(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev;
static const struct cmd reg_init[] = { static const struct cmd reg_init[] = {
{TP6800_R79_QUALITY, 0x04}, {TP6800_R79_QUALITY, 0x04},
{TP6800_R79_QUALITY, 0x01}, {TP6800_R79_QUALITY, 0x01},
...@@ -4484,19 +4456,28 @@ static void soi763a_6800_start(struct gspca_dev *gspca_dev) ...@@ -4484,19 +4456,28 @@ static void soi763a_6800_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10); reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00); reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
setsharpness(gspca_dev); setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A], bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
ARRAY_SIZE(color_gain[0])); ARRAY_SIZE(color_gain[0]));
set_led(gspca_dev, 1); set_led(gspca_dev, 1);
setexposure(gspca_dev); if (sd->sensor == SENSOR_CX0342)
setquality(gspca_dev); setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
setgamma(gspca_dev); v4l2_ctrl_g_ctrl(gspca_dev->gain),
v4l2_ctrl_g_ctrl(sd->blue),
v4l2_ctrl_g_ctrl(sd->red));
else
setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
if (sd->sensor == SENSOR_SOI763A)
setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
} }
static void soi763a_6810_start(struct gspca_dev *gspca_dev) static void soi763a_6810_start(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev;
static const struct cmd bridge_init_2[] = { static const struct cmd bridge_init_2[] = {
{TP6800_R7A_BLK_THRLD, 0x00}, {TP6800_R7A_BLK_THRLD, 0x00},
{TP6800_R79_QUALITY, 0x04}, {TP6800_R79_QUALITY, 0x04},
...@@ -4520,7 +4501,14 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev) ...@@ -4520,7 +4501,14 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x22, gspca_dev->alt); reg_w(gspca_dev, 0x22, gspca_dev->alt);
bulk_w(gspca_dev, 0x03, color_null, sizeof color_null); bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
reg_w(gspca_dev, 0x59, 0x40); reg_w(gspca_dev, 0x59, 0x40);
setexposure(gspca_dev); if (sd->sensor == SENSOR_CX0342)
setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain),
v4l2_ctrl_g_ctrl(sd->blue),
v4l2_ctrl_g_ctrl(sd->red));
else
setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2)); reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
reg_w_buf(gspca_dev, tp6810_ov_init_common, reg_w_buf(gspca_dev, tp6810_ov_init_common,
ARRAY_SIZE(tp6810_ov_init_common)); ARRAY_SIZE(tp6810_ov_init_common));
...@@ -4534,7 +4522,7 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev) ...@@ -4534,7 +4522,7 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x07, 0x85); reg_w(gspca_dev, 0x07, 0x85);
reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */ reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */
} }
setgamma(gspca_dev); setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
reg_w_buf(gspca_dev, tp6810_bridge_start, reg_w_buf(gspca_dev, tp6810_bridge_start,
ARRAY_SIZE(tp6810_bridge_start)); ARRAY_SIZE(tp6810_bridge_start));
...@@ -4545,12 +4533,19 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev) ...@@ -4545,12 +4533,19 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x00, 0x00); reg_w(gspca_dev, 0x00, 0x00);
setsharpness(gspca_dev); setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A], bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
ARRAY_SIZE(color_gain[0])); ARRAY_SIZE(color_gain[0]));
set_led(gspca_dev, 1); set_led(gspca_dev, 1);
reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0); reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0);
setexposure(gspca_dev); if (sd->sensor == SENSOR_CX0342)
setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain),
v4l2_ctrl_g_ctrl(sd->blue),
v4l2_ctrl_g_ctrl(sd->red));
else
setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6)); reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6));
} }
...@@ -4576,12 +4571,25 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -4576,12 +4571,25 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x80, 0x03); reg_w(gspca_dev, 0x80, 0x03);
reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e); reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e);
setexposure(gspca_dev); if (sd->sensor == SENSOR_CX0342)
setquality(gspca_dev); setexposure(gspca_dev,
setautogain(gspca_dev); v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain),
v4l2_ctrl_g_ctrl(sd->blue),
v4l2_ctrl_g_ctrl(sd->red));
else
setexposure(gspca_dev,
v4l2_ctrl_g_ctrl(gspca_dev->exposure),
v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
if (sd->sensor == SENSOR_SOI763A)
setquality(gspca_dev,
v4l2_ctrl_g_ctrl(sd->jpegqual));
if (sd->bridge == BRIDGE_TP6810)
setautogain(gspca_dev,
v4l2_ctrl_g_ctrl(gspca_dev->autogain));
} }
setframerate(gspca_dev); setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
return gspca_dev->usb_err; return gspca_dev->usb_err;
} }
...@@ -4672,12 +4680,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ...@@ -4672,12 +4680,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
} }
} }
/* -- do autogain -- */
/* gain setting is done in setexposure() for tp6810 */
static void setgain(struct gspca_dev *gspca_dev) {}
#define WANT_REGULAR_AUTOGAIN
#include "autogain_functions.h"
static void sd_dq_callback(struct gspca_dev *gspca_dev) static void sd_dq_callback(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
...@@ -4739,17 +4741,19 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev) ...@@ -4739,17 +4741,19 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev)
luma /= 4; luma /= 4;
reg_w(gspca_dev, 0x7d, 0x00); reg_w(gspca_dev, 0x7d, 0x00);
expo = sd->ctrls[EXPOSURE].val; expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
ret = auto_gain_n_exposure(gspca_dev, luma, ret = gspca_expo_autogain(gspca_dev, luma,
60, /* desired luma */ 60, /* desired luma */
6, /* dead zone */ 6, /* dead zone */
2, /* gain knee */ 2, /* gain knee */
70); /* expo knee */ 70); /* expo knee */
sd->ag_cnt = AG_CNT_START; sd->ag_cnt = AG_CNT_START;
if (sd->bridge == BRIDGE_TP6810) { if (sd->bridge == BRIDGE_TP6810) {
if ((expo >= 128 && sd->ctrls[EXPOSURE].val < 128) int new_expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
|| (expo < 128 && sd->ctrls[EXPOSURE].val >= 128))
setframerate(gspca_dev); if ((expo >= 128 && new_expo < 128)
|| (expo < 128 && new_expo >= 128))
setframerate(gspca_dev, new_expo);
} }
break; break;
} }
...@@ -4789,7 +4793,7 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev, ...@@ -4789,7 +4793,7 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev,
sd->framerate = tpf->denominator / tpf->numerator; sd->framerate = tpf->denominator / tpf->numerator;
if (gspca_dev->streaming) if (gspca_dev->streaming)
setframerate(gspca_dev); setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
/* Return the actual framerate */ /* Return the actual framerate */
i = get_fr_idx(gspca_dev); i = get_fr_idx(gspca_dev);
...@@ -4806,12 +4810,10 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev, ...@@ -4806,12 +4810,10 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev,
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
if (sd->sensor == SENSOR_SOI763A) if (sd->sensor != SENSOR_SOI763A)
jpeg_set_qual(sd->jpeg_hdr, jcomp->quality); return -ENOTTY;
/* else v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
fixme: TODO return 0;
*/
return gspca_dev->usb_err;
} }
static int sd_get_jcomp(struct gspca_dev *gspca_dev, static int sd_get_jcomp(struct gspca_dev *gspca_dev,
...@@ -4819,118 +4821,109 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, ...@@ -4819,118 +4821,109 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
if (sd->sensor != SENSOR_SOI763A)
return -ENOTTY;
memset(jcomp, 0, sizeof *jcomp); memset(jcomp, 0, sizeof *jcomp);
jcomp->quality = jpeg_q[sd->quality]; jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
| V4L2_JPEG_MARKER_DQT; | V4L2_JPEG_MARKER_DQT;
return 0; return 0;
} }
static struct ctrl sd_ctrls[NCTRLS] = { static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
[EXPOSURE] = { {
{ struct gspca_dev *gspca_dev =
.id = V4L2_CID_EXPOSURE, container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
.type = V4L2_CTRL_TYPE_INTEGER, struct sd *sd = (struct sd *)gspca_dev;
.name = "Exposure",
.minimum = 0x01, gspca_dev->usb_err = 0;
.maximum = 0xdc,
.step = 1, if (!gspca_dev->streaming)
.default_value = 0x4e, return 0;
},
.set_control = setexposure switch (ctrl->id) {
}, case V4L2_CID_SHARPNESS:
[QUALITY] = { setsharpness(gspca_dev, ctrl->val);
{ break;
.id = V4L2_CID_PRIVATE_BASE, case V4L2_CID_GAMMA:
.type = V4L2_CTRL_TYPE_INTEGER, setgamma(gspca_dev, ctrl->val);
.name = "Compression quality", break;
.minimum = 0, case V4L2_CID_BLUE_BALANCE:
.maximum = 15, setbgain(gspca_dev, ctrl->val);
.step = 1, break;
.default_value = 13, case V4L2_CID_RED_BALANCE:
}, setrgain(gspca_dev, ctrl->val);
.set_control = setquality break;
}, case V4L2_CID_EXPOSURE:
[RGAIN] = { sd_setgain(gspca_dev);
{ break;
.id = V4L2_CID_RED_BALANCE, case V4L2_CID_AUTOGAIN:
.type = V4L2_CTRL_TYPE_INTEGER, if (ctrl->val)
.name = "Red balance", break;
.minimum = 0, sd_setgain(gspca_dev);
.maximum = 4095, break;
.step = 1, case V4L2_CID_JPEG_COMPRESSION_QUALITY:
.default_value = 256, jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
}, break;
.set_control = setrgain }
}, return gspca_dev->usb_err;
[GAIN] = { }
{
.id = V4L2_CID_GAIN, static const struct v4l2_ctrl_ops sd_ctrl_ops = {
.type = V4L2_CTRL_TYPE_INTEGER, .s_ctrl = sd_s_ctrl,
.name = "Gain",
.minimum = 0,
.maximum = 4095,
.step = 1,
.default_value = 256,
},
.set = sd_setgain
},
[BGAIN] = {
{
.id = V4L2_CID_BLUE_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Blue balance",
.minimum = 0,
.maximum = 4095,
.step = 1,
.default_value = 256,
},
.set_control = setbgain
},
[SHARPNESS] = {
{
.id = V4L2_CID_SHARPNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Sharpness",
.minimum = 0,
.maximum = 3,
.step = 1,
.default_value = 2,
},
.set_control = setsharpness
},
[GAMMA] = {
{
.id = V4L2_CID_GAMMA,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Gamma",
.minimum = 0,
.maximum = NGAMMA - 1,
.step = 1,
.default_value = 1,
},
.set_control = setgamma
},
[AUTOGAIN] = {
{
.id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Auto Gain",
.minimum = 0,
.maximum = 1,
.step = 1,
.default_value = AUTOGAIN_DEF
},
.set_control = setautogain
},
}; };
static int sd_init_controls(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *)gspca_dev;
struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
gspca_dev->vdev.ctrl_handler = hdl;
v4l2_ctrl_handler_init(hdl, 4);
gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_EXPOSURE, 1, 0xdc, 1, 0x4e);
if (sd->sensor == SENSOR_CX0342) {
sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_RED_BALANCE, 0, 4095, 1, 256);
sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_BLUE_BALANCE, 0, 4095, 1, 256);
}
if (sd->sensor == SENSOR_SOI763A)
gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_GAIN, 0, 15, 1, 3);
else
gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_GAIN, 0, 4095, 1, 256);
sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_SHARPNESS, 0, 3, 1, 2);
sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_GAMMA, 0, NGAMMA - 1, 1,
(sd->sensor == SENSOR_SOI763A &&
sd->bridge == BRIDGE_TP6800) ? 0 : 1);
if (sd->bridge == BRIDGE_TP6810)
gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
if (sd->sensor == SENSOR_SOI763A)
sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
V4L2_CID_JPEG_COMPRESSION_QUALITY,
0, 15, 1, (sd->bridge == BRIDGE_TP6810) ? 0 : 13);
if (hdl->error) {
pr_err("Could not initialize controls\n");
return hdl->error;
}
if (gspca_dev->autogain)
v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
else
v4l2_ctrl_cluster(2, &gspca_dev->exposure);
return 0;
}
static const struct sd_desc sd_desc = { static const struct sd_desc sd_desc = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.ctrls = sd_ctrls,
.nctrls = NCTRLS,
.config = sd_config, .config = sd_config,
.init = sd_init, .init = sd_init,
.init_controls = sd_init_controls,
.isoc_init = sd_isoc_init, .isoc_init = sd_isoc_init,
.start = sd_start, .start = sd_start,
.stopN = sd_stopN, .stopN = sd_stopN,
......
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