0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0035
0036 #include "stv06xx_pb0100.h"
0037
0038 struct pb0100_ctrls {
0039 struct {
0040 struct v4l2_ctrl *autogain;
0041 struct v4l2_ctrl *gain;
0042 struct v4l2_ctrl *exposure;
0043 struct v4l2_ctrl *red;
0044 struct v4l2_ctrl *blue;
0045 struct v4l2_ctrl *natural;
0046 };
0047 struct v4l2_ctrl *target;
0048 };
0049
0050 static struct v4l2_pix_format pb0100_mode[] = {
0051
0052
0053 {
0054 320,
0055 240,
0056 V4L2_PIX_FMT_SGRBG8,
0057 V4L2_FIELD_NONE,
0058 .sizeimage = 320 * 240,
0059 .bytesperline = 320,
0060 .colorspace = V4L2_COLORSPACE_SRGB,
0061 .priv = PB0100_CROP_TO_VGA
0062 },
0063 {
0064 352,
0065 288,
0066 V4L2_PIX_FMT_SGRBG8,
0067 V4L2_FIELD_NONE,
0068 .sizeimage = 352 * 288,
0069 .bytesperline = 352,
0070 .colorspace = V4L2_COLORSPACE_SRGB,
0071 .priv = 0
0072 }
0073 };
0074
0075 static int pb0100_s_ctrl(struct v4l2_ctrl *ctrl)
0076 {
0077 struct gspca_dev *gspca_dev =
0078 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0079 struct sd *sd = (struct sd *)gspca_dev;
0080 struct pb0100_ctrls *ctrls = sd->sensor_priv;
0081 int err = -EINVAL;
0082
0083 switch (ctrl->id) {
0084 case V4L2_CID_AUTOGAIN:
0085 err = pb0100_set_autogain(gspca_dev, ctrl->val);
0086 if (err)
0087 break;
0088 if (ctrl->val)
0089 break;
0090 err = pb0100_set_gain(gspca_dev, ctrls->gain->val);
0091 if (err)
0092 break;
0093 err = pb0100_set_exposure(gspca_dev, ctrls->exposure->val);
0094 break;
0095 case V4L2_CTRL_CLASS_USER + 0x1001:
0096 err = pb0100_set_autogain_target(gspca_dev, ctrl->val);
0097 break;
0098 }
0099 return err;
0100 }
0101
0102 static const struct v4l2_ctrl_ops pb0100_ctrl_ops = {
0103 .s_ctrl = pb0100_s_ctrl,
0104 };
0105
0106 static int pb0100_init_controls(struct sd *sd)
0107 {
0108 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
0109 struct pb0100_ctrls *ctrls;
0110 static const struct v4l2_ctrl_config autogain_target = {
0111 .ops = &pb0100_ctrl_ops,
0112 .id = V4L2_CTRL_CLASS_USER + 0x1000,
0113 .type = V4L2_CTRL_TYPE_INTEGER,
0114 .name = "Automatic Gain Target",
0115 .max = 255,
0116 .step = 1,
0117 .def = 128,
0118 };
0119 static const struct v4l2_ctrl_config natural_light = {
0120 .ops = &pb0100_ctrl_ops,
0121 .id = V4L2_CTRL_CLASS_USER + 0x1001,
0122 .type = V4L2_CTRL_TYPE_BOOLEAN,
0123 .name = "Natural Light Source",
0124 .max = 1,
0125 .step = 1,
0126 .def = 1,
0127 };
0128
0129 ctrls = kzalloc(sizeof(*ctrls), GFP_KERNEL);
0130 if (!ctrls)
0131 return -ENOMEM;
0132
0133 v4l2_ctrl_handler_init(hdl, 6);
0134 ctrls->autogain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
0135 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
0136 ctrls->exposure = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
0137 V4L2_CID_EXPOSURE, 0, 511, 1, 12);
0138 ctrls->gain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
0139 V4L2_CID_GAIN, 0, 255, 1, 128);
0140 ctrls->red = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
0141 V4L2_CID_RED_BALANCE, -255, 255, 1, 0);
0142 ctrls->blue = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
0143 V4L2_CID_BLUE_BALANCE, -255, 255, 1, 0);
0144 ctrls->natural = v4l2_ctrl_new_custom(hdl, &natural_light, NULL);
0145 ctrls->target = v4l2_ctrl_new_custom(hdl, &autogain_target, NULL);
0146 if (hdl->error) {
0147 kfree(ctrls);
0148 return hdl->error;
0149 }
0150 sd->sensor_priv = ctrls;
0151 v4l2_ctrl_auto_cluster(5, &ctrls->autogain, 0, false);
0152 return 0;
0153 }
0154
0155 static int pb0100_probe(struct sd *sd)
0156 {
0157 u16 sensor;
0158 int err;
0159
0160 err = stv06xx_read_sensor(sd, PB_IDENT, &sensor);
0161
0162 if (err < 0)
0163 return -ENODEV;
0164 if ((sensor >> 8) != 0x64)
0165 return -ENODEV;
0166
0167 pr_info("Photobit pb0100 sensor detected\n");
0168
0169 sd->gspca_dev.cam.cam_mode = pb0100_mode;
0170 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
0171
0172 return 0;
0173 }
0174
0175 static int pb0100_start(struct sd *sd)
0176 {
0177 int err, packet_size, max_packet_size;
0178 struct usb_host_interface *alt;
0179 struct usb_interface *intf;
0180 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
0181 struct cam *cam = &sd->gspca_dev.cam;
0182 u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
0183
0184 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
0185 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
0186 if (!alt)
0187 return -ENODEV;
0188
0189 if (alt->desc.bNumEndpoints < 1)
0190 return -ENODEV;
0191
0192 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
0193
0194
0195 max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
0196 if (packet_size < max_packet_size)
0197 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
0198 else
0199 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
0200
0201
0202 if (mode & PB0100_CROP_TO_VGA) {
0203 stv06xx_write_sensor(sd, PB_RSTART, 30);
0204 stv06xx_write_sensor(sd, PB_CSTART, 20);
0205 stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1);
0206 stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1);
0207 } else {
0208 stv06xx_write_sensor(sd, PB_RSTART, 8);
0209 stv06xx_write_sensor(sd, PB_CSTART, 4);
0210 stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1);
0211 stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1);
0212 }
0213
0214 if (mode & PB0100_SUBSAMPLE) {
0215 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
0216 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
0217
0218 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
0219 } else {
0220 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
0221 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
0222
0223 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
0224 }
0225
0226 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1));
0227 gspca_dbg(gspca_dev, D_STREAM, "Started stream, status: %d\n", err);
0228
0229 return (err < 0) ? err : 0;
0230 }
0231
0232 static int pb0100_stop(struct sd *sd)
0233 {
0234 struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
0235 int err;
0236
0237 err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
0238
0239 if (err < 0)
0240 goto out;
0241
0242
0243 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
0244
0245 gspca_dbg(gspca_dev, D_STREAM, "Halting stream\n");
0246 out:
0247 return (err < 0) ? err : 0;
0248 }
0249
0250
0251
0252
0253
0254 static int pb0100_init(struct sd *sd)
0255 {
0256 stv06xx_write_bridge(sd, STV_REG00, 1);
0257 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0);
0258
0259
0260 stv06xx_write_sensor(sd, PB_RESET, 1);
0261 stv06xx_write_sensor(sd, PB_RESET, 0);
0262
0263
0264 stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
0265
0266
0267 stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6));
0268 stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12);
0269
0270
0271
0272
0273 stv06xx_write_sensor(sd, PB_R28, 12);
0274
0275 stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180);
0276
0277 stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12);
0278
0279
0280 stv06xx_write_sensor(sd, PB_R54, 3);
0281
0282
0283 stv06xx_write_sensor(sd, PB_R55, 0);
0284 stv06xx_write_sensor(sd, PB_UPDATEINT, 1);
0285
0286 stv06xx_write_sensor(sd, PB_R15, 800);
0287
0288 stv06xx_write_sensor(sd, PB_R17, 10);
0289
0290 stv06xx_write_sensor(sd, PB_EXPGAIN, 0);
0291
0292
0293 stv06xx_write_sensor(sd, PB_VOFFSET, 0);
0294
0295 stv06xx_write_sensor(sd, PB_ADCGAINH, 11);
0296
0297 stv06xx_write_sensor(sd, PB_ADCGAINL, 0);
0298
0299
0300 stv06xx_write_bridge(sd, STV_REG00, 0x11);
0301 stv06xx_write_bridge(sd, STV_REG03, 0x45);
0302 stv06xx_write_bridge(sd, STV_REG04, 0x07);
0303
0304
0305 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
0306 stv06xx_write_sensor(sd, PB_CFILLIN, 14);
0307 stv06xx_write_sensor(sd, PB_VBL, 0);
0308 stv06xx_write_sensor(sd, PB_FINTTIME, 0);
0309 stv06xx_write_sensor(sd, PB_RINTTIME, 123);
0310
0311 stv06xx_write_bridge(sd, STV_REG01, 0xc2);
0312 stv06xx_write_bridge(sd, STV_REG02, 0xb0);
0313 return 0;
0314 }
0315
0316 static int pb0100_dump(struct sd *sd)
0317 {
0318 return 0;
0319 }
0320
0321 static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
0322 {
0323 int err;
0324 struct sd *sd = (struct sd *) gspca_dev;
0325 struct pb0100_ctrls *ctrls = sd->sensor_priv;
0326
0327 err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
0328 if (!err)
0329 err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
0330 gspca_dbg(gspca_dev, D_CONF, "Set green gain to %d, status: %d\n",
0331 val, err);
0332
0333 if (!err)
0334 err = pb0100_set_red_balance(gspca_dev, ctrls->red->val);
0335 if (!err)
0336 err = pb0100_set_blue_balance(gspca_dev, ctrls->blue->val);
0337
0338 return err;
0339 }
0340
0341 static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
0342 {
0343 int err;
0344 struct sd *sd = (struct sd *) gspca_dev;
0345 struct pb0100_ctrls *ctrls = sd->sensor_priv;
0346
0347 val += ctrls->gain->val;
0348 if (val < 0)
0349 val = 0;
0350 else if (val > 255)
0351 val = 255;
0352
0353 err = stv06xx_write_sensor(sd, PB_RGAIN, val);
0354 gspca_dbg(gspca_dev, D_CONF, "Set red gain to %d, status: %d\n",
0355 val, err);
0356
0357 return err;
0358 }
0359
0360 static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
0361 {
0362 int err;
0363 struct sd *sd = (struct sd *) gspca_dev;
0364 struct pb0100_ctrls *ctrls = sd->sensor_priv;
0365
0366 val += ctrls->gain->val;
0367 if (val < 0)
0368 val = 0;
0369 else if (val > 255)
0370 val = 255;
0371
0372 err = stv06xx_write_sensor(sd, PB_BGAIN, val);
0373 gspca_dbg(gspca_dev, D_CONF, "Set blue gain to %d, status: %d\n",
0374 val, err);
0375
0376 return err;
0377 }
0378
0379 static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
0380 {
0381 struct sd *sd = (struct sd *) gspca_dev;
0382 int err;
0383
0384 err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
0385 gspca_dbg(gspca_dev, D_CONF, "Set exposure to %d, status: %d\n",
0386 val, err);
0387
0388 return err;
0389 }
0390
0391 static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
0392 {
0393 int err;
0394 struct sd *sd = (struct sd *) gspca_dev;
0395 struct pb0100_ctrls *ctrls = sd->sensor_priv;
0396
0397 if (val) {
0398 if (ctrls->natural->val)
0399 val = BIT(6)|BIT(4)|BIT(0);
0400 else
0401 val = BIT(4)|BIT(0);
0402 } else
0403 val = 0;
0404
0405 err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
0406 gspca_dbg(gspca_dev, D_CONF, "Set autogain to %d (natural: %d), status: %d\n",
0407 val, ctrls->natural->val, err);
0408
0409 return err;
0410 }
0411
0412 static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
0413 {
0414 int err, totalpixels, brightpixels, darkpixels;
0415 struct sd *sd = (struct sd *) gspca_dev;
0416
0417
0418
0419 totalpixels = gspca_dev->pixfmt.width * gspca_dev->pixfmt.height;
0420 totalpixels = totalpixels/(8*8) + totalpixels/(64*64);
0421
0422 brightpixels = (totalpixels * val) >> 8;
0423 darkpixels = totalpixels - brightpixels;
0424 err = stv06xx_write_sensor(sd, PB_R21, brightpixels);
0425 if (!err)
0426 err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
0427
0428 gspca_dbg(gspca_dev, D_CONF, "Set autogain target to %d, status: %d\n",
0429 val, err);
0430
0431 return err;
0432 }