Loading drivers/media/video/gspca/topro.c +226 −233 Original line number Diff line number Diff line Loading @@ -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) */ Loading Loading @@ -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); 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, sd->ctrls[BGAIN].val >> 8); i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, sd->ctrls[BGAIN].val); blue >> 8); i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, blue); 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); 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; Loading @@ -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 */ Loading @@ -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; Loading Loading @@ -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 */ Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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 */ Loading Loading @@ -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; Loading @@ -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 */ } Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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 */ Loading Loading @@ -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}, Loading Loading @@ -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); Loading @@ -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}, Loading Loading @@ -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}, Loading @@ -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)); Loading @@ -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)); Loading @@ -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)); } Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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, Loading @@ -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] = { static int sd_s_ctrl(struct v4l2_ctrl *ctrl) { .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 }, 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, Loading Loading
drivers/media/video/gspca/topro.c +226 −233 Original line number Diff line number Diff line Loading @@ -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) */ Loading Loading @@ -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); 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, sd->ctrls[BGAIN].val >> 8); i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, sd->ctrls[BGAIN].val); blue >> 8); i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, blue); 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); 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; Loading @@ -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 */ Loading @@ -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; Loading Loading @@ -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 */ Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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 */ Loading Loading @@ -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; Loading @@ -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 */ } Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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 */ Loading Loading @@ -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}, Loading Loading @@ -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); Loading @@ -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}, Loading Loading @@ -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}, Loading @@ -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)); Loading @@ -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)); Loading @@ -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)); } Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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, Loading @@ -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] = { static int sd_s_ctrl(struct v4l2_ctrl *ctrl) { .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 }, 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, Loading