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

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

DEFINITIONS

This source file includes following definitions.
  1. st6422_s_ctrl
  2. st6422_init_controls
  3. st6422_probe
  4. st6422_init
  5. setbrightness
  6. setcontrast
  7. setgain
  8. setexposure
  9. st6422_start
  10. st6422_stop

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Support for the sensor part which is integrated (I think) into the
   4  * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
   5  * but instead direct bridge writes.
   6  *
   7  * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
   8  *
   9  * Strongly based on qc-usb-messenger, which is:
  10  * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
  11  *                    Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
  12  * Copyright (c) 2002, 2003 Tuukka Toivonen
  13  */
  14 
  15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  16 
  17 #include "stv06xx_st6422.h"
  18 
  19 static struct v4l2_pix_format st6422_mode[] = {
  20         /* Note we actually get 124 lines of data, of which we skip the 4st
  21            4 as they are garbage */
  22         {
  23                 162,
  24                 120,
  25                 V4L2_PIX_FMT_SGRBG8,
  26                 V4L2_FIELD_NONE,
  27                 .sizeimage = 162 * 120,
  28                 .bytesperline = 162,
  29                 .colorspace = V4L2_COLORSPACE_SRGB,
  30                 .priv = 1
  31         },
  32         /* Note we actually get 248 lines of data, of which we skip the 4st
  33            4 as they are garbage, and we tell the app it only gets the
  34            first 240 of the 244 lines it actually gets, so that it ignores
  35            the last 4. */
  36         {
  37                 324,
  38                 240,
  39                 V4L2_PIX_FMT_SGRBG8,
  40                 V4L2_FIELD_NONE,
  41                 .sizeimage = 324 * 244,
  42                 .bytesperline = 324,
  43                 .colorspace = V4L2_COLORSPACE_SRGB,
  44                 .priv = 0
  45         },
  46 };
  47 
  48 /* V4L2 controls supported by the driver */
  49 static int setbrightness(struct sd *sd, s32 val);
  50 static int setcontrast(struct sd *sd, s32 val);
  51 static int setgain(struct sd *sd, u8 gain);
  52 static int setexposure(struct sd *sd, s16 expo);
  53 
  54 static int st6422_s_ctrl(struct v4l2_ctrl *ctrl)
  55 {
  56         struct gspca_dev *gspca_dev =
  57                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
  58         struct sd *sd = (struct sd *)gspca_dev;
  59         int err = -EINVAL;
  60 
  61         switch (ctrl->id) {
  62         case V4L2_CID_BRIGHTNESS:
  63                 err = setbrightness(sd, ctrl->val);
  64                 break;
  65         case V4L2_CID_CONTRAST:
  66                 err = setcontrast(sd, ctrl->val);
  67                 break;
  68         case V4L2_CID_GAIN:
  69                 err = setgain(sd, ctrl->val);
  70                 break;
  71         case V4L2_CID_EXPOSURE:
  72                 err = setexposure(sd, ctrl->val);
  73                 break;
  74         }
  75 
  76         /* commit settings */
  77         if (err >= 0)
  78                 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
  79         sd->gspca_dev.usb_err = err;
  80         return err;
  81 }
  82 
  83 static const struct v4l2_ctrl_ops st6422_ctrl_ops = {
  84         .s_ctrl = st6422_s_ctrl,
  85 };
  86 
  87 static int st6422_init_controls(struct sd *sd)
  88 {
  89         struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
  90 
  91         v4l2_ctrl_handler_init(hdl, 4);
  92         v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
  93                         V4L2_CID_BRIGHTNESS, 0, 31, 1, 3);
  94         v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
  95                         V4L2_CID_CONTRAST, 0, 15, 1, 11);
  96         v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
  97                         V4L2_CID_EXPOSURE, 0, 1023, 1, 256);
  98         v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
  99                         V4L2_CID_GAIN, 0, 255, 1, 64);
 100 
 101         return hdl->error;
 102 }
 103 
 104 static int st6422_probe(struct sd *sd)
 105 {
 106         if (sd->bridge != BRIDGE_ST6422)
 107                 return -ENODEV;
 108 
 109         pr_info("st6422 sensor detected\n");
 110 
 111         sd->gspca_dev.cam.cam_mode = st6422_mode;
 112         sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
 113         return 0;
 114 }
 115 
 116 static int st6422_init(struct sd *sd)
 117 {
 118         int err = 0, i;
 119 
 120         const u16 st6422_bridge_init[][2] = {
 121                 { STV_ISO_ENABLE, 0x00 }, /* disable capture */
 122                 { 0x1436, 0x00 },
 123                 { 0x1432, 0x03 },       /* 0x00-0x1F brightness */
 124                 { 0x143a, 0xf9 },       /* 0x00-0x0F contrast */
 125                 { 0x0509, 0x38 },       /* R */
 126                 { 0x050a, 0x38 },       /* G */
 127                 { 0x050b, 0x38 },       /* B */
 128                 { 0x050c, 0x2a },
 129                 { 0x050d, 0x01 },
 130 
 131 
 132                 { 0x1431, 0x00 },       /* 0x00-0x07 ??? */
 133                 { 0x1433, 0x34 },       /* 160x120, 0x00-0x01 night filter */
 134                 { 0x1438, 0x18 },       /* 640x480 */
 135 /* 18 bayes */
 136 /* 10 compressed? */
 137 
 138                 { 0x1439, 0x00 },
 139 /* anti-noise?  0xa2 gives a perfect image */
 140 
 141                 { 0x143b, 0x05 },
 142                 { 0x143c, 0x00 },       /* 0x00-0x01 - ??? */
 143 
 144 
 145 /* shutter time 0x0000-0x03FF */
 146 /* low value  give good picures on moving objects (but requires much light) */
 147 /* high value gives good picures in darkness (but tends to be overexposed) */
 148                 { 0x143e, 0x01 },
 149                 { 0x143d, 0x00 },
 150 
 151                 { 0x1442, 0xe2 },
 152 /* write: 1x1x xxxx */
 153 /* read:  1x1x xxxx */
 154 /*        bit 5 == button pressed and hold if 0 */
 155 /* write 0xe2,0xea */
 156 
 157 /* 0x144a */
 158 /* 0x00 init */
 159 /* bit 7 == button has been pressed, but not handled */
 160 
 161 /* interrupt */
 162 /* if(urb->iso_frame_desc[i].status == 0x80) { */
 163 /* if(urb->iso_frame_desc[i].status == 0x88) { */
 164 
 165                 { 0x1500, 0xd0 },
 166                 { 0x1500, 0xd0 },
 167                 { 0x1500, 0x50 },       /* 0x00 - 0xFF  0x80 == compr ? */
 168 
 169                 { 0x1501, 0xaf },
 170 /* high val-> light area gets darker */
 171 /* low val -> light area gets lighter */
 172                 { 0x1502, 0xc2 },
 173 /* high val-> light area gets darker */
 174 /* low val -> light area gets lighter */
 175                 { 0x1503, 0x45 },
 176 /* high val-> light area gets darker */
 177 /* low val -> light area gets lighter */
 178                 { 0x1505, 0x02 },
 179 /* 2  : 324x248  80352 bytes */
 180 /* 7  : 248x162  40176 bytes */
 181 /* c+f: 162*124  20088 bytes */
 182 
 183                 { 0x150e, 0x8e },
 184                 { 0x150f, 0x37 },
 185                 { 0x15c0, 0x00 },
 186                 { 0x15c3, 0x08 },       /* 0x04/0x14 ... test pictures ??? */
 187 
 188 
 189                 { 0x143f, 0x01 },       /* commit settings */
 190 
 191         };
 192 
 193         for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
 194                 err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
 195                                                st6422_bridge_init[i][1]);
 196         }
 197 
 198         return err;
 199 }
 200 
 201 static int setbrightness(struct sd *sd, s32 val)
 202 {
 203         /* val goes from 0 -> 31 */
 204         return stv06xx_write_bridge(sd, 0x1432, val);
 205 }
 206 
 207 static int setcontrast(struct sd *sd, s32 val)
 208 {
 209         /* Val goes from 0 -> 15 */
 210         return stv06xx_write_bridge(sd, 0x143a, val | 0xf0);
 211 }
 212 
 213 static int setgain(struct sd *sd, u8 gain)
 214 {
 215         int err;
 216 
 217         /* Set red, green, blue, gain */
 218         err = stv06xx_write_bridge(sd, 0x0509, gain);
 219         if (err < 0)
 220                 return err;
 221 
 222         err = stv06xx_write_bridge(sd, 0x050a, gain);
 223         if (err < 0)
 224                 return err;
 225 
 226         err = stv06xx_write_bridge(sd, 0x050b, gain);
 227         if (err < 0)
 228                 return err;
 229 
 230         /* 2 mystery writes */
 231         err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
 232         if (err < 0)
 233                 return err;
 234 
 235         return stv06xx_write_bridge(sd, 0x050d, 0x01);
 236 }
 237 
 238 static int setexposure(struct sd *sd, s16 expo)
 239 {
 240         int err;
 241 
 242         err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
 243         if (err < 0)
 244                 return err;
 245 
 246         return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
 247 }
 248 
 249 static int st6422_start(struct sd *sd)
 250 {
 251         int err;
 252         struct cam *cam = &sd->gspca_dev.cam;
 253 
 254         if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
 255                 err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
 256         else
 257                 err = stv06xx_write_bridge(sd, 0x1505, 0x02);
 258         if (err < 0)
 259                 return err;
 260 
 261         /* commit settings */
 262         err = stv06xx_write_bridge(sd, 0x143f, 0x01);
 263         return (err < 0) ? err : 0;
 264 }
 265 
 266 static int st6422_stop(struct sd *sd)
 267 {
 268         struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 269 
 270         gspca_dbg(gspca_dev, D_STREAM, "Halting stream\n");
 271 
 272         return 0;
 273 }

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