root/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vv6410_s_ctrl
  2. vv6410_probe
  3. vv6410_init_controls
  4. vv6410_init
  5. vv6410_start
  6. vv6410_stop
  7. vv6410_dump
  8. vv6410_set_hflip
  9. vv6410_set_vflip
  10. vv6410_set_analog_gain
  11. vv6410_set_exposure

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
   4  *                    Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
   5  * Copyright (c) 2002, 2003 Tuukka Toivonen
   6  * Copyright (c) 2008 Erik Andrén
   7  *
   8  * P/N 861037:      Sensor HDCS1000        ASIC STV0600
   9  * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
  10  * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
  11  * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
  12  * P/N 861075-0040: Sensor HDCS1000        ASIC
  13  * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
  14  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
  15  */
  16 
  17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  18 
  19 #include "stv06xx_vv6410.h"
  20 
  21 static struct v4l2_pix_format vv6410_mode[] = {
  22         {
  23                 356,
  24                 292,
  25                 V4L2_PIX_FMT_SGRBG8,
  26                 V4L2_FIELD_NONE,
  27                 .sizeimage = 356 * 292,
  28                 .bytesperline = 356,
  29                 .colorspace = V4L2_COLORSPACE_SRGB,
  30                 .priv = 0
  31         }
  32 };
  33 
  34 static int vv6410_s_ctrl(struct v4l2_ctrl *ctrl)
  35 {
  36         struct gspca_dev *gspca_dev =
  37                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
  38         int err = -EINVAL;
  39 
  40         switch (ctrl->id) {
  41         case V4L2_CID_HFLIP:
  42                 if (!gspca_dev->streaming)
  43                         return 0;
  44                 err = vv6410_set_hflip(gspca_dev, ctrl->val);
  45                 break;
  46         case V4L2_CID_VFLIP:
  47                 if (!gspca_dev->streaming)
  48                         return 0;
  49                 err = vv6410_set_vflip(gspca_dev, ctrl->val);
  50                 break;
  51         case V4L2_CID_GAIN:
  52                 err = vv6410_set_analog_gain(gspca_dev, ctrl->val);
  53                 break;
  54         case V4L2_CID_EXPOSURE:
  55                 err = vv6410_set_exposure(gspca_dev, ctrl->val);
  56                 break;
  57         }
  58         return err;
  59 }
  60 
  61 static const struct v4l2_ctrl_ops vv6410_ctrl_ops = {
  62         .s_ctrl = vv6410_s_ctrl,
  63 };
  64 
  65 static int vv6410_probe(struct sd *sd)
  66 {
  67         u16 data;
  68         int err;
  69 
  70         err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
  71         if (err < 0)
  72                 return -ENODEV;
  73 
  74         if (data != 0x19)
  75                 return -ENODEV;
  76 
  77         pr_info("vv6410 sensor detected\n");
  78 
  79         sd->gspca_dev.cam.cam_mode = vv6410_mode;
  80         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode);
  81         return 0;
  82 }
  83 
  84 static int vv6410_init_controls(struct sd *sd)
  85 {
  86         struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
  87 
  88         v4l2_ctrl_handler_init(hdl, 2);
  89         /* Disable the hardware VFLIP and HFLIP as we currently lack a
  90            mechanism to adjust the image offset in such a way that
  91            we don't need to renegotiate the announced format */
  92         /* v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, */
  93         /*              V4L2_CID_HFLIP, 0, 1, 1, 0); */
  94         /* v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, */
  95         /*              V4L2_CID_VFLIP, 0, 1, 1, 0); */
  96         v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
  97                         V4L2_CID_EXPOSURE, 0, 32768, 1, 20000);
  98         v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
  99                         V4L2_CID_GAIN, 0, 15, 1, 10);
 100         return hdl->error;
 101 }
 102 
 103 static int vv6410_init(struct sd *sd)
 104 {
 105         int err = 0, i;
 106 
 107         for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++)
 108                 stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
 109 
 110         err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
 111                                          ARRAY_SIZE(vv6410_sensor_init));
 112         return (err < 0) ? err : 0;
 113 }
 114 
 115 static int vv6410_start(struct sd *sd)
 116 {
 117         int err;
 118         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 119         struct cam *cam = &sd->gspca_dev.cam;
 120         u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 121 
 122         if (priv & VV6410_SUBSAMPLE) {
 123                 gspca_dbg(gspca_dev, D_CONF, "Enabling subsampling\n");
 124                 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
 125                 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
 126 
 127                 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
 128         } else {
 129                 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
 130                 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
 131                 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
 132 
 133         }
 134 
 135         /* Turn on LED */
 136         err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
 137         if (err < 0)
 138                 return err;
 139 
 140         err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0);
 141         if (err < 0)
 142                 return err;
 143 
 144         gspca_dbg(gspca_dev, D_STREAM, "Starting stream\n");
 145 
 146         return 0;
 147 }
 148 
 149 static int vv6410_stop(struct sd *sd)
 150 {
 151         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 152         int err;
 153 
 154         /* Turn off LED */
 155         err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
 156         if (err < 0)
 157                 return err;
 158 
 159         err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE);
 160         if (err < 0)
 161                 return err;
 162 
 163         gspca_dbg(gspca_dev, D_STREAM, "Halting stream\n");
 164 
 165         return 0;
 166 }
 167 
 168 static int vv6410_dump(struct sd *sd)
 169 {
 170         u8 i;
 171         int err = 0;
 172 
 173         pr_info("Dumping all vv6410 sensor registers\n");
 174         for (i = 0; i < 0xff && !err; i++) {
 175                 u16 data;
 176                 err = stv06xx_read_sensor(sd, i, &data);
 177                 pr_info("Register 0x%x contained 0x%x\n", i, data);
 178         }
 179         return (err < 0) ? err : 0;
 180 }
 181 
 182 static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 183 {
 184         int err;
 185         u16 i2c_data;
 186         struct sd *sd = (struct sd *) gspca_dev;
 187 
 188         err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
 189         if (err < 0)
 190                 return err;
 191 
 192         if (val)
 193                 i2c_data |= VV6410_HFLIP;
 194         else
 195                 i2c_data &= ~VV6410_HFLIP;
 196 
 197         gspca_dbg(gspca_dev, D_CONF, "Set horizontal flip to %d\n", val);
 198         err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
 199 
 200         return (err < 0) ? err : 0;
 201 }
 202 
 203 static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 204 {
 205         int err;
 206         u16 i2c_data;
 207         struct sd *sd = (struct sd *) gspca_dev;
 208 
 209         err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
 210         if (err < 0)
 211                 return err;
 212 
 213         if (val)
 214                 i2c_data |= VV6410_VFLIP;
 215         else
 216                 i2c_data &= ~VV6410_VFLIP;
 217 
 218         gspca_dbg(gspca_dev, D_CONF, "Set vertical flip to %d\n", val);
 219         err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
 220 
 221         return (err < 0) ? err : 0;
 222 }
 223 
 224 static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
 225 {
 226         int err;
 227         struct sd *sd = (struct sd *) gspca_dev;
 228 
 229         gspca_dbg(gspca_dev, D_CONF, "Set analog gain to %d\n", val);
 230         err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
 231 
 232         return (err < 0) ? err : 0;
 233 }
 234 
 235 static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 236 {
 237         int err;
 238         struct sd *sd = (struct sd *) gspca_dev;
 239         unsigned int fine, coarse;
 240 
 241         val = (val * val >> 14) + val / 4;
 242 
 243         fine = val % VV6410_CIF_LINELENGTH;
 244         coarse = min(512, val / VV6410_CIF_LINELENGTH);
 245 
 246         gspca_dbg(gspca_dev, D_CONF, "Set coarse exposure to %d, fine exposure to %d\n",
 247                   coarse, fine);
 248 
 249         err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
 250         if (err < 0)
 251                 goto out;
 252 
 253         err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
 254         if (err < 0)
 255                 goto out;
 256 
 257         err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
 258         if (err < 0)
 259                 goto out;
 260 
 261         err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
 262 
 263 out:
 264         return err;
 265 }

/* [<][>][^][v][top][bottom][index][help] */