Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
0004  *            Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
0005  * Copyright (c) 2002, 2003 Tuukka Toivonen
0006  * Copyright (c) 2008 Erik Andrén
0007  * Copyright (c) 2008 Chia-I Wu
0008  *
0009  * P/N 861037:      Sensor HDCS1000        ASIC STV0600
0010  * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
0011  * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
0012  * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
0013  * P/N 861075-0040: Sensor HDCS1000        ASIC
0014  * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
0015  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
0016  */
0017 
0018 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0019 
0020 #include "stv06xx_hdcs.h"
0021 
0022 static struct v4l2_pix_format hdcs1x00_mode[] = {
0023     {
0024         HDCS_1X00_DEF_WIDTH,
0025         HDCS_1X00_DEF_HEIGHT,
0026         V4L2_PIX_FMT_SGRBG8,
0027         V4L2_FIELD_NONE,
0028         .sizeimage =
0029             HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
0030         .bytesperline = HDCS_1X00_DEF_WIDTH,
0031         .colorspace = V4L2_COLORSPACE_SRGB,
0032         .priv = 1
0033     }
0034 };
0035 
0036 static struct v4l2_pix_format hdcs1020_mode[] = {
0037     {
0038         HDCS_1020_DEF_WIDTH,
0039         HDCS_1020_DEF_HEIGHT,
0040         V4L2_PIX_FMT_SGRBG8,
0041         V4L2_FIELD_NONE,
0042         .sizeimage =
0043             HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
0044         .bytesperline = HDCS_1020_DEF_WIDTH,
0045         .colorspace = V4L2_COLORSPACE_SRGB,
0046         .priv = 1
0047     }
0048 };
0049 
0050 enum hdcs_power_state {
0051     HDCS_STATE_SLEEP,
0052     HDCS_STATE_IDLE,
0053     HDCS_STATE_RUN
0054 };
0055 
0056 /* no lock? */
0057 struct hdcs {
0058     enum hdcs_power_state state;
0059     int w, h;
0060 
0061     /* visible area of the sensor array */
0062     struct {
0063         int left, top;
0064         int width, height;
0065         int border;
0066     } array;
0067 
0068     struct {
0069         /* Column timing overhead */
0070         u8 cto;
0071         /* Column processing overhead */
0072         u8 cpo;
0073         /* Row sample period constant */
0074         u16 rs;
0075         /* Exposure reset duration */
0076         u16 er;
0077     } exp;
0078 
0079     int psmp;
0080 };
0081 
0082 static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
0083 {
0084     u8 regs[I2C_MAX_BYTES * 2];
0085     int i;
0086 
0087     if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) ||
0088              (reg + len > 0xff)))
0089         return -EINVAL;
0090 
0091     for (i = 0; i < len; i++) {
0092         regs[2 * i] = reg;
0093         regs[2 * i + 1] = vals[i];
0094         /* All addresses are shifted left one bit
0095          * as bit 0 toggles r/w */
0096         reg += 2;
0097     }
0098 
0099     return stv06xx_write_sensor_bytes(sd, regs, len);
0100 }
0101 
0102 static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
0103 {
0104     struct hdcs *hdcs = sd->sensor_priv;
0105     u8 val;
0106     int ret;
0107 
0108     if (hdcs->state == state)
0109         return 0;
0110 
0111     /* we need to go idle before running or sleeping */
0112     if (hdcs->state != HDCS_STATE_IDLE) {
0113         ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
0114         if (ret)
0115             return ret;
0116     }
0117 
0118     hdcs->state = HDCS_STATE_IDLE;
0119 
0120     if (state == HDCS_STATE_IDLE)
0121         return 0;
0122 
0123     switch (state) {
0124     case HDCS_STATE_SLEEP:
0125         val = HDCS_SLEEP_MODE;
0126         break;
0127 
0128     case HDCS_STATE_RUN:
0129         val = HDCS_RUN_ENABLE;
0130         break;
0131 
0132     default:
0133         return -EINVAL;
0134     }
0135 
0136     ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
0137 
0138     /* Update the state if the write succeeded */
0139     if (!ret)
0140         hdcs->state = state;
0141 
0142     return ret;
0143 }
0144 
0145 static int hdcs_reset(struct sd *sd)
0146 {
0147     struct hdcs *hdcs = sd->sensor_priv;
0148     int err;
0149 
0150     err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1);
0151     if (err < 0)
0152         return err;
0153 
0154     err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
0155     if (err < 0)
0156         hdcs->state = HDCS_STATE_IDLE;
0157 
0158     return err;
0159 }
0160 
0161 static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
0162 {
0163     struct sd *sd = (struct sd *) gspca_dev;
0164     struct hdcs *hdcs = sd->sensor_priv;
0165     int rowexp, srowexp;
0166     int max_srowexp;
0167     /* Column time period */
0168     int ct;
0169     /* Column processing period */
0170     int cp;
0171     /* Row processing period */
0172     int rp;
0173     /* Minimum number of column timing periods
0174        within the column processing period */
0175     int mnct;
0176     int cycles, err;
0177     u8 exp[14];
0178 
0179     cycles = val * HDCS_CLK_FREQ_MHZ * 257;
0180 
0181     ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
0182     cp = hdcs->exp.cto + (hdcs->w * ct / 2);
0183 
0184     /* the cycles one row takes */
0185     rp = hdcs->exp.rs + cp;
0186 
0187     rowexp = cycles / rp;
0188 
0189     /* the remaining cycles */
0190     cycles -= rowexp * rp;
0191 
0192     /* calculate sub-row exposure */
0193     if (IS_1020(sd)) {
0194         /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */
0195         srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct;
0196 
0197         mnct = (hdcs->exp.er + 12 + ct - 1) / ct;
0198         max_srowexp = hdcs->w - mnct;
0199     } else {
0200         /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */
0201         srowexp = cp - hdcs->exp.er - 6 - cycles;
0202 
0203         mnct = (hdcs->exp.er + 5 + ct - 1) / ct;
0204         max_srowexp = cp - mnct * ct - 1;
0205     }
0206 
0207     if (srowexp < 0)
0208         srowexp = 0;
0209     else if (srowexp > max_srowexp)
0210         srowexp = max_srowexp;
0211 
0212     if (IS_1020(sd)) {
0213         exp[0] = HDCS20_CONTROL;
0214         exp[1] = 0x00;      /* Stop streaming */
0215         exp[2] = HDCS_ROWEXPL;
0216         exp[3] = rowexp & 0xff;
0217         exp[4] = HDCS_ROWEXPH;
0218         exp[5] = rowexp >> 8;
0219         exp[6] = HDCS20_SROWEXP;
0220         exp[7] = (srowexp >> 2) & 0xff;
0221         exp[8] = HDCS20_ERROR;
0222         exp[9] = 0x10;      /* Clear exposure error flag*/
0223         exp[10] = HDCS20_CONTROL;
0224         exp[11] = 0x04;     /* Restart streaming */
0225         err = stv06xx_write_sensor_bytes(sd, exp, 6);
0226     } else {
0227         exp[0] = HDCS00_CONTROL;
0228         exp[1] = 0x00;         /* Stop streaming */
0229         exp[2] = HDCS_ROWEXPL;
0230         exp[3] = rowexp & 0xff;
0231         exp[4] = HDCS_ROWEXPH;
0232         exp[5] = rowexp >> 8;
0233         exp[6] = HDCS00_SROWEXPL;
0234         exp[7] = srowexp & 0xff;
0235         exp[8] = HDCS00_SROWEXPH;
0236         exp[9] = srowexp >> 8;
0237         exp[10] = HDCS_STATUS;
0238         exp[11] = 0x10;         /* Clear exposure error flag*/
0239         exp[12] = HDCS00_CONTROL;
0240         exp[13] = 0x04;         /* Restart streaming */
0241         err = stv06xx_write_sensor_bytes(sd, exp, 7);
0242         if (err < 0)
0243             return err;
0244     }
0245     gspca_dbg(gspca_dev, D_CONF, "Writing exposure %d, rowexp %d, srowexp %d\n",
0246           val, rowexp, srowexp);
0247     return err;
0248 }
0249 
0250 static int hdcs_set_gains(struct sd *sd, u8 g)
0251 {
0252     int err;
0253     u8 gains[4];
0254 
0255     /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */
0256     if (g > 127)
0257         g = 0x80 | (g / 2);
0258 
0259     gains[0] = g;
0260     gains[1] = g;
0261     gains[2] = g;
0262     gains[3] = g;
0263 
0264     err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4);
0265     return err;
0266 }
0267 
0268 static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
0269 {
0270     gspca_dbg(gspca_dev, D_CONF, "Writing gain %d\n", val);
0271     return hdcs_set_gains((struct sd *) gspca_dev,
0272                    val & 0xff);
0273 }
0274 
0275 static int hdcs_set_size(struct sd *sd,
0276         unsigned int width, unsigned int height)
0277 {
0278     struct hdcs *hdcs = sd->sensor_priv;
0279     u8 win[4];
0280     unsigned int x, y;
0281     int err;
0282 
0283     /* must be multiple of 4 */
0284     width = (width + 3) & ~0x3;
0285     height = (height + 3) & ~0x3;
0286 
0287     if (width > hdcs->array.width)
0288         width = hdcs->array.width;
0289 
0290     if (IS_1020(sd)) {
0291         /* the borders are also invalid */
0292         if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP
0293                   > hdcs->array.height)
0294             height = hdcs->array.height - 2 * hdcs->array.border -
0295                 HDCS_1020_BOTTOM_Y_SKIP;
0296 
0297         y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2
0298                 + hdcs->array.top;
0299     } else {
0300         if (height > hdcs->array.height)
0301             height = hdcs->array.height;
0302 
0303         y = hdcs->array.top + (hdcs->array.height - height) / 2;
0304     }
0305 
0306     x = hdcs->array.left + (hdcs->array.width - width) / 2;
0307 
0308     win[0] = y / 4;
0309     win[1] = x / 4;
0310     win[2] = (y + height) / 4 - 1;
0311     win[3] = (x + width) / 4 - 1;
0312 
0313     err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4);
0314     if (err < 0)
0315         return err;
0316 
0317     /* Update the current width and height */
0318     hdcs->w = width;
0319     hdcs->h = height;
0320     return err;
0321 }
0322 
0323 static int hdcs_s_ctrl(struct v4l2_ctrl *ctrl)
0324 {
0325     struct gspca_dev *gspca_dev =
0326         container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0327     int err = -EINVAL;
0328 
0329     switch (ctrl->id) {
0330     case V4L2_CID_GAIN:
0331         err = hdcs_set_gain(gspca_dev, ctrl->val);
0332         break;
0333     case V4L2_CID_EXPOSURE:
0334         err = hdcs_set_exposure(gspca_dev, ctrl->val);
0335         break;
0336     }
0337     return err;
0338 }
0339 
0340 static const struct v4l2_ctrl_ops hdcs_ctrl_ops = {
0341     .s_ctrl = hdcs_s_ctrl,
0342 };
0343 
0344 static int hdcs_init_controls(struct sd *sd)
0345 {
0346     struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
0347 
0348     v4l2_ctrl_handler_init(hdl, 2);
0349     v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops,
0350             V4L2_CID_EXPOSURE, 0, 0xff, 1, HDCS_DEFAULT_EXPOSURE);
0351     v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops,
0352             V4L2_CID_GAIN, 0, 0xff, 1, HDCS_DEFAULT_GAIN);
0353     return hdl->error;
0354 }
0355 
0356 static int hdcs_probe_1x00(struct sd *sd)
0357 {
0358     struct hdcs *hdcs;
0359     u16 sensor;
0360     int ret;
0361 
0362     ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
0363     if (ret < 0 || sensor != 0x08)
0364         return -ENODEV;
0365 
0366     pr_info("HDCS-1000/1100 sensor detected\n");
0367 
0368     sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
0369     sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
0370 
0371     hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
0372     if (!hdcs)
0373         return -ENOMEM;
0374 
0375     hdcs->array.left = 8;
0376     hdcs->array.top = 8;
0377     hdcs->array.width = HDCS_1X00_DEF_WIDTH;
0378     hdcs->array.height = HDCS_1X00_DEF_HEIGHT;
0379     hdcs->array.border = 4;
0380 
0381     hdcs->exp.cto = 4;
0382     hdcs->exp.cpo = 2;
0383     hdcs->exp.rs = 186;
0384     hdcs->exp.er = 100;
0385 
0386     /*
0387      * Frame rate on HDCS-1000 with STV600 depends on PSMP:
0388      *  4 = doesn't work at all
0389      *  5 = 7.8 fps,
0390      *  6 = 6.9 fps,
0391      *  8 = 6.3 fps,
0392      * 10 = 5.5 fps,
0393      * 15 = 4.4 fps,
0394      * 31 = 2.8 fps
0395      *
0396      * Frame rate on HDCS-1000 with STV602 depends on PSMP:
0397      * 15 = doesn't work at all
0398      * 18 = doesn't work at all
0399      * 19 = 7.3 fps
0400      * 20 = 7.4 fps
0401      * 21 = 7.4 fps
0402      * 22 = 7.4 fps
0403      * 24 = 6.3 fps
0404      * 30 = 5.4 fps
0405      */
0406     hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
0407 
0408     sd->sensor_priv = hdcs;
0409 
0410     return 0;
0411 }
0412 
0413 static int hdcs_probe_1020(struct sd *sd)
0414 {
0415     struct hdcs *hdcs;
0416     u16 sensor;
0417     int ret;
0418 
0419     ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
0420     if (ret < 0 || sensor != 0x10)
0421         return -ENODEV;
0422 
0423     pr_info("HDCS-1020 sensor detected\n");
0424 
0425     sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
0426     sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
0427 
0428     hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
0429     if (!hdcs)
0430         return -ENOMEM;
0431 
0432     /*
0433      * From Andrey's test image: looks like HDCS-1020 upper-left
0434      * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
0435      * visible pixel at 375,299 (x maybe even larger?)
0436      */
0437     hdcs->array.left = 24;
0438     hdcs->array.top  = 4;
0439     hdcs->array.width = HDCS_1020_DEF_WIDTH;
0440     hdcs->array.height = 304;
0441     hdcs->array.border = 4;
0442 
0443     hdcs->psmp = 6;
0444 
0445     hdcs->exp.cto = 3;
0446     hdcs->exp.cpo = 3;
0447     hdcs->exp.rs = 155;
0448     hdcs->exp.er = 96;
0449 
0450     sd->sensor_priv = hdcs;
0451 
0452     return 0;
0453 }
0454 
0455 static int hdcs_start(struct sd *sd)
0456 {
0457     struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
0458 
0459     gspca_dbg(gspca_dev, D_STREAM, "Starting stream\n");
0460 
0461     return hdcs_set_state(sd, HDCS_STATE_RUN);
0462 }
0463 
0464 static int hdcs_stop(struct sd *sd)
0465 {
0466     struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
0467 
0468     gspca_dbg(gspca_dev, D_STREAM, "Halting stream\n");
0469 
0470     return hdcs_set_state(sd, HDCS_STATE_SLEEP);
0471 }
0472 
0473 static int hdcs_init(struct sd *sd)
0474 {
0475     struct hdcs *hdcs = sd->sensor_priv;
0476     int i, err = 0;
0477 
0478     /* Set the STV0602AA in STV0600 emulation mode */
0479     if (sd->bridge == BRIDGE_STV602)
0480         stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
0481 
0482     /* Execute the bridge init */
0483     for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) {
0484         err = stv06xx_write_bridge(sd, stv_bridge_init[i][0],
0485                        stv_bridge_init[i][1]);
0486     }
0487     if (err < 0)
0488         return err;
0489 
0490     /* sensor soft reset */
0491     hdcs_reset(sd);
0492 
0493     /* Execute the sensor init */
0494     for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) {
0495         err = stv06xx_write_sensor(sd, stv_sensor_init[i][0],
0496                          stv_sensor_init[i][1]);
0497     }
0498     if (err < 0)
0499         return err;
0500 
0501     /* Enable continuous frame capture, bit 2: stop when frame complete */
0502     err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
0503     if (err < 0)
0504         return err;
0505 
0506     /* Set PGA sample duration
0507     (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
0508     if (IS_1020(sd))
0509         err = stv06xx_write_sensor(sd, HDCS_TCTRL,
0510                 (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
0511     else
0512         err = stv06xx_write_sensor(sd, HDCS_TCTRL,
0513                 (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp);
0514     if (err < 0)
0515         return err;
0516 
0517     return hdcs_set_size(sd, hdcs->array.width, hdcs->array.height);
0518 }
0519 
0520 static int hdcs_dump(struct sd *sd)
0521 {
0522     u16 reg, val;
0523 
0524     pr_info("Dumping sensor registers:\n");
0525 
0526     for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
0527         stv06xx_read_sensor(sd, reg, &val);
0528         pr_info("reg 0x%02x = 0x%02x\n", reg, val);
0529     }
0530     return 0;
0531 }