1 /***************************************************************************
 
   2  * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera   *
 
   5  * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
 
   6  *                       <medaglia@undl.org.br>                            *
 
   7  *                       http://cadu.homelinux.com:8080/                   *
 
   9  * DAC Magnitude, exposure and green gain controls added by                *
 
  10  * Luca Risolia <luca.risolia@studio.unibo.it>                             *
 
  12  * This program is free software; you can redistribute it and/or modify    *
 
  13  * it under the terms of the GNU General Public License as published by    *
 
  14  * the Free Software Foundation; either version 2 of the License, or       *
 
  15  * (at your option) any later version.                                     *
 
  17  * This program is distributed in the hope that it will be useful,         *
 
  18  * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 
  19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 
  20  * GNU General Public License for more details.                            *
 
  22  * You should have received a copy of the GNU General Public License       *
 
  23  * along with this program; if not, write to the Free Software             *
 
  24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
 
  25  ***************************************************************************/
 
  27 #include <linux/delay.h>
 
  28 #include "sn9c102_sensor.h"
 
  31 static struct sn9c102_sensor pas202bcb;
 
  34 static int pas202bcb_init(struct sn9c102_device* cam)
 
  38         err += sn9c102_write_reg(cam, 0x00, 0x10);
 
  39         err += sn9c102_write_reg(cam, 0x00, 0x11);
 
  40         err += sn9c102_write_reg(cam, 0x00, 0x14);
 
  41         err += sn9c102_write_reg(cam, 0x20, 0x17);
 
  42         err += sn9c102_write_reg(cam, 0x30, 0x19);
 
  43         err += sn9c102_write_reg(cam, 0x09, 0x18);
 
  45         err += sn9c102_i2c_write(cam, 0x02, 0x14);
 
  46         err += sn9c102_i2c_write(cam, 0x03, 0x40);
 
  47         err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
 
  48         err += sn9c102_i2c_write(cam, 0x0e, 0x01);
 
  49         err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
 
  50         err += sn9c102_i2c_write(cam, 0x10, 0x08);
 
  51         err += sn9c102_i2c_write(cam, 0x13, 0x63);
 
  52         err += sn9c102_i2c_write(cam, 0x15, 0x70);
 
  53         err += sn9c102_i2c_write(cam, 0x11, 0x01);
 
  61 static int pas202bcb_get_ctrl(struct sn9c102_device* cam, 
 
  62                               struct v4l2_control* ctrl)
 
  65         case V4L2_CID_EXPOSURE:
 
  67                         int r1 = sn9c102_i2c_read(cam, 0x04),
 
  68                             r2 = sn9c102_i2c_read(cam, 0x05);
 
  71                         ctrl->value = (r1 << 6) | (r2 & 0x3f);
 
  74         case V4L2_CID_RED_BALANCE:
 
  75                 if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
 
  79         case V4L2_CID_BLUE_BALANCE:
 
  80                 if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
 
  85                 if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
 
  89         case SN9C102_V4L2_CID_GREEN_BALANCE:
 
  90                 if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
 
  94         case SN9C102_V4L2_CID_DAC_MAGNITUDE:
 
  95                 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
 
 104 static int pas202bcb_set_pix_format(struct sn9c102_device* cam, 
 
 105                                     const struct v4l2_pix_format* pix)
 
 109         if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
 
 110                 err += sn9c102_write_reg(cam, 0x24, 0x17);
 
 112                 err += sn9c102_write_reg(cam, 0x20, 0x17);
 
 118 static int pas202bcb_set_ctrl(struct sn9c102_device* cam, 
 
 119                               const struct v4l2_control* ctrl)
 
 124         case V4L2_CID_EXPOSURE:
 
 125                 err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
 
 126                 err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
 
 128         case V4L2_CID_RED_BALANCE:
 
 129                 err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
 
 131         case V4L2_CID_BLUE_BALANCE:
 
 132                 err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
 
 135                 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
 
 137         case SN9C102_V4L2_CID_GREEN_BALANCE:
 
 138                 err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
 
 140         case SN9C102_V4L2_CID_DAC_MAGNITUDE:
 
 141                 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
 
 146         err += sn9c102_i2c_write(cam, 0x11, 0x01);
 
 148         return err ? -EIO : 0;
 
 152 static int pas202bcb_set_crop(struct sn9c102_device* cam, 
 
 153                               const struct v4l2_rect* rect)
 
 155         struct sn9c102_sensor* s = &pas202bcb;
 
 157         u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
 
 158            v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
 
 160         err += sn9c102_write_reg(cam, h_start, 0x12);
 
 161         err += sn9c102_write_reg(cam, v_start, 0x13);
 
 167 static struct sn9c102_sensor pas202bcb = {
 
 169         .maintainer = "Carlos Eduardo Medaglia Dyonisio "
 
 170                       "<medaglia@undl.org.br>",
 
 171         .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
 
 172         .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
 
 173         .interface = SN9C102_I2C_2WIRES,
 
 174         .i2c_slave_id = 0x40,
 
 175         .init = &pas202bcb_init,
 
 178                         .id = V4L2_CID_EXPOSURE,
 
 179                         .type = V4L2_CTRL_TYPE_INTEGER,
 
 184                         .default_value = 0x01e5,
 
 189                         .type = V4L2_CTRL_TYPE_INTEGER,
 
 190                         .name = "global gain",
 
 194                         .default_value = 0x0c,
 
 198                         .id = V4L2_CID_RED_BALANCE,
 
 199                         .type = V4L2_CTRL_TYPE_INTEGER,
 
 200                         .name = "red balance",
 
 204                         .default_value = 0x01,
 
 208                         .id = V4L2_CID_BLUE_BALANCE,
 
 209                         .type = V4L2_CTRL_TYPE_INTEGER,
 
 210                         .name = "blue balance",
 
 214                         .default_value = 0x05,
 
 218                         .id = SN9C102_V4L2_CID_GREEN_BALANCE,
 
 219                         .type = V4L2_CTRL_TYPE_INTEGER,
 
 220                         .name = "green balance",
 
 224                         .default_value = 0x00,
 
 228                         .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
 
 229                         .type = V4L2_CTRL_TYPE_INTEGER,
 
 230                         .name = "DAC magnitude",
 
 234                         .default_value = 0x04,
 
 238         .get_ctrl = &pas202bcb_get_ctrl,
 
 239         .set_ctrl = &pas202bcb_set_ctrl,
 
 254         .set_crop = &pas202bcb_set_crop,
 
 258                 .pixelformat = V4L2_PIX_FMT_SBGGR8,
 
 261         .set_pix_format = &pas202bcb_set_pix_format
 
 265 int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
 
 267         int r0 = 0, r1 = 0, err = 0;
 
 268         unsigned int pid = 0;
 
 271          *  Minimal initialization to enable the I2C communication
 
 272          *  NOTE: do NOT change the values!
 
 274         err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
 
 275         err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */
 
 276         err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
 
 280         r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
 
 281         r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
 
 283         if (r0 < 0 || r1 < 0)
 
 286         pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
 
 290         sn9c102_attach_sensor(cam, &pas202bcb);