diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-05-14 04:54:13 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-07-30 18:21:35 -0300 |
commit | 1bfea3e49d2edd8ea102d04be25ae62d6fc016c0 (patch) | |
tree | df60449ad894454c5bb3b621829479e1658f35c6 /drivers/media/video/gspca | |
parent | cbc1c94cc573d8e355447191ba88ede99d12594f (diff) | |
download | linux-3.10-1bfea3e49d2edd8ea102d04be25ae62d6fc016c0.tar.gz linux-3.10-1bfea3e49d2edd8ea102d04be25ae62d6fc016c0.tar.bz2 linux-3.10-1bfea3e49d2edd8ea102d04be25ae62d6fc016c0.zip |
[media] gspca-cpia1: 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>
Diffstat (limited to 'drivers/media/video/gspca')
-rw-r--r-- | drivers/media/video/gspca/cpia1.c | 485 |
1 files changed, 127 insertions, 358 deletions
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 8f33bbd091a..57cad7b9431 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -225,6 +225,15 @@ MODULE_LICENSE("GPL"); #define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \ sd->params.version.firmwareRevision == (y)) +#define CPIA1_CID_COMP_TARGET (V4L2_CTRL_CLASS_USER + 0x1000) +#define BRIGHTNESS_DEF 50 +#define CONTRAST_DEF 48 +#define SATURATION_DEF 50 +#define FREQ_DEF V4L2_CID_POWER_LINE_FREQUENCY_50HZ +#define ILLUMINATORS_1_DEF 0 +#define ILLUMINATORS_2_DEF 0 +#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY + /* Developer's Guide Table 5 p 3-34 * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ static u8 flicker_jumps[2][2][4] = @@ -360,135 +369,9 @@ struct sd { atomic_t fps; int exposure_count; u8 exposure_status; + struct v4l2_ctrl *freq; u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */ u8 first_frame; - u8 freq; -}; - -/* V4L2 controls supported by the driver */ -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getilluminator1(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getilluminator2(struct gspca_dev *gspca_dev, __s32 *val); - -static const struct ctrl sd_ctrls[] = { - { -#define BRIGHTNESS_IDX 0 - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 100, - .step = 1, -#define BRIGHTNESS_DEF 50 - .default_value = BRIGHTNESS_DEF, - .flags = 0, - }, - .set = sd_setbrightness, - .get = sd_getbrightness, - }, -#define CONTRAST_IDX 1 - { - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 96, - .step = 8, -#define CONTRAST_DEF 48 - .default_value = CONTRAST_DEF, - }, - .set = sd_setcontrast, - .get = sd_getcontrast, - }, -#define SATURATION_IDX 2 - { - { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 100, - .step = 1, -#define SATURATION_DEF 50 - .default_value = SATURATION_DEF, - }, - .set = sd_setsaturation, - .get = sd_getsaturation, - }, -#define POWER_LINE_FREQUENCY_IDX 3 - { - { - .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, -#define FREQ_DEF 1 - .default_value = FREQ_DEF, - }, - .set = sd_setfreq, - .get = sd_getfreq, - }, -#define ILLUMINATORS_1_IDX 4 - { - { - .id = V4L2_CID_ILLUMINATORS_1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Illuminator 1", - .minimum = 0, - .maximum = 1, - .step = 1, -#define ILLUMINATORS_1_DEF 0 - .default_value = ILLUMINATORS_1_DEF, - }, - .set = sd_setilluminator1, - .get = sd_getilluminator1, - }, -#define ILLUMINATORS_2_IDX 5 - { - { - .id = V4L2_CID_ILLUMINATORS_2, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Illuminator 2", - .minimum = 0, - .maximum = 1, - .step = 1, -#define ILLUMINATORS_2_DEF 0 - .default_value = ILLUMINATORS_2_DEF, - }, - .set = sd_setilluminator2, - .get = sd_getilluminator2, - }, -#define COMP_TARGET_IDX 6 - { - { -#define V4L2_CID_COMP_TARGET V4L2_CID_PRIVATE_BASE - .id = V4L2_CID_COMP_TARGET, - .type = V4L2_CTRL_TYPE_MENU, - .name = "Compression Target", - .minimum = 0, - .maximum = 1, - .step = 1, -#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY - .default_value = COMP_TARGET_DEF, - }, - .set = sd_setcomptarget, - .get = sd_getcomptarget, - }, }; static const struct v4l2_pix_format mode[] = { @@ -770,15 +653,6 @@ static void reset_camera_params(struct gspca_dev *gspca_dev) params->apcor.gain2 = 0x16; params->apcor.gain4 = 0x24; params->apcor.gain8 = 0x34; - params->flickerControl.flickerMode = 0; - params->flickerControl.disabled = 1; - - params->flickerControl.coarseJump = - flicker_jumps[sd->mainsFreq] - [params->sensorFps.baserate] - [params->sensorFps.divisor]; - params->flickerControl.allowableOverExposure = - find_over_exposure(params->colourParams.brightness); params->vlOffset.gain1 = 20; params->vlOffset.gain2 = 24; params->vlOffset.gain4 = 26; @@ -798,6 +672,15 @@ static void reset_camera_params(struct gspca_dev *gspca_dev) params->sensorFps.divisor = 1; params->sensorFps.baserate = 1; + params->flickerControl.flickerMode = 0; + params->flickerControl.disabled = 1; + params->flickerControl.coarseJump = + flicker_jumps[sd->mainsFreq] + [params->sensorFps.baserate] + [params->sensorFps.divisor]; + params->flickerControl.allowableOverExposure = + find_over_exposure(params->colourParams.brightness); + params->yuvThreshold.yThreshold = 6; /* From windows driver */ params->yuvThreshold.uvThreshold = 6; /* From windows driver */ @@ -1110,9 +993,6 @@ static int command_setlights(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int ret, p1, p2; - if (!sd->params.qx3.qx3_detected) - return 0; - p1 = (sd->params.qx3.bottomlight == 0) << 1; p2 = (sd->params.qx3.toplight == 0) << 3; @@ -1551,8 +1431,10 @@ static void restart_flicker(struct gspca_dev *gspca_dev) static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { + struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; + sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ; reset_camera_params(gspca_dev); PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)", @@ -1562,8 +1444,25 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = mode; cam->nmodes = ARRAY_SIZE(mode); - sd_setfreq(gspca_dev, FREQ_DEF); + goto_low_power(gspca_dev); + /* Check the firmware version. */ + sd->params.version.firmwareVersion = 0; + get_version_information(gspca_dev); + if (sd->params.version.firmwareVersion != 1) { + PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)", + sd->params.version.firmwareVersion); + return -ENODEV; + } + /* A bug in firmware 1-02 limits gainMode to 2 */ + if (sd->params.version.firmwareRevision <= 2 && + sd->params.exposure.gainMode > 2) { + sd->params.exposure.gainMode = 2; + } + + /* set QX3 detected flag */ + sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 && + sd->params.pnpID.product == 0x0001); return 0; } @@ -1602,21 +1501,6 @@ static int sd_start(struct gspca_dev *gspca_dev) /* Check the firmware version. */ sd->params.version.firmwareVersion = 0; get_version_information(gspca_dev); - if (sd->params.version.firmwareVersion != 1) { - PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)", - sd->params.version.firmwareVersion); - return -ENODEV; - } - - /* A bug in firmware 1-02 limits gainMode to 2 */ - if (sd->params.version.firmwareRevision <= 2 && - sd->params.exposure.gainMode > 2) { - sd->params.exposure.gainMode = 2; - } - - /* set QX3 detected flag */ - sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 && - sd->params.pnpID.product == 0x0001); /* The fatal error checking should be done after * the camera powers up (developer's guide p 3-38) */ @@ -1785,9 +1669,6 @@ static int sd_init(struct gspca_dev *gspca_dev) or disable the illuminator controls, if this isn't a QX3 */ if (sd->params.qx3.qx3_detected) command_setlights(gspca_dev); - else - gspca_dev->ctrl_dis |= - ((1 << ILLUMINATORS_1_IDX) | (1 << ILLUMINATORS_2_IDX)); sd_stopN(gspca_dev); @@ -1871,235 +1752,123 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev) do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); } -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - sd->params.colourParams.brightness = val; - sd->params.flickerControl.allowableOverExposure = - find_over_exposure(sd->params.colourParams.brightness); - if (gspca_dev->streaming) { - ret = command_setcolourparams(gspca_dev); - if (ret) - return ret; - return command_setflickerctrl(gspca_dev); - } - return 0; -} - -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) +static int sd_s_ctrl(struct v4l2_ctrl *ctrl) { - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->params.colourParams.brightness; - return 0; -} + struct gspca_dev *gspca_dev = + container_of(ctrl->handler, struct gspca_dev, ctrl_handler); + struct sd *sd = (struct sd *)gspca_dev; -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; + gspca_dev->usb_err = 0; - sd->params.colourParams.contrast = val; - if (gspca_dev->streaming) - return command_setcolourparams(gspca_dev); - - return 0; -} - -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->params.colourParams.contrast; - return 0; -} - -static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->params.colourParams.saturation = val; - if (gspca_dev->streaming) - return command_setcolourparams(gspca_dev); - - return 0; -} - -static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->params.colourParams.saturation; - return 0; -} - -static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - int on; + if (!gspca_dev->streaming && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY) + return 0; - switch (val) { - case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ - on = 0; + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + sd->params.colourParams.brightness = ctrl->val; + sd->params.flickerControl.allowableOverExposure = + find_over_exposure(sd->params.colourParams.brightness); + gspca_dev->usb_err = command_setcolourparams(gspca_dev); + if (!gspca_dev->usb_err) + gspca_dev->usb_err = command_setflickerctrl(gspca_dev); break; - case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ - on = 1; - sd->mainsFreq = 0; + case V4L2_CID_CONTRAST: + sd->params.colourParams.contrast = ctrl->val; + gspca_dev->usb_err = command_setcolourparams(gspca_dev); break; - case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ - on = 1; - sd->mainsFreq = 1; + case V4L2_CID_SATURATION: + sd->params.colourParams.saturation = ctrl->val; + gspca_dev->usb_err = command_setcolourparams(gspca_dev); break; - default: - return -EINVAL; - } - - sd->freq = val; - sd->params.flickerControl.coarseJump = - flicker_jumps[sd->mainsFreq] - [sd->params.sensorFps.baserate] - [sd->params.sensorFps.divisor]; - - return set_flicker(gspca_dev, on, gspca_dev->streaming); -} - -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_setcomptarget(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->params.compressionTarget.frTargeting = val; - if (gspca_dev->streaming) - return command_setcompressiontarget(gspca_dev); - - return 0; -} - -static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->params.compressionTarget.frTargeting; - return 0; -} - -static int sd_setilluminator(struct gspca_dev *gspca_dev, __s32 val, int n) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - if (!sd->params.qx3.qx3_detected) - return -EINVAL; - - switch (n) { - case 1: - sd->params.qx3.bottomlight = val ? 1 : 0; + case V4L2_CID_POWER_LINE_FREQUENCY: + sd->mainsFreq = ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ; + sd->params.flickerControl.coarseJump = + flicker_jumps[sd->mainsFreq] + [sd->params.sensorFps.baserate] + [sd->params.sensorFps.divisor]; + + gspca_dev->usb_err = set_flicker(gspca_dev, + ctrl->val != V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, + gspca_dev->streaming); break; - case 2: - sd->params.qx3.toplight = val ? 1 : 0; + case V4L2_CID_ILLUMINATORS_1: + sd->params.qx3.bottomlight = ctrl->val; + gspca_dev->usb_err = command_setlights(gspca_dev); break; - default: - return -EINVAL; - } - - ret = command_setlights(gspca_dev); - if (ret && ret != -EINVAL) - ret = -EBUSY; - - return ret; -} - -static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val) -{ - return sd_setilluminator(gspca_dev, val, 1); -} - -static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val) -{ - return sd_setilluminator(gspca_dev, val, 2); -} - -static int sd_getilluminator(struct gspca_dev *gspca_dev, __s32 *val, int n) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!sd->params.qx3.qx3_detected) - return -EINVAL; - - switch (n) { - case 1: - *val = sd->params.qx3.bottomlight; + case V4L2_CID_ILLUMINATORS_2: + sd->params.qx3.toplight = ctrl->val; + gspca_dev->usb_err = command_setlights(gspca_dev); break; - case 2: - *val = sd->params.qx3.toplight; + case CPIA1_CID_COMP_TARGET: + sd->params.compressionTarget.frTargeting = ctrl->val; + gspca_dev->usb_err = command_setcompressiontarget(gspca_dev); break; - default: - return -EINVAL; } - return 0; + return gspca_dev->usb_err; } -static int sd_getilluminator1(struct gspca_dev *gspca_dev, __s32 *val) -{ - return sd_getilluminator(gspca_dev, val, 1); -} +static const struct v4l2_ctrl_ops sd_ctrl_ops = { + .s_ctrl = sd_s_ctrl, +}; -static int sd_getilluminator2(struct gspca_dev *gspca_dev, __s32 *val) +static int sd_init_controls(struct gspca_dev *gspca_dev) { - return sd_getilluminator(gspca_dev, val, 2); -} + struct sd *sd = (struct sd *)gspca_dev; + struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; + static const char * const comp_target_menu[] = { + "Quality", + "Framerate", + NULL + }; + static const struct v4l2_ctrl_config comp_target = { + .ops = &sd_ctrl_ops, + .id = CPIA1_CID_COMP_TARGET, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Compression Target", + .qmenu = comp_target_menu, + .max = 1, + .def = COMP_TARGET_DEF, + }; + + gspca_dev->vdev.ctrl_handler = hdl; + v4l2_ctrl_handler_init(hdl, 7); + v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 100, 1, BRIGHTNESS_DEF); + v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_CONTRAST, 0, 96, 8, CONTRAST_DEF); + v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_SATURATION, 0, 100, 1, SATURATION_DEF); + sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, + V4L2_CID_POWER_LINE_FREQUENCY, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, + FREQ_DEF); + if (sd->params.qx3.qx3_detected) { + v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_ILLUMINATORS_1, 0, 1, 1, + ILLUMINATORS_1_DEF); + v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_ILLUMINATORS_2, 0, 1, 1, + ILLUMINATORS_2_DEF); + } + v4l2_ctrl_new_custom(hdl, &comp_target, NULL); -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; - case V4L2_CID_COMP_TARGET: - switch (menu->index) { - case CPIA_COMPRESSION_TARGET_QUALITY: - strcpy((char *) menu->name, "Quality"); - return 0; - case CPIA_COMPRESSION_TARGET_FRAMERATE: - strcpy((char *) menu->name, "Framerate"); - return 0; - } - break; + if (hdl->error) { + pr_err("Could not initialize controls\n"); + return hdl->error; } - return -EINVAL; + return 0; } /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, - .ctrls = sd_ctrls, - .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, .init = sd_init, + .init_controls = sd_init_controls, .start = sd_start, .stopN = sd_stopN, .dq_callback = sd_dq_callback, .pkt_scan = sd_pkt_scan, - .querymenu = sd_querymenu, #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) .other_input = 1, #endif |