[media] gspca - sonixb: Use the new control mechanism

Acked-by: Hans de Goede <hdegoede@redhat.com>
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 2011-03-13 15:04:11 -03:00 коммит произвёл Mauro Carvalho Chehab
Родитель fa85bb6f9b
Коммит f51a8caafe
1 изменённых файлов: 93 добавлений и 193 удалений

Просмотреть файл

@ -56,9 +56,22 @@ MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver"); MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* controls */
enum e_ctrl {
BRIGHTNESS,
GAIN,
EXPOSURE,
AUTOGAIN,
FREQ,
NCTRLS /* number of controls */
};
/* specific webcam descriptor */ /* specific webcam descriptor */
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 gspca_ctrl ctrls[NCTRLS];
atomic_t avg_lum; atomic_t avg_lum;
int prev_avg_lum; int prev_avg_lum;
int exp_too_low_cnt; int exp_too_low_cnt;
@ -66,13 +79,8 @@ struct sd {
int header_read; int header_read;
u8 header[12]; /* Header without sof marker */ u8 header[12]; /* Header without sof marker */
unsigned short exposure;
unsigned char gain;
unsigned char brightness;
unsigned char autogain;
unsigned char autogain_ignore_frames; unsigned char autogain_ignore_frames;
unsigned char frames_to_drop; unsigned char frames_to_drop;
unsigned char freq; /* light freq filter setting */
__u8 bridge; /* Type of bridge */ __u8 bridge; /* Type of bridge */
#define BRIDGE_101 0 #define BRIDGE_101 0
@ -113,10 +121,9 @@ struct sensor_data {
#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
/* ctrl_dis helper macros */ /* ctrl_dis helper macros */
#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \ #define NO_EXPO ((1 << EXPOSURE) | (1 << AUTOGAIN))
(1 << AUTOGAIN_IDX)) #define NO_FREQ (1 << FREQ)
#define NO_FREQ (1 << FREQ_IDX) #define NO_BRIGHTNESS (1 << BRIGHTNESS)
#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
#define COMP 0xc7 /* 0x87 //0x07 */ #define COMP 0xc7 /* 0x87 //0x07 */
#define COMP1 0xc9 /* 0x89 //0x09 */ #define COMP1 0xc9 /* 0x89 //0x09 */
@ -141,20 +148,14 @@ struct sensor_data {
#define AUTOGAIN_IGNORE_FRAMES 1 #define AUTOGAIN_IGNORE_FRAMES 1
/* V4L2 controls supported by the driver */ /* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static void setbrightness(struct gspca_dev *gspca_dev);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); static void setgain(struct gspca_dev *gspca_dev);
static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); static void setexposure(struct gspca_dev *gspca_dev);
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_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static void setfreq(struct gspca_dev *gspca_dev);
static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
static const struct ctrl sd_ctrls[] = { static const struct ctrl sd_ctrls[NCTRLS] = {
#define BRIGHTNESS_IDX 0 [BRIGHTNESS] = {
{
{ {
.id = V4L2_CID_BRIGHTNESS, .id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER, .type = V4L2_CTRL_TYPE_INTEGER,
@ -162,14 +163,11 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0, .minimum = 0,
.maximum = 255, .maximum = 255,
.step = 1, .step = 1,
#define BRIGHTNESS_DEF 127 .default_value = 127,
.default_value = BRIGHTNESS_DEF,
}, },
.set = sd_setbrightness, .set_control = setbrightness
.get = sd_getbrightness,
}, },
#define GAIN_IDX 1 [GAIN] = {
{
{ {
.id = V4L2_CID_GAIN, .id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER, .type = V4L2_CTRL_TYPE_INTEGER,
@ -177,48 +175,31 @@ static const struct ctrl sd_ctrls[] = {
.minimum = 0, .minimum = 0,
.maximum = 255, .maximum = 255,
.step = 1, .step = 1,
#define GAIN_DEF 127
#define GAIN_KNEE 230 #define GAIN_KNEE 230
.default_value = GAIN_DEF, .default_value = 127,
}, },
.set = sd_setgain, .set_control = setgain
.get = sd_getgain,
}, },
#define EXPOSURE_IDX 2 [EXPOSURE] = {
{
{ {
.id = V4L2_CID_EXPOSURE, .id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER, .type = V4L2_CTRL_TYPE_INTEGER,
.name = "Exposure", .name = "Exposure",
#define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */
#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
.minimum = 0, .minimum = 0,
.maximum = 1023, .maximum = 1023,
.step = 1, .step = 1,
.default_value = EXPOSURE_DEF, .default_value = 66,
/* 33 ms / 30 fps (except on PASXXX) */
#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
.flags = 0, .flags = 0,
}, },
.set = sd_setexposure, .set_control = setexposure
.get = sd_getexposure,
}, },
#define COARSE_EXPOSURE_IDX 3 /* for coarse exposure */
{ #define COARSE_EXPOSURE_MIN 2
{ #define COARSE_EXPOSURE_MAX 15
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Exposure",
#define COARSE_EXPOSURE_DEF 2 /* 30 fps */ #define COARSE_EXPOSURE_DEF 2 /* 30 fps */
.minimum = 2, [AUTOGAIN] = {
.maximum = 15,
.step = 1,
.default_value = COARSE_EXPOSURE_DEF,
.flags = 0,
},
.set = sd_setexposure,
.get = sd_getexposure,
},
#define AUTOGAIN_IDX 4
{
{ {
.id = V4L2_CID_AUTOGAIN, .id = V4L2_CID_AUTOGAIN,
.type = V4L2_CTRL_TYPE_BOOLEAN, .type = V4L2_CTRL_TYPE_BOOLEAN,
@ -231,10 +212,8 @@ static const struct ctrl sd_ctrls[] = {
.flags = 0, .flags = 0,
}, },
.set = sd_setautogain, .set = sd_setautogain,
.get = sd_getautogain,
}, },
#define FREQ_IDX 5 [FREQ] = {
{
{ {
.id = V4L2_CID_POWER_LINE_FREQUENCY, .id = V4L2_CID_POWER_LINE_FREQUENCY,
.type = V4L2_CTRL_TYPE_MENU, .type = V4L2_CTRL_TYPE_MENU,
@ -245,8 +224,7 @@ static const struct ctrl sd_ctrls[] = {
#define FREQ_DEF 0 #define FREQ_DEF 0
.default_value = FREQ_DEF, .default_value = FREQ_DEF,
}, },
.set = sd_setfreq, .set_control = setfreq
.get = sd_getfreq,
}, },
}; };
@ -646,7 +624,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
/* change reg 0x06 */ /* change reg 0x06 */
i2cOV[1] = sensor_data[sd->sensor].sensor_addr; i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
i2cOV[3] = sd->brightness; i2cOV[3] = sd->ctrls[BRIGHTNESS].val;
if (i2c_w(gspca_dev, i2cOV) < 0) if (i2c_w(gspca_dev, i2cOV) < 0)
goto err; goto err;
break; break;
@ -664,13 +642,13 @@ static void setbrightness(struct gspca_dev *gspca_dev)
i2cpdoit[2] = 0x13; i2cpdoit[2] = 0x13;
} }
if (sd->brightness < 127) { if (sd->ctrls[BRIGHTNESS].val < 127) {
/* change reg 0x0b, signreg */ /* change reg 0x0b, signreg */
i2cpbright[3] = 0x01; i2cpbright[3] = 0x01;
/* set reg 0x0c, offset */ /* set reg 0x0c, offset */
i2cpbright[4] = 127 - sd->brightness; i2cpbright[4] = 127 - sd->ctrls[BRIGHTNESS].val;
} else } else
i2cpbright[4] = sd->brightness - 127; i2cpbright[4] = sd->ctrls[BRIGHTNESS].val - 127;
if (i2c_w(gspca_dev, i2cpbright) < 0) if (i2c_w(gspca_dev, i2cpbright) < 0)
goto err; goto err;
@ -687,16 +665,16 @@ err:
static void setsensorgain(struct gspca_dev *gspca_dev) static void setsensorgain(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
unsigned char gain = sd->gain; u8 gain = sd->ctrls[GAIN].val;
switch (sd->sensor) { switch (sd->sensor) {
case SENSOR_HV7131D: { case SENSOR_HV7131D: {
__u8 i2c[] = __u8 i2c[] =
{0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17}; {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
i2c[3] = 0x3f - (sd->gain / 4); i2c[3] = 0x3f - (gain / 4);
i2c[4] = 0x3f - (sd->gain / 4); i2c[4] = 0x3f - (gain / 4);
i2c[5] = 0x3f - (sd->gain / 4); i2c[5] = 0x3f - (gain / 4);
if (i2c_w(gspca_dev, i2c) < 0) if (i2c_w(gspca_dev, i2c) < 0)
goto err; goto err;
@ -759,11 +737,11 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
i2cpdoit[2] = 0x13; i2cpdoit[2] = 0x13;
} }
i2cpgain[3] = sd->gain >> 3; i2cpgain[3] = gain >> 3;
i2cpcolorgain[3] = sd->gain >> 4; i2cpcolorgain[3] = gain >> 4;
i2cpcolorgain[4] = sd->gain >> 4; i2cpcolorgain[4] = gain >> 4;
i2cpcolorgain[5] = sd->gain >> 4; i2cpcolorgain[5] = gain >> 4;
i2cpcolorgain[6] = sd->gain >> 4; i2cpcolorgain[6] = gain >> 4;
if (i2c_w(gspca_dev, i2cpgain) < 0) if (i2c_w(gspca_dev, i2cpgain) < 0)
goto err; goto err;
@ -792,13 +770,13 @@ static void setgain(struct gspca_dev *gspca_dev)
} }
if (sd->bridge == BRIDGE_103) { if (sd->bridge == BRIDGE_103) {
gain = sd->gain >> 1; gain = sd->ctrls[GAIN].val >> 1;
buf[0] = gain; /* Red */ buf[0] = gain; /* Red */
buf[1] = gain; /* Green */ buf[1] = gain; /* Green */
buf[2] = gain; /* Blue */ buf[2] = gain; /* Blue */
reg_w(gspca_dev, 0x05, buf, 3); reg_w(gspca_dev, 0x05, buf, 3);
} else { } else {
gain = sd->gain >> 4; gain = sd->ctrls[GAIN].val >> 4;
buf[0] = gain << 4 | gain; /* Red and blue */ buf[0] = gain << 4 | gain; /* Red and blue */
buf[1] = gain; /* Green */ buf[1] = gain; /* Green */
reg_w(gspca_dev, 0x10, buf, 2); reg_w(gspca_dev, 0x10, buf, 2);
@ -820,7 +798,8 @@ static void setexposure(struct gspca_dev *gspca_dev)
where the framerate starts dropping where the framerate starts dropping
2) At 6138 the framerate has already dropped to 2 fps, 2) At 6138 the framerate has already dropped to 2 fps,
going any lower makes little sense */ going any lower makes little sense */
__u16 reg = sd->exposure * 6; u16 reg = sd->ctrls[EXPOSURE].val * 6;
i2c[3] = reg >> 8; i2c[3] = reg >> 8;
i2c[4] = reg & 0xff; i2c[4] = reg & 0xff;
if (i2c_w(gspca_dev, i2c) != 0) if (i2c_w(gspca_dev, i2c) != 0)
@ -832,7 +811,8 @@ static void setexposure(struct gspca_dev *gspca_dev)
/* register 19's high nibble contains the sn9c10x clock divider /* register 19's high nibble contains the sn9c10x clock divider
The high nibble configures the no fps according to the The high nibble configures the no fps according to the
formula: 60 / high_nibble. With a maximum of 30 fps */ formula: 60 / high_nibble. With a maximum of 30 fps */
__u8 reg = sd->exposure; u8 reg = sd->ctrls[EXPOSURE].val;
reg = (reg << 4) | 0x0b; reg = (reg << 4) | 0x0b;
reg_w(gspca_dev, 0x19, &reg, 1); reg_w(gspca_dev, 0x19, &reg, 1);
break; break;
@ -868,7 +848,7 @@ static void setexposure(struct gspca_dev *gspca_dev)
} else } else
reg10_max = 0x41; reg10_max = 0x41;
reg11 = (15 * sd->exposure + 999) / 1000; reg11 = (15 * sd->ctrls[EXPOSURE].val + 999) / 1000;
if (reg11 < 1) if (reg11 < 1)
reg11 = 1; reg11 = 1;
else if (reg11 > 16) else if (reg11 > 16)
@ -881,14 +861,16 @@ static void setexposure(struct gspca_dev *gspca_dev)
reg11 = 4; reg11 = 4;
/* frame exposure time in ms = 1000 * reg11 / 30 -> /* frame exposure time in ms = 1000 * reg11 / 30 ->
reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */ reg10 = (sd->ctrls[EXPOSURE].val / 2) * reg10_max
reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11); / (1000 * reg11 / 30) */
reg10 = (sd->ctrls[EXPOSURE].val * 15 * reg10_max)
/ (1000 * reg11);
/* Don't allow this to get below 10 when using autogain, the /* Don't allow this to get below 10 when using autogain, the
steps become very large (relatively) when below 10 causing steps become very large (relatively) when below 10 causing
the image to oscilate from much too dark, to much too bright the image to oscilate from much too dark, to much too bright
and back again. */ and back again. */
if (sd->autogain && reg10 < 10) if (sd->ctrls[AUTOGAIN].val && reg10 < 10)
reg10 = 10; reg10 = 10;
else if (reg10 > reg10_max) else if (reg10 > reg10_max)
reg10 = reg10_max; reg10 = reg10_max;
@ -927,15 +909,16 @@ static void setexposure(struct gspca_dev *gspca_dev)
frame exposure times (like we are doing with the ov chips), frame exposure times (like we are doing with the ov chips),
as that sometimes leads to jumps in the exposure control, as that sometimes leads to jumps in the exposure control,
which are bad for auto exposure. */ which are bad for auto exposure. */
if (sd->exposure < 200) { if (sd->ctrls[EXPOSURE].val < 200) {
i2cpexpo[3] = 255 - (sd->exposure * 255) / 200; i2cpexpo[3] = 255 - (sd->ctrls[EXPOSURE].val * 255)
/ 200;
framerate_ctrl = 500; framerate_ctrl = 500;
} else { } else {
/* The PAS202's exposure control goes from 0 - 4095, /* The PAS202's exposure control goes from 0 - 4095,
but anything below 500 causes vsync issues, so scale but anything below 500 causes vsync issues, so scale
our 200-1023 to 500-4095 */ our 200-1023 to 500-4095 */
framerate_ctrl = (sd->exposure - 200) * 1000 / 229 + framerate_ctrl = (sd->ctrls[EXPOSURE].val - 200)
500; * 1000 / 229 + 500;
} }
i2cpframerate[3] = framerate_ctrl >> 6; i2cpframerate[3] = framerate_ctrl >> 6;
@ -959,15 +942,15 @@ static void setexposure(struct gspca_dev *gspca_dev)
/* For values below 150 use partial frame exposure, above /* For values below 150 use partial frame exposure, above
that use framerate ctrl */ that use framerate ctrl */
if (sd->exposure < 150) { if (sd->ctrls[EXPOSURE].val < 150) {
i2cpexpo[3] = 150 - sd->exposure; i2cpexpo[3] = 150 - sd->ctrls[EXPOSURE].val;
framerate_ctrl = 300; framerate_ctrl = 300;
} else { } else {
/* The PAS106's exposure control goes from 0 - 4095, /* The PAS106's exposure control goes from 0 - 4095,
but anything below 300 causes vsync issues, so scale but anything below 300 causes vsync issues, so scale
our 150-1023 to 300-4095 */ our 150-1023 to 300-4095 */
framerate_ctrl = (sd->exposure - 150) * 1000 / 230 + framerate_ctrl = (sd->ctrls[EXPOSURE].val - 150)
300; * 1000 / 230 + 300;
} }
i2cpframerate[3] = framerate_ctrl >> 4; i2cpframerate[3] = framerate_ctrl >> 4;
@ -998,7 +981,7 @@ static void setfreq(struct gspca_dev *gspca_dev)
0x2b register, see ov6630 datasheet. 0x2b register, see ov6630 datasheet.
0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */ 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
__u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}; __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
switch (sd->freq) { switch (sd->ctrls[FREQ].val) {
default: default:
/* case 0: * no filter*/ /* case 0: * no filter*/
/* case 2: * 60 hz */ /* case 2: * 60 hz */
@ -1017,7 +1000,7 @@ static void setfreq(struct gspca_dev *gspca_dev)
} }
} }
#include "coarse_expo_autogain.h" #include "autogain_functions.h"
static void do_autogain(struct gspca_dev *gspca_dev) static void do_autogain(struct gspca_dev *gspca_dev)
{ {
@ -1025,7 +1008,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int avg_lum = atomic_read(&sd->avg_lum); int avg_lum = atomic_read(&sd->avg_lum);
if (avg_lum == -1 || !sd->autogain) if (avg_lum == -1 || !sd->ctrls[AUTOGAIN].val)
return; return;
if (sd->autogain_ignore_frames > 0) { if (sd->autogain_ignore_frames > 0) {
@ -1045,17 +1028,20 @@ static void do_autogain(struct gspca_dev *gspca_dev)
} }
if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, result = coarse_grained_expo_autogain(gspca_dev, avg_lum,
sd->brightness * desired_avg_lum / 127, sd->ctrls[BRIGHTNESS].val
* desired_avg_lum / 127,
deadzone); deadzone);
else else
result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum, result = auto_gain_n_exposure(gspca_dev, avg_lum,
sd->brightness * desired_avg_lum / 127, sd->ctrls[BRIGHTNESS].val
* desired_avg_lum / 127,
deadzone, GAIN_KNEE, EXPOSURE_KNEE); deadzone, GAIN_KNEE, EXPOSURE_KNEE);
if (result) { if (result) {
PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d", PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
(int)sd->gain, (int)sd->exposure); (int) sd->ctrls[GAIN].val,
(int) sd->ctrls[EXPOSURE].val);
sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
} }
} }
@ -1074,9 +1060,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
/* copy the webcam info from the device id */ /* copy the webcam info from the device id */
sd->sensor = id->driver_info >> 8; sd->sensor = id->driver_info >> 8;
sd->bridge = id->driver_info & 0xff; sd->bridge = id->driver_info & 0xff;
gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis; gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
cam = &gspca_dev->cam; cam = &gspca_dev->cam;
cam->ctrls = sd->ctrls;
if (!(sensor_data[sd->sensor].flags & F_SIF)) { if (!(sensor_data[sd->sensor].flags & F_SIF)) {
cam->cam_mode = vga_mode; cam->cam_mode = vga_mode;
cam->nmodes = ARRAY_SIZE(vga_mode); cam->nmodes = ARRAY_SIZE(vga_mode);
@ -1086,20 +1074,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
} }
cam->npkt = 36; /* 36 packets per ISOC message */ cam->npkt = 36; /* 36 packets per ISOC message */
sd->brightness = BRIGHTNESS_DEF;
sd->gain = GAIN_DEF;
if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) { if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
sd->exposure = COARSE_EXPOSURE_DEF; sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN;
gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX); sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX;
} else { sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF;
sd->exposure = EXPOSURE_DEF;
gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX);
} }
if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
sd->autogain = 0; /* Disable do_autogain callback */
else
sd->autogain = AUTOGAIN_DEF;
sd->freq = FREQ_DEF;
return 0; return 0;
} }
@ -1398,65 +1377,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
} }
} }
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
if (gspca_dev->streaming)
setbrightness(gspca_dev);
return 0;
}
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->brightness;
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 0;
}
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 0;
}
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) static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
sd->autogain = val; sd->ctrls[AUTOGAIN].val = val;
sd->exp_too_high_cnt = 0; sd->exp_too_high_cnt = 0;
sd->exp_too_low_cnt = 0; sd->exp_too_low_cnt = 0;
@ -1464,9 +1389,10 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
we are on a valid point of the autogain gain / we are on a valid point of the autogain gain /
exposure knee graph, and give this change time to exposure knee graph, and give this change time to
take effect before doing autogain. */ take effect before doing autogain. */
if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) { if (sd->ctrls[AUTOGAIN].val
sd->exposure = EXPOSURE_DEF; && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
sd->gain = GAIN_DEF; sd->ctrls[EXPOSURE].val = sd->ctrls[EXPOSURE].def;
sd->ctrls[GAIN].val = sd->ctrls[GAIN].def;
if (gspca_dev->streaming) { if (gspca_dev->streaming) {
sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
setexposure(gspca_dev); setexposure(gspca_dev);
@ -1477,32 +1403,6 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
return 0; return 0;
} }
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_setfreq(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->freq = val;
if (gspca_dev->streaming)
setfreq(gspca_dev);
return 0;
}
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->freq;
return 0;
}
static int sd_querymenu(struct gspca_dev *gspca_dev, static int sd_querymenu(struct gspca_dev *gspca_dev,
struct v4l2_querymenu *menu) struct v4l2_querymenu *menu)
{ {