|
@@ -35,26 +35,23 @@ static int force_sensor = -1;
|
|
|
#define REG08_DEF 3 /* default JPEG compression (75%) */
|
|
|
#include "zc3xx-reg.h"
|
|
|
|
|
|
-/* controls */
|
|
|
-enum e_ctrl {
|
|
|
- BRIGHTNESS,
|
|
|
- CONTRAST,
|
|
|
- EXPOSURE,
|
|
|
- GAMMA,
|
|
|
- AUTOGAIN,
|
|
|
- LIGHTFREQ,
|
|
|
- SHARPNESS,
|
|
|
- QUALITY,
|
|
|
- NCTRLS /* number of controls */
|
|
|
-};
|
|
|
-
|
|
|
-#define AUTOGAIN_DEF 1
|
|
|
-
|
|
|
/* 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 { /* gamma/brightness/contrast control cluster */
|
|
|
+ struct v4l2_ctrl *gamma;
|
|
|
+ struct v4l2_ctrl *brightness;
|
|
|
+ struct v4l2_ctrl *contrast;
|
|
|
+ };
|
|
|
+ struct { /* autogain/exposure control cluster */
|
|
|
+ struct v4l2_ctrl *autogain;
|
|
|
+ struct v4l2_ctrl *exposure;
|
|
|
+ };
|
|
|
+ struct v4l2_ctrl *plfreq;
|
|
|
+ struct v4l2_ctrl *sharpness;
|
|
|
+ struct v4l2_ctrl *jpegqual;
|
|
|
|
|
|
struct work_struct work;
|
|
|
struct workqueue_struct *work_thread;
|
|
@@ -94,114 +91,6 @@ enum sensors {
|
|
|
SENSOR_MAX
|
|
|
};
|
|
|
|
|
|
-/* V4L2 controls supported by the driver */
|
|
|
-static void setcontrast(struct gspca_dev *gspca_dev);
|
|
|
-static void setexposure(struct gspca_dev *gspca_dev);
|
|
|
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
|
|
|
-static void setlightfreq(struct gspca_dev *gspca_dev);
|
|
|
-static void setsharpness(struct gspca_dev *gspca_dev);
|
|
|
-static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val);
|
|
|
-
|
|
|
-static const struct ctrl sd_ctrls[NCTRLS] = {
|
|
|
-[BRIGHTNESS] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_BRIGHTNESS,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Brightness",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 255,
|
|
|
- .step = 1,
|
|
|
- .default_value = 128,
|
|
|
- },
|
|
|
- .set_control = setcontrast
|
|
|
- },
|
|
|
-[CONTRAST] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_CONTRAST,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Contrast",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 255,
|
|
|
- .step = 1,
|
|
|
- .default_value = 128,
|
|
|
- },
|
|
|
- .set_control = setcontrast
|
|
|
- },
|
|
|
-[EXPOSURE] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_EXPOSURE,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Exposure",
|
|
|
- .minimum = 0x30d,
|
|
|
- .maximum = 0x493e,
|
|
|
- .step = 1,
|
|
|
- .default_value = 0x927
|
|
|
- },
|
|
|
- .set_control = setexposure
|
|
|
- },
|
|
|
-[GAMMA] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_GAMMA,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Gamma",
|
|
|
- .minimum = 1,
|
|
|
- .maximum = 6,
|
|
|
- .step = 1,
|
|
|
- .default_value = 4,
|
|
|
- },
|
|
|
- .set_control = setcontrast
|
|
|
- },
|
|
|
-[AUTOGAIN] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_AUTOGAIN,
|
|
|
- .type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
|
- .name = "Auto Gain",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 1,
|
|
|
- .step = 1,
|
|
|
- .default_value = AUTOGAIN_DEF,
|
|
|
- .flags = V4L2_CTRL_FLAG_UPDATE
|
|
|
- },
|
|
|
- .set = sd_setautogain
|
|
|
- },
|
|
|
-[LIGHTFREQ] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_POWER_LINE_FREQUENCY,
|
|
|
- .type = V4L2_CTRL_TYPE_MENU,
|
|
|
- .name = "Light frequency filter",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
|
|
|
- .step = 1,
|
|
|
- .default_value = 0,
|
|
|
- },
|
|
|
- .set_control = setlightfreq
|
|
|
- },
|
|
|
-[SHARPNESS] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_SHARPNESS,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Sharpness",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 3,
|
|
|
- .step = 1,
|
|
|
- .default_value = 2,
|
|
|
- },
|
|
|
- .set_control = setsharpness
|
|
|
- },
|
|
|
-[QUALITY] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_JPEG_COMPRESSION_QUALITY,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Compression Quality",
|
|
|
- .minimum = 50,
|
|
|
- .maximum = 87,
|
|
|
- .step = 1,
|
|
|
- .default_value = 75,
|
|
|
- },
|
|
|
- .set = sd_setquality
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
static const struct v4l2_pix_format vga_mode[] = {
|
|
|
{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
|
|
|
.bytesperline = 320,
|
|
@@ -5821,10 +5710,8 @@ static void setmatrix(struct gspca_dev *gspca_dev)
|
|
|
reg_w(gspca_dev, matrix[i], 0x010a + i);
|
|
|
}
|
|
|
|
|
|
-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;
|
|
|
- int sharpness;
|
|
|
static const u8 sharpness_tb[][2] = {
|
|
|
{0x02, 0x03},
|
|
|
{0x04, 0x07},
|
|
@@ -5832,19 +5719,18 @@ static void setsharpness(struct gspca_dev *gspca_dev)
|
|
|
{0x10, 0x1e}
|
|
|
};
|
|
|
|
|
|
- sharpness = sd->ctrls[SHARPNESS].val;
|
|
|
- reg_w(gspca_dev, sharpness_tb[sharpness][0], 0x01c6);
|
|
|
+ reg_w(gspca_dev, sharpness_tb[val][0], 0x01c6);
|
|
|
reg_r(gspca_dev, 0x01c8);
|
|
|
reg_r(gspca_dev, 0x01c9);
|
|
|
reg_r(gspca_dev, 0x01ca);
|
|
|
- reg_w(gspca_dev, sharpness_tb[sharpness][1], 0x01cb);
|
|
|
+ reg_w(gspca_dev, sharpness_tb[val][1], 0x01cb);
|
|
|
}
|
|
|
|
|
|
-static void setcontrast(struct gspca_dev *gspca_dev)
|
|
|
+static void setcontrast(struct gspca_dev *gspca_dev,
|
|
|
+ s32 gamma, s32 brightness, s32 contrast)
|
|
|
{
|
|
|
- struct sd *sd = (struct sd *) gspca_dev;
|
|
|
const u8 *Tgamma;
|
|
|
- int g, i, brightness, contrast, adj, gp1, gp2;
|
|
|
+ int g, i, adj, gp1, gp2;
|
|
|
u8 gr[16];
|
|
|
static const u8 delta_b[16] = /* delta for brightness */
|
|
|
{0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d,
|
|
@@ -5867,10 +5753,10 @@ static void setcontrast(struct gspca_dev *gspca_dev)
|
|
|
0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff},
|
|
|
};
|
|
|
|
|
|
- Tgamma = gamma_tb[sd->ctrls[GAMMA].val - 1];
|
|
|
+ Tgamma = gamma_tb[gamma - 1];
|
|
|
|
|
|
- contrast = ((int) sd->ctrls[CONTRAST].val - 128); /* -128 / 127 */
|
|
|
- brightness = ((int) sd->ctrls[BRIGHTNESS].val - 128); /* -128 / 92 */
|
|
|
+ contrast -= 128; /* -128 / 127 */
|
|
|
+ brightness -= 128; /* -128 / 92 */
|
|
|
adj = 0;
|
|
|
gp1 = gp2 = 0;
|
|
|
for (i = 0; i < 16; i++) {
|
|
@@ -5897,25 +5783,15 @@ static void setcontrast(struct gspca_dev *gspca_dev)
|
|
|
reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */
|
|
|
}
|
|
|
|
|
|
-static void getexposure(struct gspca_dev *gspca_dev)
|
|
|
+static s32 getexposure(struct gspca_dev *gspca_dev)
|
|
|
{
|
|
|
- struct sd *sd = (struct sd *) gspca_dev;
|
|
|
-
|
|
|
- if (sd->sensor != SENSOR_HV7131R)
|
|
|
- return;
|
|
|
- sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9)
|
|
|
+ return (i2c_read(gspca_dev, 0x25) << 9)
|
|
|
| (i2c_read(gspca_dev, 0x26) << 1)
|
|
|
| (i2c_read(gspca_dev, 0x27) >> 7);
|
|
|
}
|
|
|
|
|
|
-static void setexposure(struct gspca_dev *gspca_dev)
|
|
|
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
|
|
|
{
|
|
|
- struct sd *sd = (struct sd *) gspca_dev;
|
|
|
- int val;
|
|
|
-
|
|
|
- if (sd->sensor != SENSOR_HV7131R)
|
|
|
- return;
|
|
|
- val = sd->ctrls[EXPOSURE].val;
|
|
|
i2c_write(gspca_dev, 0x25, val >> 9, 0x00);
|
|
|
i2c_write(gspca_dev, 0x26, val >> 1, 0x00);
|
|
|
i2c_write(gspca_dev, 0x27, val << 7, 0x00);
|
|
@@ -5934,7 +5810,7 @@ static void setquality(struct gspca_dev *gspca_dev)
|
|
|
* 60Hz, for American lighting
|
|
|
* 0 = No Fliker (for outdoore usage)
|
|
|
*/
|
|
|
-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;
|
|
|
int i, mode;
|
|
@@ -6018,7 +5894,7 @@ static void setlightfreq(struct gspca_dev *gspca_dev)
|
|
|
tas5130c_60HZ, tas5130c_60HZScale},
|
|
|
};
|
|
|
|
|
|
- i = sd->ctrls[LIGHTFREQ].val * 2;
|
|
|
+ i = val * 2;
|
|
|
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
|
|
|
if (mode)
|
|
|
i++; /* 320x240 */
|
|
@@ -6028,14 +5904,14 @@ static void setlightfreq(struct gspca_dev *gspca_dev)
|
|
|
usb_exchange(gspca_dev, zc3_freq);
|
|
|
switch (sd->sensor) {
|
|
|
case SENSOR_GC0305:
|
|
|
- if (mode /* if 320x240 */
|
|
|
- && sd->ctrls[LIGHTFREQ].val == 1) /* and 50Hz */
|
|
|
+ if (mode /* if 320x240 */
|
|
|
+ && val == 1) /* and 50Hz */
|
|
|
reg_w(gspca_dev, 0x85, 0x018d);
|
|
|
/* win: 0x80, 0x018d */
|
|
|
break;
|
|
|
case SENSOR_OV7620:
|
|
|
- if (!mode) { /* if 640x480 */
|
|
|
- if (sd->ctrls[LIGHTFREQ].val != 0) /* and filter */
|
|
|
+ if (!mode) { /* if 640x480 */
|
|
|
+ if (val != 0) /* and filter */
|
|
|
reg_w(gspca_dev, 0x40, 0x0002);
|
|
|
else
|
|
|
reg_w(gspca_dev, 0x44, 0x0002);
|
|
@@ -6047,16 +5923,9 @@ static void setlightfreq(struct gspca_dev *gspca_dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-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;
|
|
|
- u8 autoval;
|
|
|
-
|
|
|
- if (sd->ctrls[AUTOGAIN].val)
|
|
|
- autoval = 0x42;
|
|
|
- else
|
|
|
- autoval = 0x02;
|
|
|
- reg_w(gspca_dev, autoval, 0x0180);
|
|
|
+ reg_w(gspca_dev, val ? 0x42 : 0x02, 0x0180);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -6450,7 +6319,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
|
|
/* define some sensors from the vendor/product */
|
|
|
sd->sensor = id->driver_info;
|
|
|
|
|
|
- gspca_dev->cam.ctrls = sd->ctrls;
|
|
|
sd->reg08 = REG08_DEF;
|
|
|
|
|
|
INIT_WORK(&sd->work, transfer_update);
|
|
@@ -6458,12 +6326,85 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* this function is called at probe and resume time */
|
|
|
-static int sd_init(struct gspca_dev *gspca_dev)
|
|
|
+static int zcxx_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
|
|
{
|
|
|
- struct sd *sd = (struct sd *) gspca_dev;
|
|
|
- struct cam *cam;
|
|
|
- int sensor;
|
|
|
+ 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->exposure && gspca_dev->streaming)
|
|
|
+ sd->exposure->val = getexposure(gspca_dev);
|
|
|
+ return gspca_dev->usb_err;
|
|
|
+ }
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+static int zcxx_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;
|
|
|
+ int i, qual;
|
|
|
+
|
|
|
+ gspca_dev->usb_err = 0;
|
|
|
+
|
|
|
+ if (ctrl->id == V4L2_CID_JPEG_COMPRESSION_QUALITY) {
|
|
|
+ qual = sd->reg08 >> 1;
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(jpeg_qual); i++) {
|
|
|
+ if (ctrl->val <= jpeg_qual[i])
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (i > 0 && i == qual && ctrl->val < jpeg_qual[i])
|
|
|
+ i--;
|
|
|
+
|
|
|
+ /* With high quality settings we need max bandwidth */
|
|
|
+ if (i >= 2 && gspca_dev->streaming &&
|
|
|
+ !gspca_dev->cam.needs_full_bandwidth)
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
+ sd->reg08 = (i << 1) | 1;
|
|
|
+ ctrl->val = jpeg_qual[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!gspca_dev->streaming)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ switch (ctrl->id) {
|
|
|
+ /* gamma/brightness/contrast cluster */
|
|
|
+ case V4L2_CID_GAMMA:
|
|
|
+ setcontrast(gspca_dev, sd->gamma->val,
|
|
|
+ sd->brightness->val, sd->contrast->val);
|
|
|
+ break;
|
|
|
+ /* autogain/exposure cluster */
|
|
|
+ case V4L2_CID_AUTOGAIN:
|
|
|
+ setautogain(gspca_dev, ctrl->val);
|
|
|
+ if (!gspca_dev->usb_err && !ctrl->val && sd->exposure)
|
|
|
+ setexposure(gspca_dev, sd->exposure->val);
|
|
|
+ break;
|
|
|
+ case V4L2_CID_POWER_LINE_FREQUENCY:
|
|
|
+ setlightfreq(gspca_dev, ctrl->val);
|
|
|
+ break;
|
|
|
+ case V4L2_CID_SHARPNESS:
|
|
|
+ setsharpness(gspca_dev, ctrl->val);
|
|
|
+ break;
|
|
|
+ case V4L2_CID_JPEG_COMPRESSION_QUALITY:
|
|
|
+ setquality(gspca_dev);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return gspca_dev->usb_err;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct v4l2_ctrl_ops zcxx_ctrl_ops = {
|
|
|
+ .g_volatile_ctrl = zcxx_g_volatile_ctrl,
|
|
|
+ .s_ctrl = zcxx_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;
|
|
|
static const u8 gamma[SENSOR_MAX] = {
|
|
|
[SENSOR_ADCM2700] = 4,
|
|
|
[SENSOR_CS2102] = 4,
|
|
@@ -6485,6 +6426,48 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
|
|
[SENSOR_PO2030] = 4,
|
|
|
[SENSOR_TAS5130C] = 3,
|
|
|
};
|
|
|
+
|
|
|
+ gspca_dev->vdev.ctrl_handler = hdl;
|
|
|
+ v4l2_ctrl_handler_init(hdl, 8);
|
|
|
+ sd->brightness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
|
|
|
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
|
|
|
+ sd->contrast = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
|
|
|
+ V4L2_CID_CONTRAST, 0, 255, 1, 128);
|
|
|
+ sd->gamma = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
|
|
|
+ V4L2_CID_GAMMA, 1, 6, 1, gamma[sd->sensor]);
|
|
|
+ if (sd->sensor == SENSOR_HV7131R)
|
|
|
+ sd->exposure = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
|
|
|
+ V4L2_CID_EXPOSURE, 0x30d, 0x493e, 1, 0x927);
|
|
|
+ sd->autogain = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
|
|
|
+ V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
|
|
|
+ if (sd->sensor != SENSOR_OV7630C)
|
|
|
+ sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &zcxx_ctrl_ops,
|
|
|
+ V4L2_CID_POWER_LINE_FREQUENCY,
|
|
|
+ V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
|
|
|
+ V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
|
|
|
+ sd->sharpness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
|
|
|
+ V4L2_CID_SHARPNESS, 0, 3, 1,
|
|
|
+ sd->sensor == SENSOR_PO2030 ? 0 : 2);
|
|
|
+ sd->jpegqual = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
|
|
|
+ V4L2_CID_JPEG_COMPRESSION_QUALITY,
|
|
|
+ jpeg_qual[0], jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1], 1,
|
|
|
+ jpeg_qual[REG08_DEF >> 1]);
|
|
|
+ if (hdl->error) {
|
|
|
+ pr_err("Could not initialize controls\n");
|
|
|
+ return hdl->error;
|
|
|
+ }
|
|
|
+ v4l2_ctrl_cluster(3, &sd->gamma);
|
|
|
+ if (sd->sensor == SENSOR_HV7131R)
|
|
|
+ v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* this function is called at probe and resume time */
|
|
|
+static int sd_init(struct gspca_dev *gspca_dev)
|
|
|
+{
|
|
|
+ struct sd *sd = (struct sd *) gspca_dev;
|
|
|
+ struct cam *cam;
|
|
|
+ int sensor;
|
|
|
static const u8 mode_tb[SENSOR_MAX] = {
|
|
|
[SENSOR_ADCM2700] = 2,
|
|
|
[SENSOR_CS2102] = 1,
|
|
@@ -6614,7 +6597,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
|
|
case 0x2030:
|
|
|
PDEBUG(D_PROBE, "Find Sensor PO2030");
|
|
|
sd->sensor = SENSOR_PO2030;
|
|
|
- sd->ctrls[SHARPNESS].def = 0; /* from win traces */
|
|
|
break;
|
|
|
case 0x7620:
|
|
|
PDEBUG(D_PROBE, "Find Sensor OV7620");
|
|
@@ -6656,26 +6638,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- sd->ctrls[GAMMA].def = gamma[sd->sensor];
|
|
|
- sd->ctrls[QUALITY].def = jpeg_qual[sd->reg08 >> 1];
|
|
|
- sd->ctrls[QUALITY].min = jpeg_qual[0];
|
|
|
- sd->ctrls[QUALITY].max = jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1];
|
|
|
-
|
|
|
- switch (sd->sensor) {
|
|
|
- case SENSOR_HV7131R:
|
|
|
- break;
|
|
|
- case SENSOR_OV7630C:
|
|
|
- gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE);
|
|
|
- break;
|
|
|
- default:
|
|
|
- gspca_dev->ctrl_dis = (1 << EXPOSURE);
|
|
|
- break;
|
|
|
- }
|
|
|
-#if AUTOGAIN_DEF
|
|
|
- if (sd->ctrls[AUTOGAIN].val)
|
|
|
- gspca_dev->ctrl_inac = (1 << EXPOSURE);
|
|
|
-#endif
|
|
|
-
|
|
|
/* switch off the led */
|
|
|
reg_w(gspca_dev, 0x01, 0x0000);
|
|
|
return gspca_dev->usb_err;
|
|
@@ -6792,7 +6754,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
|
|
reg_w(gspca_dev, 0x03, 0x0008);
|
|
|
break;
|
|
|
}
|
|
|
- setsharpness(gspca_dev);
|
|
|
+ setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
|
|
|
|
|
|
/* set the gamma tables when not set */
|
|
|
switch (sd->sensor) {
|
|
@@ -6801,7 +6763,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
|
|
case SENSOR_OV7630C:
|
|
|
break;
|
|
|
default:
|
|
|
- setcontrast(gspca_dev);
|
|
|
+ setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma),
|
|
|
+ v4l2_ctrl_g_ctrl(sd->brightness),
|
|
|
+ v4l2_ctrl_g_ctrl(sd->contrast));
|
|
|
break;
|
|
|
}
|
|
|
setmatrix(gspca_dev); /* one more time? */
|
|
@@ -6815,7 +6779,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
|
|
setquality(gspca_dev);
|
|
|
/* Start with BRC disabled, transfer_update will enable it if needed */
|
|
|
reg_w(gspca_dev, 0x00, 0x0007);
|
|
|
- setlightfreq(gspca_dev);
|
|
|
+ if (sd->plfreq)
|
|
|
+ setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq));
|
|
|
|
|
|
switch (sd->sensor) {
|
|
|
case SENSOR_ADCM2700:
|
|
@@ -6826,7 +6791,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
|
|
reg_w(gspca_dev, 0x40, 0x0117);
|
|
|
break;
|
|
|
case SENSOR_HV7131R:
|
|
|
- setexposure(gspca_dev);
|
|
|
+ setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
|
|
|
reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
|
|
|
break;
|
|
|
case SENSOR_GC0305:
|
|
@@ -6850,7 +6815,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- setautogain(gspca_dev);
|
|
|
+ setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
|
|
|
|
|
|
if (gspca_dev->usb_err < 0)
|
|
|
return gspca_dev->usb_err;
|
|
@@ -6911,79 +6876,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
|
|
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
|
|
|
}
|
|
|
|
|
|
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
|
|
|
-{
|
|
|
- struct sd *sd = (struct sd *) gspca_dev;
|
|
|
-
|
|
|
- sd->ctrls[AUTOGAIN].val = val;
|
|
|
- if (val) {
|
|
|
- gspca_dev->ctrl_inac |= (1 << EXPOSURE);
|
|
|
- } else {
|
|
|
- gspca_dev->ctrl_inac &= ~(1 << EXPOSURE);
|
|
|
- if (gspca_dev->streaming)
|
|
|
- getexposure(gspca_dev);
|
|
|
- }
|
|
|
- if (gspca_dev->streaming)
|
|
|
- setautogain(gspca_dev);
|
|
|
- return gspca_dev->usb_err;
|
|
|
-}
|
|
|
-
|
|
|
-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, "NoFliker");
|
|
|
- return 0;
|
|
|
- case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
|
|
|
- strcpy((char *) menu->name, "50 Hz");
|
|
|
- return 0;
|
|
|
- case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
|
|
|
- strcpy((char *) menu->name, "60 Hz");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- return -EINVAL;
|
|
|
-}
|
|
|
-
|
|
|
-static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val)
|
|
|
-{
|
|
|
- struct sd *sd = (struct sd *) gspca_dev;
|
|
|
- int i, qual = sd->reg08 >> 1;
|
|
|
-
|
|
|
- for (i = 0; i < ARRAY_SIZE(jpeg_qual); i++) {
|
|
|
- if (val <= jpeg_qual[i])
|
|
|
- break;
|
|
|
- }
|
|
|
- if (i > 0
|
|
|
- && i == qual
|
|
|
- && val < jpeg_qual[i])
|
|
|
- i--;
|
|
|
-
|
|
|
- /* With high quality settings we need max bandwidth */
|
|
|
- if (i >= 2 && gspca_dev->streaming &&
|
|
|
- !gspca_dev->cam.needs_full_bandwidth)
|
|
|
- return -EBUSY;
|
|
|
-
|
|
|
- sd->reg08 = (i << 1) | 1;
|
|
|
- sd->ctrls[QUALITY].val = jpeg_qual[i];
|
|
|
-
|
|
|
- if (gspca_dev->streaming)
|
|
|
- setquality(gspca_dev);
|
|
|
- return gspca_dev->usb_err;
|
|
|
-}
|
|
|
-
|
|
|
static int sd_set_jcomp(struct gspca_dev *gspca_dev,
|
|
|
struct v4l2_jpegcompression *jcomp)
|
|
|
{
|
|
|
struct sd *sd = (struct sd *) gspca_dev;
|
|
|
+ int ret;
|
|
|
|
|
|
- sd_setquality(gspca_dev, jcomp->quality);
|
|
|
- jcomp->quality = sd->ctrls[QUALITY].val;
|
|
|
- return gspca_dev->usb_err;
|
|
|
+ ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int sd_get_jcomp(struct gspca_dev *gspca_dev,
|
|
@@ -6992,7 +6895,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
|
|
|
struct sd *sd = (struct sd *) gspca_dev;
|
|
|
|
|
|
memset(jcomp, 0, sizeof *jcomp);
|
|
|
- jcomp->quality = sd->ctrls[QUALITY].val;
|
|
|
+ jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
|
|
|
jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
|
|
|
| V4L2_JPEG_MARKER_DQT;
|
|
|
return 0;
|
|
@@ -7016,15 +6919,13 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
|
|
|
|
|
|
static const struct sd_desc sd_desc = {
|
|
|
.name = KBUILD_MODNAME,
|
|
|
- .ctrls = sd_ctrls,
|
|
|
- .nctrls = ARRAY_SIZE(sd_ctrls),
|
|
|
.config = sd_config,
|
|
|
.init = sd_init,
|
|
|
+ .init_controls = sd_init_controls,
|
|
|
.isoc_init = sd_pre_start,
|
|
|
.start = sd_start,
|
|
|
.stop0 = sd_stop0,
|
|
|
.pkt_scan = sd_pkt_scan,
|
|
|
- .querymenu = sd_querymenu,
|
|
|
.get_jcomp = sd_get_jcomp,
|
|
|
.set_jcomp = sd_set_jcomp,
|
|
|
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
|
|
@@ -7108,6 +7009,7 @@ static struct usb_driver sd_driver = {
|
|
|
#ifdef CONFIG_PM
|
|
|
.suspend = gspca_suspend,
|
|
|
.resume = gspca_resume,
|
|
|
+ .reset_resume = gspca_resume,
|
|
|
#endif
|
|
|
};
|
|
|
|