Loading drivers/media/video/gspca/mr97310a.c +133 −305 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ #define MR97310A_CS_GAIN_MAX 0x7ff #define MR97310A_CS_GAIN_DEFAULT 0x110 #define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000) #define MR97310A_MIN_CLOCKDIV_MIN 3 #define MR97310A_MIN_CLOCKDIV_MAX 8 #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 Loading @@ -84,17 +85,15 @@ MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ struct { /* exposure/min_clockdiv control cluster */ struct v4l2_ctrl *exposure; struct v4l2_ctrl *min_clockdiv; }; u8 sof_read; u8 cam_type; /* 0 is CIF and 1 is VGA */ u8 sensor_type; /* We use 0 and 1 here, too. */ u8 do_lcd_stop; u8 adj_colors; int brightness; u16 exposure; u32 gain; u8 contrast; u8 min_clockdiv; }; struct sensor_w_data { Loading @@ -105,132 +104,6 @@ struct sensor_w_data { }; static void sd_stopN(struct gspca_dev *gspca_dev); 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_setexposure(struct gspca_dev *gspca_dev, __s32 val); static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); static void setbrightness(struct gspca_dev *gspca_dev); static void setexposure(struct gspca_dev *gspca_dev); static void setgain(struct gspca_dev *gspca_dev); static void setcontrast(struct gspca_dev *gspca_dev); /* V4L2 controls supported by the driver */ static const struct ctrl sd_ctrls[] = { /* Separate brightness control description for Argus QuickClix as it has * different limits from the other mr97310a cameras, and separate gain * control for Sakar CyberPix camera. */ { #define NORM_BRIGHTNESS_IDX 0 { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = -254, .maximum = 255, .step = 1, .default_value = MR97310A_BRIGHTNESS_DEFAULT, .flags = 0, }, .set = sd_setbrightness, .get = sd_getbrightness, }, { #define ARGUS_QC_BRIGHTNESS_IDX 1 { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = 0, .maximum = 15, .step = 1, .default_value = MR97310A_BRIGHTNESS_DEFAULT, .flags = 0, }, .set = sd_setbrightness, .get = sd_getbrightness, }, { #define EXPOSURE_IDX 2 { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Exposure", .minimum = MR97310A_EXPOSURE_MIN, .maximum = MR97310A_EXPOSURE_MAX, .step = 1, .default_value = MR97310A_EXPOSURE_DEFAULT, .flags = 0, }, .set = sd_setexposure, .get = sd_getexposure, }, { #define GAIN_IDX 3 { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gain", .minimum = MR97310A_GAIN_MIN, .maximum = MR97310A_GAIN_MAX, .step = 1, .default_value = MR97310A_GAIN_DEFAULT, .flags = 0, }, .set = sd_setgain, .get = sd_getgain, }, { #define SAKAR_CS_GAIN_IDX 4 { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gain", .minimum = MR97310A_CS_GAIN_MIN, .maximum = MR97310A_CS_GAIN_MAX, .step = 1, .default_value = MR97310A_CS_GAIN_DEFAULT, .flags = 0, }, .set = sd_setgain, .get = sd_getgain, }, { #define CONTRAST_IDX 5 { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = MR97310A_CONTRAST_MIN, .maximum = MR97310A_CONTRAST_MAX, .step = 1, .default_value = MR97310A_CONTRAST_DEFAULT, .flags = 0, }, .set = sd_setcontrast, .get = sd_getcontrast, }, { #define MIN_CLOCKDIV_IDX 6 { .id = V4L2_CID_PRIVATE_BASE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Minimum Clock Divider", .minimum = MR97310A_MIN_CLOCKDIV_MIN, .maximum = MR97310A_MIN_CLOCKDIV_MAX, .step = 1, .default_value = MR97310A_MIN_CLOCKDIV_DEFAULT, .flags = 0, }, .set = sd_setmin_clockdiv, .get = sd_getmin_clockdiv, }, }; static const struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, Loading Loading @@ -481,7 +354,6 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int gain_default = MR97310A_GAIN_DEFAULT; int err_code; cam = &gspca_dev->cam; Loading Loading @@ -615,52 +487,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor_type); } /* Setup controls depending on camera type */ if (sd->cam_type == CAM_TYPE_CIF) { /* No brightness for sensor_type 0 */ if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX); else gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX) | (1 << MIN_CLOCKDIV_IDX); } else { /* All controls need to be disabled if VGA sensor_type is 0 */ if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << EXPOSURE_IDX) | (1 << GAIN_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX) | (1 << MIN_CLOCKDIV_IDX); else if (sd->sensor_type == 2) { gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << GAIN_IDX) | (1 << MIN_CLOCKDIV_IDX); gain_default = MR97310A_CS_GAIN_DEFAULT; } else if (sd->do_lcd_stop) /* Argus QuickClix has different brightness limits */ gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX); else gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX); } sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; sd->exposure = MR97310A_EXPOSURE_DEFAULT; sd->gain = gain_default; sd->contrast = MR97310A_CONTRAST_DEFAULT; sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; return 0; } Loading Loading @@ -952,11 +778,6 @@ static int sd_start(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; setbrightness(gspca_dev); setcontrast(gspca_dev); setexposure(gspca_dev); setgain(gspca_dev); return isoc_enable(gspca_dev); } Loading @@ -971,37 +792,25 @@ static void sd_stopN(struct gspca_dev *gspca_dev) lcd_stop(gspca_dev); } static void setbrightness(struct gspca_dev *gspca_dev) static void setbrightness(struct gspca_dev *gspca_dev, s32 val) { struct sd *sd = (struct sd *) gspca_dev; u8 val; u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */ u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ static const u8 quick_clix_table[] = /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; /* * This control is disabled for CIF type 1 and VGA type 0 cameras. * It does not quite act linearly for the Argus QuickClix camera, * but it does control brightness. The values are 0 - 15 only, and * the table above makes them act consecutively. */ if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) && (gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX))) return; if (sd->cam_type == CAM_TYPE_VGA) { sign_reg += 4; value_reg += 4; } /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ if (sd->brightness > 0) { if (val > 0) { sensor_write1(gspca_dev, sign_reg, 0x00); val = sd->brightness; } else { sensor_write1(gspca_dev, sign_reg, 0x01); val = (257 - sd->brightness); val = 257 - val; } /* Use lookup table for funky Argus QuickClix brightness */ if (sd->do_lcd_stop) Loading @@ -1010,23 +819,20 @@ static void setbrightness(struct gspca_dev *gspca_dev) sensor_write1(gspca_dev, value_reg, val); } static void setexposure(struct gspca_dev *gspca_dev) static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv) { struct sd *sd = (struct sd *) gspca_dev; int exposure = MR97310A_EXPOSURE_DEFAULT; u8 buf[2]; if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) return; if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { /* This cam does not like exposure settings < 300, so scale 0 - 4095 to 300 - 4095 */ exposure = (sd->exposure * 9267) / 10000 + 300; exposure = (expo * 9267) / 10000 + 300; sensor_write1(gspca_dev, 3, exposure >> 4); sensor_write1(gspca_dev, 4, exposure & 0x0f); } else if (sd->sensor_type == 2) { exposure = sd->exposure; exposure = expo; exposure >>= 3; sensor_write1(gspca_dev, 3, exposure >> 8); sensor_write1(gspca_dev, 4, exposure & 0xff); Loading @@ -1038,11 +844,11 @@ static void setexposure(struct gspca_dev *gspca_dev) Note our 0 - 4095 exposure is mapped to 0 - 511 milliseconds exposure time */ u8 clockdiv = (60 * sd->exposure + 7999) / 8000; u8 clockdiv = (60 * expo + 7999) / 8000; /* Limit framerate to not exceed usb bandwidth */ if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320) clockdiv = sd->min_clockdiv; if (clockdiv < min_clockdiv && gspca_dev->width >= 320) clockdiv = min_clockdiv; else if (clockdiv < 2) clockdiv = 2; Loading @@ -1051,7 +857,7 @@ static void setexposure(struct gspca_dev *gspca_dev) /* Frame exposure time in ms = 1000 * clockdiv / 60 -> exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv); exposure = (60 * 511 * expo) / (8000 * clockdiv); if (exposure > 511) exposure = 511; Loading @@ -1065,125 +871,148 @@ static void setexposure(struct gspca_dev *gspca_dev) } } static void setgain(struct gspca_dev *gspca_dev) static void setgain(struct gspca_dev *gspca_dev, s32 val) { struct sd *sd = (struct sd *) gspca_dev; u8 gainreg; if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) && (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX))) return; if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) sensor_write1(gspca_dev, 0x0e, sd->gain); sensor_write1(gspca_dev, 0x0e, val); else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { sensor_write1(gspca_dev, gainreg, sd->gain >> 8); sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff); sensor_write1(gspca_dev, gainreg, val >> 8); sensor_write1(gspca_dev, gainreg + 1, val & 0xff); } else sensor_write1(gspca_dev, 0x10, sd->gain); sensor_write1(gspca_dev, 0x10, val); } static void setcontrast(struct gspca_dev *gspca_dev) static void setcontrast(struct gspca_dev *gspca_dev, s32 val) { struct sd *sd = (struct sd *) gspca_dev; if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) return; sensor_write1(gspca_dev, 0x1c, sd->contrast); sensor_write1(gspca_dev, 0x1c, val); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 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; sd->brightness = val; if (gspca_dev->streaming) setbrightness(gspca_dev); return 0; } gspca_dev->usb_err = 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_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); if (!gspca_dev->streaming) 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; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: setbrightness(gspca_dev, ctrl->val); break; case V4L2_CID_CONTRAST: setcontrast(gspca_dev, ctrl->val); break; case V4L2_CID_EXPOSURE: setexposure(gspca_dev, sd->exposure->val, sd->min_clockdiv ? sd->min_clockdiv->val : 0); break; case V4L2_CID_GAIN: setgain(gspca_dev, ctrl->val); break; } 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; return gspca_dev->usb_err; } static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; *val = sd->gain; return 0; } static const struct v4l2_ctrl_ops sd_ctrl_ops = { .s_ctrl = sd_s_ctrl, }; static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 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; static const struct v4l2_ctrl_config clockdiv = { .ops = &sd_ctrl_ops, .id = MR97310A_CID_CLOCKDIV, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Minimum Clock Divider", .min = MR97310A_MIN_CLOCKDIV_MIN, .max = MR97310A_MIN_CLOCKDIV_MAX, .step = 1, .def = MR97310A_MIN_CLOCKDIV_DEFAULT, }; bool has_brightness = false; bool has_argus_brightness = false; bool has_contrast = false; bool has_gain = false; bool has_cs_gain = false; bool has_exposure = false; bool has_clockdiv = false; sd->contrast = val; if (gspca_dev->streaming) setcontrast(gspca_dev); return 0; } static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; gspca_dev->vdev.ctrl_handler = hdl; v4l2_ctrl_handler_init(hdl, 4); *val = sd->contrast; return 0; /* Setup controls depending on camera type */ if (sd->cam_type == CAM_TYPE_CIF) { /* No brightness for sensor_type 0 */ if (sd->sensor_type == 0) has_exposure = has_gain = has_clockdiv = true; else has_exposure = has_gain = has_brightness = true; } else { /* All controls need to be disabled if VGA sensor_type is 0 */ if (sd->sensor_type == 0) ; /* no controls! */ else if (sd->sensor_type == 2) has_exposure = has_cs_gain = has_contrast = true; else if (sd->do_lcd_stop) has_exposure = has_gain = has_argus_brightness = has_clockdiv = true; else has_exposure = has_gain = has_brightness = has_clockdiv = true; } static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; sd->min_clockdiv = val; if (gspca_dev->streaming) setexposure(gspca_dev); return 0; /* Separate brightness control description for Argus QuickClix as it has * different limits from the other mr97310a cameras, and separate gain * control for Sakar CyberPix camera. */ /* * This control is disabled for CIF type 1 and VGA type 0 cameras. * It does not quite act linearly for the Argus QuickClix camera, * but it does control brightness. The values are 0 - 15 only, and * the table above makes them act consecutively. */ if (has_brightness) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS, -254, 255, 1, MR97310A_BRIGHTNESS_DEFAULT); else if (has_argus_brightness) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 15, 1, MR97310A_BRIGHTNESS_DEFAULT); if (has_contrast) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN, MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT); if (has_gain) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX, 1, MR97310A_GAIN_DEFAULT); else if (has_cs_gain) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN, MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX, 1, MR97310A_CS_GAIN_DEFAULT); if (has_exposure) sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN, MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT); if (has_clockdiv) sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL); if (hdl->error) { pr_err("Could not initialize controls\n"); return hdl->error; } static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; *val = sd->min_clockdiv; if (has_exposure && has_clockdiv) v4l2_ctrl_cluster(2, &sd->exposure); return 0; } Loading Loading @@ -1221,10 +1050,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* 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, .pkt_scan = sd_pkt_scan, Loading Loading
drivers/media/video/gspca/mr97310a.c +133 −305 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ #define MR97310A_CS_GAIN_MAX 0x7ff #define MR97310A_CS_GAIN_DEFAULT 0x110 #define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000) #define MR97310A_MIN_CLOCKDIV_MIN 3 #define MR97310A_MIN_CLOCKDIV_MAX 8 #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 Loading @@ -84,17 +85,15 @@ MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ struct { /* exposure/min_clockdiv control cluster */ struct v4l2_ctrl *exposure; struct v4l2_ctrl *min_clockdiv; }; u8 sof_read; u8 cam_type; /* 0 is CIF and 1 is VGA */ u8 sensor_type; /* We use 0 and 1 here, too. */ u8 do_lcd_stop; u8 adj_colors; int brightness; u16 exposure; u32 gain; u8 contrast; u8 min_clockdiv; }; struct sensor_w_data { Loading @@ -105,132 +104,6 @@ struct sensor_w_data { }; static void sd_stopN(struct gspca_dev *gspca_dev); 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_setexposure(struct gspca_dev *gspca_dev, __s32 val); static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); static void setbrightness(struct gspca_dev *gspca_dev); static void setexposure(struct gspca_dev *gspca_dev); static void setgain(struct gspca_dev *gspca_dev); static void setcontrast(struct gspca_dev *gspca_dev); /* V4L2 controls supported by the driver */ static const struct ctrl sd_ctrls[] = { /* Separate brightness control description for Argus QuickClix as it has * different limits from the other mr97310a cameras, and separate gain * control for Sakar CyberPix camera. */ { #define NORM_BRIGHTNESS_IDX 0 { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = -254, .maximum = 255, .step = 1, .default_value = MR97310A_BRIGHTNESS_DEFAULT, .flags = 0, }, .set = sd_setbrightness, .get = sd_getbrightness, }, { #define ARGUS_QC_BRIGHTNESS_IDX 1 { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = 0, .maximum = 15, .step = 1, .default_value = MR97310A_BRIGHTNESS_DEFAULT, .flags = 0, }, .set = sd_setbrightness, .get = sd_getbrightness, }, { #define EXPOSURE_IDX 2 { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Exposure", .minimum = MR97310A_EXPOSURE_MIN, .maximum = MR97310A_EXPOSURE_MAX, .step = 1, .default_value = MR97310A_EXPOSURE_DEFAULT, .flags = 0, }, .set = sd_setexposure, .get = sd_getexposure, }, { #define GAIN_IDX 3 { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gain", .minimum = MR97310A_GAIN_MIN, .maximum = MR97310A_GAIN_MAX, .step = 1, .default_value = MR97310A_GAIN_DEFAULT, .flags = 0, }, .set = sd_setgain, .get = sd_getgain, }, { #define SAKAR_CS_GAIN_IDX 4 { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gain", .minimum = MR97310A_CS_GAIN_MIN, .maximum = MR97310A_CS_GAIN_MAX, .step = 1, .default_value = MR97310A_CS_GAIN_DEFAULT, .flags = 0, }, .set = sd_setgain, .get = sd_getgain, }, { #define CONTRAST_IDX 5 { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = MR97310A_CONTRAST_MIN, .maximum = MR97310A_CONTRAST_MAX, .step = 1, .default_value = MR97310A_CONTRAST_DEFAULT, .flags = 0, }, .set = sd_setcontrast, .get = sd_getcontrast, }, { #define MIN_CLOCKDIV_IDX 6 { .id = V4L2_CID_PRIVATE_BASE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Minimum Clock Divider", .minimum = MR97310A_MIN_CLOCKDIV_MIN, .maximum = MR97310A_MIN_CLOCKDIV_MAX, .step = 1, .default_value = MR97310A_MIN_CLOCKDIV_DEFAULT, .flags = 0, }, .set = sd_setmin_clockdiv, .get = sd_getmin_clockdiv, }, }; static const struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, Loading Loading @@ -481,7 +354,6 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int gain_default = MR97310A_GAIN_DEFAULT; int err_code; cam = &gspca_dev->cam; Loading Loading @@ -615,52 +487,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor_type); } /* Setup controls depending on camera type */ if (sd->cam_type == CAM_TYPE_CIF) { /* No brightness for sensor_type 0 */ if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX); else gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX) | (1 << MIN_CLOCKDIV_IDX); } else { /* All controls need to be disabled if VGA sensor_type is 0 */ if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << EXPOSURE_IDX) | (1 << GAIN_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX) | (1 << MIN_CLOCKDIV_IDX); else if (sd->sensor_type == 2) { gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << GAIN_IDX) | (1 << MIN_CLOCKDIV_IDX); gain_default = MR97310A_CS_GAIN_DEFAULT; } else if (sd->do_lcd_stop) /* Argus QuickClix has different brightness limits */ gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX); else gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << SAKAR_CS_GAIN_IDX); } sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; sd->exposure = MR97310A_EXPOSURE_DEFAULT; sd->gain = gain_default; sd->contrast = MR97310A_CONTRAST_DEFAULT; sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; return 0; } Loading Loading @@ -952,11 +778,6 @@ static int sd_start(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; setbrightness(gspca_dev); setcontrast(gspca_dev); setexposure(gspca_dev); setgain(gspca_dev); return isoc_enable(gspca_dev); } Loading @@ -971,37 +792,25 @@ static void sd_stopN(struct gspca_dev *gspca_dev) lcd_stop(gspca_dev); } static void setbrightness(struct gspca_dev *gspca_dev) static void setbrightness(struct gspca_dev *gspca_dev, s32 val) { struct sd *sd = (struct sd *) gspca_dev; u8 val; u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */ u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ static const u8 quick_clix_table[] = /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; /* * This control is disabled for CIF type 1 and VGA type 0 cameras. * It does not quite act linearly for the Argus QuickClix camera, * but it does control brightness. The values are 0 - 15 only, and * the table above makes them act consecutively. */ if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) && (gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX))) return; if (sd->cam_type == CAM_TYPE_VGA) { sign_reg += 4; value_reg += 4; } /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ if (sd->brightness > 0) { if (val > 0) { sensor_write1(gspca_dev, sign_reg, 0x00); val = sd->brightness; } else { sensor_write1(gspca_dev, sign_reg, 0x01); val = (257 - sd->brightness); val = 257 - val; } /* Use lookup table for funky Argus QuickClix brightness */ if (sd->do_lcd_stop) Loading @@ -1010,23 +819,20 @@ static void setbrightness(struct gspca_dev *gspca_dev) sensor_write1(gspca_dev, value_reg, val); } static void setexposure(struct gspca_dev *gspca_dev) static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv) { struct sd *sd = (struct sd *) gspca_dev; int exposure = MR97310A_EXPOSURE_DEFAULT; u8 buf[2]; if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) return; if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { /* This cam does not like exposure settings < 300, so scale 0 - 4095 to 300 - 4095 */ exposure = (sd->exposure * 9267) / 10000 + 300; exposure = (expo * 9267) / 10000 + 300; sensor_write1(gspca_dev, 3, exposure >> 4); sensor_write1(gspca_dev, 4, exposure & 0x0f); } else if (sd->sensor_type == 2) { exposure = sd->exposure; exposure = expo; exposure >>= 3; sensor_write1(gspca_dev, 3, exposure >> 8); sensor_write1(gspca_dev, 4, exposure & 0xff); Loading @@ -1038,11 +844,11 @@ static void setexposure(struct gspca_dev *gspca_dev) Note our 0 - 4095 exposure is mapped to 0 - 511 milliseconds exposure time */ u8 clockdiv = (60 * sd->exposure + 7999) / 8000; u8 clockdiv = (60 * expo + 7999) / 8000; /* Limit framerate to not exceed usb bandwidth */ if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320) clockdiv = sd->min_clockdiv; if (clockdiv < min_clockdiv && gspca_dev->width >= 320) clockdiv = min_clockdiv; else if (clockdiv < 2) clockdiv = 2; Loading @@ -1051,7 +857,7 @@ static void setexposure(struct gspca_dev *gspca_dev) /* Frame exposure time in ms = 1000 * clockdiv / 60 -> exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv); exposure = (60 * 511 * expo) / (8000 * clockdiv); if (exposure > 511) exposure = 511; Loading @@ -1065,125 +871,148 @@ static void setexposure(struct gspca_dev *gspca_dev) } } static void setgain(struct gspca_dev *gspca_dev) static void setgain(struct gspca_dev *gspca_dev, s32 val) { struct sd *sd = (struct sd *) gspca_dev; u8 gainreg; if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) && (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX))) return; if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) sensor_write1(gspca_dev, 0x0e, sd->gain); sensor_write1(gspca_dev, 0x0e, val); else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { sensor_write1(gspca_dev, gainreg, sd->gain >> 8); sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff); sensor_write1(gspca_dev, gainreg, val >> 8); sensor_write1(gspca_dev, gainreg + 1, val & 0xff); } else sensor_write1(gspca_dev, 0x10, sd->gain); sensor_write1(gspca_dev, 0x10, val); } static void setcontrast(struct gspca_dev *gspca_dev) static void setcontrast(struct gspca_dev *gspca_dev, s32 val) { struct sd *sd = (struct sd *) gspca_dev; if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) return; sensor_write1(gspca_dev, 0x1c, sd->contrast); sensor_write1(gspca_dev, 0x1c, val); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 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; sd->brightness = val; if (gspca_dev->streaming) setbrightness(gspca_dev); return 0; } gspca_dev->usb_err = 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_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); if (!gspca_dev->streaming) 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; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: setbrightness(gspca_dev, ctrl->val); break; case V4L2_CID_CONTRAST: setcontrast(gspca_dev, ctrl->val); break; case V4L2_CID_EXPOSURE: setexposure(gspca_dev, sd->exposure->val, sd->min_clockdiv ? sd->min_clockdiv->val : 0); break; case V4L2_CID_GAIN: setgain(gspca_dev, ctrl->val); break; } 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; return gspca_dev->usb_err; } static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; *val = sd->gain; return 0; } static const struct v4l2_ctrl_ops sd_ctrl_ops = { .s_ctrl = sd_s_ctrl, }; static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 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; static const struct v4l2_ctrl_config clockdiv = { .ops = &sd_ctrl_ops, .id = MR97310A_CID_CLOCKDIV, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Minimum Clock Divider", .min = MR97310A_MIN_CLOCKDIV_MIN, .max = MR97310A_MIN_CLOCKDIV_MAX, .step = 1, .def = MR97310A_MIN_CLOCKDIV_DEFAULT, }; bool has_brightness = false; bool has_argus_brightness = false; bool has_contrast = false; bool has_gain = false; bool has_cs_gain = false; bool has_exposure = false; bool has_clockdiv = false; sd->contrast = val; if (gspca_dev->streaming) setcontrast(gspca_dev); return 0; } static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; gspca_dev->vdev.ctrl_handler = hdl; v4l2_ctrl_handler_init(hdl, 4); *val = sd->contrast; return 0; /* Setup controls depending on camera type */ if (sd->cam_type == CAM_TYPE_CIF) { /* No brightness for sensor_type 0 */ if (sd->sensor_type == 0) has_exposure = has_gain = has_clockdiv = true; else has_exposure = has_gain = has_brightness = true; } else { /* All controls need to be disabled if VGA sensor_type is 0 */ if (sd->sensor_type == 0) ; /* no controls! */ else if (sd->sensor_type == 2) has_exposure = has_cs_gain = has_contrast = true; else if (sd->do_lcd_stop) has_exposure = has_gain = has_argus_brightness = has_clockdiv = true; else has_exposure = has_gain = has_brightness = has_clockdiv = true; } static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; sd->min_clockdiv = val; if (gspca_dev->streaming) setexposure(gspca_dev); return 0; /* Separate brightness control description for Argus QuickClix as it has * different limits from the other mr97310a cameras, and separate gain * control for Sakar CyberPix camera. */ /* * This control is disabled for CIF type 1 and VGA type 0 cameras. * It does not quite act linearly for the Argus QuickClix camera, * but it does control brightness. The values are 0 - 15 only, and * the table above makes them act consecutively. */ if (has_brightness) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS, -254, 255, 1, MR97310A_BRIGHTNESS_DEFAULT); else if (has_argus_brightness) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 15, 1, MR97310A_BRIGHTNESS_DEFAULT); if (has_contrast) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN, MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT); if (has_gain) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX, 1, MR97310A_GAIN_DEFAULT); else if (has_cs_gain) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN, MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX, 1, MR97310A_CS_GAIN_DEFAULT); if (has_exposure) sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN, MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT); if (has_clockdiv) sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL); if (hdl->error) { pr_err("Could not initialize controls\n"); return hdl->error; } static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; *val = sd->min_clockdiv; if (has_exposure && has_clockdiv) v4l2_ctrl_cluster(2, &sd->exposure); return 0; } Loading Loading @@ -1221,10 +1050,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* 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, .pkt_scan = sd_pkt_scan, Loading