0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018
0019 #include "stv06xx_vv6410.h"
0020
0021 static struct v4l2_pix_format vv6410_mode[] = {
0022 {
0023 356,
0024 292,
0025 V4L2_PIX_FMT_SGRBG8,
0026 V4L2_FIELD_NONE,
0027 .sizeimage = 356 * 292,
0028 .bytesperline = 356,
0029 .colorspace = V4L2_COLORSPACE_SRGB,
0030 .priv = 0
0031 }
0032 };
0033
0034 static int vv6410_s_ctrl(struct v4l2_ctrl *ctrl)
0035 {
0036 struct gspca_dev *gspca_dev =
0037 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0038 int err = -EINVAL;
0039
0040 switch (ctrl->id) {
0041 case V4L2_CID_HFLIP:
0042 if (!gspca_dev->streaming)
0043 return 0;
0044 err = vv6410_set_hflip(gspca_dev, ctrl->val);
0045 break;
0046 case V4L2_CID_VFLIP:
0047 if (!gspca_dev->streaming)
0048 return 0;
0049 err = vv6410_set_vflip(gspca_dev, ctrl->val);
0050 break;
0051 case V4L2_CID_GAIN:
0052 err = vv6410_set_analog_gain(gspca_dev, ctrl->val);
0053 break;
0054 case V4L2_CID_EXPOSURE:
0055 err = vv6410_set_exposure(gspca_dev, ctrl->val);
0056 break;
0057 }
0058 return err;
0059 }
0060
0061 static const struct v4l2_ctrl_ops vv6410_ctrl_ops = {
0062 .s_ctrl = vv6410_s_ctrl,
0063 };
0064
0065 static int vv6410_probe(struct sd *sd)
0066 {
0067 u16 data;
0068 int err;
0069
0070 err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
0071 if (err < 0)
0072 return -ENODEV;
0073
0074 if (data != 0x19)
0075 return -ENODEV;
0076
0077 pr_info("vv6410 sensor detected\n");
0078
0079 sd->gspca_dev.cam.cam_mode = vv6410_mode;
0080 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode);
0081 return 0;
0082 }
0083
0084 static int vv6410_init_controls(struct sd *sd)
0085 {
0086 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
0087
0088 v4l2_ctrl_handler_init(hdl, 2);
0089
0090
0091
0092
0093
0094
0095
0096 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
0097 V4L2_CID_EXPOSURE, 0, 32768, 1, 20000);
0098 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
0099 V4L2_CID_GAIN, 0, 15, 1, 10);
0100 return hdl->error;
0101 }
0102
0103 static int vv6410_init(struct sd *sd)
0104 {
0105 int err = 0, i;
0106
0107 for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++)
0108 stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
0109
0110 err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
0111 ARRAY_SIZE(vv6410_sensor_init));
0112 return (err < 0) ? err : 0;
0113 }
0114
0115 static int vv6410_start(struct sd *sd)
0116 {
0117 int err;
0118 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
0119 struct cam *cam = &sd->gspca_dev.cam;
0120 u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
0121
0122 if (priv & VV6410_SUBSAMPLE) {
0123 gspca_dbg(gspca_dev, D_CONF, "Enabling subsampling\n");
0124 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
0125 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
0126
0127 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
0128 } else {
0129 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
0130 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
0131 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
0132
0133 }
0134
0135
0136 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
0137 if (err < 0)
0138 return err;
0139
0140 err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0);
0141 if (err < 0)
0142 return err;
0143
0144 gspca_dbg(gspca_dev, D_STREAM, "Starting stream\n");
0145
0146 return 0;
0147 }
0148
0149 static int vv6410_stop(struct sd *sd)
0150 {
0151 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
0152 int err;
0153
0154
0155 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
0156 if (err < 0)
0157 return err;
0158
0159 err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE);
0160 if (err < 0)
0161 return err;
0162
0163 gspca_dbg(gspca_dev, D_STREAM, "Halting stream\n");
0164
0165 return 0;
0166 }
0167
0168 static int vv6410_dump(struct sd *sd)
0169 {
0170 u8 i;
0171 int err = 0;
0172
0173 pr_info("Dumping all vv6410 sensor registers\n");
0174 for (i = 0; i < 0xff && !err; i++) {
0175 u16 data;
0176 err = stv06xx_read_sensor(sd, i, &data);
0177 pr_info("Register 0x%x contained 0x%x\n", i, data);
0178 }
0179 return (err < 0) ? err : 0;
0180 }
0181
0182 static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
0183 {
0184 int err;
0185 u16 i2c_data;
0186 struct sd *sd = (struct sd *) gspca_dev;
0187
0188 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
0189 if (err < 0)
0190 return err;
0191
0192 if (val)
0193 i2c_data |= VV6410_HFLIP;
0194 else
0195 i2c_data &= ~VV6410_HFLIP;
0196
0197 gspca_dbg(gspca_dev, D_CONF, "Set horizontal flip to %d\n", val);
0198 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
0199
0200 return (err < 0) ? err : 0;
0201 }
0202
0203 static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
0204 {
0205 int err;
0206 u16 i2c_data;
0207 struct sd *sd = (struct sd *) gspca_dev;
0208
0209 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
0210 if (err < 0)
0211 return err;
0212
0213 if (val)
0214 i2c_data |= VV6410_VFLIP;
0215 else
0216 i2c_data &= ~VV6410_VFLIP;
0217
0218 gspca_dbg(gspca_dev, D_CONF, "Set vertical flip to %d\n", val);
0219 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
0220
0221 return (err < 0) ? err : 0;
0222 }
0223
0224 static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
0225 {
0226 int err;
0227 struct sd *sd = (struct sd *) gspca_dev;
0228
0229 gspca_dbg(gspca_dev, D_CONF, "Set analog gain to %d\n", val);
0230 err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
0231
0232 return (err < 0) ? err : 0;
0233 }
0234
0235 static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
0236 {
0237 int err;
0238 struct sd *sd = (struct sd *) gspca_dev;
0239 unsigned int fine, coarse;
0240
0241 val = (val * val >> 14) + val / 4;
0242
0243 fine = val % VV6410_CIF_LINELENGTH;
0244 coarse = min(512, val / VV6410_CIF_LINELENGTH);
0245
0246 gspca_dbg(gspca_dev, D_CONF, "Set coarse exposure to %d, fine exposure to %d\n",
0247 coarse, fine);
0248
0249 err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
0250 if (err < 0)
0251 goto out;
0252
0253 err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
0254 if (err < 0)
0255 goto out;
0256
0257 err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
0258 if (err < 0)
0259 goto out;
0260
0261 err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
0262
0263 out:
0264 return err;
0265 }