dect
/
linux-2.6
Archived
13
0
Fork 0

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

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2012-05-21 05:37:39 -03:00 committed by Mauro Carvalho Chehab
parent 930806cb92
commit 0cfe9de234
1 changed files with 226 additions and 233 deletions

View File

@ -120,24 +120,13 @@ static const u8 jpeg_head[] = {
#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 gspca_dev gspca_dev; /* !! must be the first item */
struct gspca_ctrl ctrls[NCTRLS];
struct v4l2_ctrl *jpegqual;
struct v4l2_ctrl *sharpness;
struct v4l2_ctrl *gamma;
struct v4l2_ctrl *blue;
struct v4l2_ctrl *red;
u8 framerate;
u8 quality; /* webcam current JPEG quality (0..16) */
@ -1415,32 +1404,33 @@ static void soi763a_6810_init(struct gspca_dev *gspca_dev)
}
/* 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;
if (sd->sensor == SENSOR_CX0342) {
int expo;
expo = (sd->ctrls[EXPOSURE].val << 2) - 1;
expo = (expo << 2) - 1;
i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo);
i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8);
if (sd->bridge == BRIDGE_TP6800)
i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H,
sd->ctrls[GAIN].val >> 8);
i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, sd->ctrls[GAIN].val);
gain >> 8);
i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, gain);
if (sd->bridge == BRIDGE_TP6800)
i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H,
sd->ctrls[GAIN].val >> 8);
i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, sd->ctrls[GAIN].val);
if (sd->bridge == BRIDGE_TP6800)
i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
sd->ctrls[BGAIN].val >> 8);
i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, sd->ctrls[BGAIN].val);
if (sd->bridge == BRIDGE_TP6800)
i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
sd->ctrls[RGAIN].val >> 8);
i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, sd->ctrls[RGAIN].val);
gain >> 8);
i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, gain);
if (sd->sensor == SENSOR_CX0342) {
if (sd->bridge == BRIDGE_TP6800)
i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
blue >> 8);
i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, blue);
if (sd->bridge == BRIDGE_TP6800)
i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
red >> 8);
i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, red);
}
i2c_w(gspca_dev, CX0342_SYS_CTRL_0,
sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81);
return;
@ -1448,10 +1438,10 @@ static void setexposure(struct gspca_dev *gspca_dev)
/* soi763a */
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, 0x00, /* gain */
sd->ctrls[GAIN].val);
gain);
}
/* set the JPEG quantization tables */
@ -1472,12 +1462,10 @@ static void set_dqt(struct gspca_dev *gspca_dev, u8 q)
}
/* 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;
u16 q;
q = sd->ctrls[QUALITY].val;
if (q != 16)
q = 15 - q;
@ -1508,10 +1496,9 @@ static const u8 color_gain[NSENSORS][18] = {
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;
int gamma;
#define NGAMMA 6
static const u8 gamma_tb[NGAMMA][3][1024] = {
{ /* gamma 0 - from tp6800 + soi763a */
@ -3836,7 +3823,6 @@ static void setgamma(struct gspca_dev *gspca_dev)
if (sd->bridge == BRIDGE_TP6810)
reg_w(gspca_dev, 0x02, 0x28);
/* msleep(50); */
gamma = sd->ctrls[GAMMA].val;
bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024);
bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024);
bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024);
@ -3864,43 +3850,35 @@ static void setgamma(struct gspca_dev *gspca_dev)
/* 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;
u8 val;
if (sd->bridge == BRIDGE_TP6800) {
val = sd->ctrls[SHARPNESS].val
| 0x08; /* grid compensation enable */
val |= 0x08; /* grid compensation enable */
if (gspca_dev->width == 640)
reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
else
val |= 0x04; /* scaling down enable */
reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val);
} else {
val = (sd->ctrls[SHARPNESS].val << 5) | 0x08;
val = (val << 5) | 0x08;
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;
if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
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));
}
sd->ag_cnt = val ? AG_CNT_START : -1;
}
/* set the resolution for sensor cx0342 */
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);
if (gspca_dev->width == 320) {
reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
@ -3926,8 +3904,9 @@ static void set_resolution(struct gspca_dev *gspca_dev)
i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
ARRAY_SIZE(color_gain[0]));
setgamma(gspca_dev);
setquality(gspca_dev);
setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
if (sd->sensor == SENSOR_SOI763A)
setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
}
/* convert the frame rate to a tp68x0 value */
@ -3963,7 +3942,7 @@ static int get_fr_idx(struct gspca_dev *gspca_dev)
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;
u8 fr_idx;
@ -3974,7 +3953,7 @@ static void setframerate(struct gspca_dev *gspca_dev)
reg_r(gspca_dev, 0x7b);
reg_w(gspca_dev, 0x7b,
sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90);
if (sd->ctrls[EXPOSURE].val >= 128)
if (val >= 128)
fr_idx = 0xf0; /* lower frame rate */
}
@ -3984,43 +3963,43 @@ static void setframerate(struct gspca_dev *gspca_dev)
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_L, rgain);
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;
s32 val = gspca_dev->gain->val;
if (sd->sensor == SENSOR_CX0342) {
sd->ctrls[BGAIN].val = sd->ctrls[BGAIN].val
* val / sd->ctrls[GAIN].val;
if (sd->ctrls[BGAIN].val > 4095)
sd->ctrls[BGAIN].val = 4095;
sd->ctrls[RGAIN].val = sd->ctrls[RGAIN].val
* val / sd->ctrls[GAIN].val;
if (sd->ctrls[RGAIN].val > 4095)
sd->ctrls[RGAIN].val = 4095;
s32 old = gspca_dev->gain->cur.val ?
gspca_dev->gain->cur.val : 1;
sd->blue->val = sd->blue->val * val / old;
if (sd->blue->val > 4095)
sd->blue->val = 4095;
sd->red->val = sd->red->val * val / old;
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;
}
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_L, bgain);
i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
@ -4040,7 +4019,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
framerates : framerates_6810;
sd->framerate = 30; /* default: 30 fps */
gspca_dev->cam.ctrls = sd->ctrls;
return 0;
}
@ -4108,32 +4086,16 @@ static int sd_init(struct gspca_dev *gspca_dev)
}
if (sd->sensor == SENSOR_SOI763A) {
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) {
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 {
pr_info("Sensor cx0342\n");
if (sd->bridge == BRIDGE_TP6810) {
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);
return 0;
}
@ -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)
{
struct sd *sd = (struct sd *) gspca_dev;
static const struct cmd reg_init[] = {
/*fixme: is this usefull?*/
/* fixme: is this useful? */
{TP6800_R17_GPIO_IO, 0x9f},
{TP6800_R16_GPIO_PD, 0x40},
{TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */
@ -4279,13 +4242,21 @@ static void cx0342_6800_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
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_resolution(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[] = {
{CX0342_EXPO_LINE_L, 0x6f},
{CX0342_EXPO_LINE_H, 0x02},
@ -4366,10 +4337,10 @@ static void cx0342_6810_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x07, 0x85);
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,
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],
ARRAY_SIZE(color_gain[0]));
reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
@ -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));
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)
{
struct sd *sd = (struct sd *) gspca_dev;
static const struct cmd reg_init[] = {
{TP6800_R79_QUALITY, 0x04},
{TP6800_R79_QUALITY, 0x01},
@ -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_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],
ARRAY_SIZE(color_gain[0]));
set_led(gspca_dev, 1);
setexposure(gspca_dev);
setquality(gspca_dev);
setgamma(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);
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)
{
struct sd *sd = (struct sd *) gspca_dev;
static const struct cmd bridge_init_2[] = {
{TP6800_R7A_BLK_THRLD, 0x00},
{TP6800_R79_QUALITY, 0x04},
@ -4520,7 +4501,14 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x22, gspca_dev->alt);
bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
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, tp6810_ov_init_common,
ARRAY_SIZE(tp6810_ov_init_common));
@ -4534,7 +4522,7 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x07, 0x85);
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,
ARRAY_SIZE(tp6810_bridge_start));
@ -4545,12 +4533,19 @@ static void soi763a_6810_start(struct gspca_dev *gspca_dev)
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],
ARRAY_SIZE(color_gain[0]));
set_led(gspca_dev, 1);
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));
}
@ -4576,12 +4571,25 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x80, 0x03);
reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e);
setexposure(gspca_dev);
setquality(gspca_dev);
setautogain(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);
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;
}
@ -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)
{
struct sd *sd = (struct sd *) gspca_dev;
@ -4739,17 +4741,19 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev)
luma /= 4;
reg_w(gspca_dev, 0x7d, 0x00);
expo = sd->ctrls[EXPOSURE].val;
ret = auto_gain_n_exposure(gspca_dev, luma,
expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
ret = gspca_expo_autogain(gspca_dev, luma,
60, /* desired luma */
6, /* dead zone */
2, /* gain knee */
70); /* expo knee */
sd->ag_cnt = AG_CNT_START;
if (sd->bridge == BRIDGE_TP6810) {
if ((expo >= 128 && sd->ctrls[EXPOSURE].val < 128)
|| (expo < 128 && sd->ctrls[EXPOSURE].val >= 128))
setframerate(gspca_dev);
int new_expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
if ((expo >= 128 && new_expo < 128)
|| (expo < 128 && new_expo >= 128))
setframerate(gspca_dev, new_expo);
}
break;
}
@ -4789,7 +4793,7 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev,
sd->framerate = tpf->denominator / tpf->numerator;
if (gspca_dev->streaming)
setframerate(gspca_dev);
setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
/* Return the actual framerate */
i = get_fr_idx(gspca_dev);
@ -4806,12 +4810,10 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev,
{
struct sd *sd = (struct sd *) gspca_dev;
if (sd->sensor == SENSOR_SOI763A)
jpeg_set_qual(sd->jpeg_hdr, jcomp->quality);
/* else
fixme: TODO
*/
return gspca_dev->usb_err;
if (sd->sensor != SENSOR_SOI763A)
return -ENOTTY;
v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
return 0;
}
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;
if (sd->sensor != SENSOR_SOI763A)
return -ENOTTY;
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
| V4L2_JPEG_MARKER_DQT;
return 0;
}
static struct ctrl sd_ctrls[NCTRLS] = {
[EXPOSURE] = {
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Exposure",
.minimum = 0x01,
.maximum = 0xdc,
.step = 1,
.default_value = 0x4e,
},
.set_control = setexposure
},
[QUALITY] = {
{
.id = V4L2_CID_PRIVATE_BASE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Compression quality",
.minimum = 0,
.maximum = 15,
.step = 1,
.default_value = 13,
},
.set_control = setquality
},
[RGAIN] = {
{
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Red balance",
.minimum = 0,
.maximum = 4095,
.step = 1,
.default_value = 256,
},
.set_control = setrgain
},
[GAIN] = {
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.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_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct gspca_dev *gspca_dev =
container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
struct sd *sd = (struct sd *)gspca_dev;
gspca_dev->usb_err = 0;
if (!gspca_dev->streaming)
return 0;
switch (ctrl->id) {
case V4L2_CID_SHARPNESS:
setsharpness(gspca_dev, ctrl->val);
break;
case V4L2_CID_GAMMA:
setgamma(gspca_dev, ctrl->val);
break;
case V4L2_CID_BLUE_BALANCE:
setbgain(gspca_dev, ctrl->val);
break;
case V4L2_CID_RED_BALANCE:
setrgain(gspca_dev, ctrl->val);
break;
case V4L2_CID_EXPOSURE:
sd_setgain(gspca_dev);
break;
case V4L2_CID_AUTOGAIN:
if (ctrl->val)
break;
sd_setgain(gspca_dev);
break;
case V4L2_CID_JPEG_COMPRESSION_QUALITY:
jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
break;
}
return gspca_dev->usb_err;
}
static const struct v4l2_ctrl_ops sd_ctrl_ops = {
.s_ctrl = sd_s_ctrl,
};
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 = {
.name = KBUILD_MODNAME,
.ctrls = sd_ctrls,
.nctrls = NCTRLS,
.config = sd_config,
.init = sd_init,
.init_controls = sd_init_controls,
.isoc_init = sd_isoc_init,
.start = sd_start,
.stopN = sd_stopN,