linux/drivers/media/video/zc0301/zc0301_pas202bcb.c
<<
>>
Prefs
   1/***************************************************************************
   2 * Plug-in for PAS202BCB image sensor connected to the ZC0301 Image        *
   3 * Processor and Control Chip                                              *
   4 *                                                                         *
   5 * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
   6 *                                                                         *
   7 * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
   8 * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
   9 *                                                                         *
  10 * This program is free software; you can redistribute it and/or modify    *
  11 * it under the terms of the GNU General Public License as published by    *
  12 * the Free Software Foundation; either version 2 of the License, or       *
  13 * (at your option) any later version.                                     *
  14 *                                                                         *
  15 * This program is distributed in the hope that it will be useful,         *
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
  18 * GNU General Public License for more details.                            *
  19 *                                                                         *
  20 * You should have received a copy of the GNU General Public License       *
  21 * along with this program; if not, write to the Free Software             *
  22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  23 ***************************************************************************/
  24
  25/*
  26   NOTE: Sensor controls are disabled for now, becouse changing them while
  27         streaming sometimes results in out-of-sync video frames. We'll use
  28         the default initialization, until we know how to stop and start video
  29         in the chip. However, the image quality still looks good under various
  30         light conditions.
  31*/
  32
  33#include <linux/delay.h>
  34#include "zc0301_sensor.h"
  35
  36
  37static struct zc0301_sensor pas202bcb;
  38
  39
  40static int pas202bcb_init(struct zc0301_device* cam)
  41{
  42        int err = 0;
  43
  44        err += zc0301_write_reg(cam, 0x0002, 0x00);
  45        err += zc0301_write_reg(cam, 0x0003, 0x02);
  46        err += zc0301_write_reg(cam, 0x0004, 0x80);
  47        err += zc0301_write_reg(cam, 0x0005, 0x01);
  48        err += zc0301_write_reg(cam, 0x0006, 0xE0);
  49        err += zc0301_write_reg(cam, 0x0098, 0x00);
  50        err += zc0301_write_reg(cam, 0x009A, 0x03);
  51        err += zc0301_write_reg(cam, 0x011A, 0x00);
  52        err += zc0301_write_reg(cam, 0x011C, 0x03);
  53        err += zc0301_write_reg(cam, 0x009B, 0x01);
  54        err += zc0301_write_reg(cam, 0x009C, 0xE6);
  55        err += zc0301_write_reg(cam, 0x009D, 0x02);
  56        err += zc0301_write_reg(cam, 0x009E, 0x86);
  57
  58        err += zc0301_i2c_write(cam, 0x02, 0x02);
  59        err += zc0301_i2c_write(cam, 0x0A, 0x01);
  60        err += zc0301_i2c_write(cam, 0x0B, 0x01);
  61        err += zc0301_i2c_write(cam, 0x0D, 0x00);
  62        err += zc0301_i2c_write(cam, 0x12, 0x05);
  63        err += zc0301_i2c_write(cam, 0x13, 0x63);
  64        err += zc0301_i2c_write(cam, 0x15, 0x70);
  65
  66        err += zc0301_write_reg(cam, 0x0101, 0xB7);
  67        err += zc0301_write_reg(cam, 0x0100, 0x0D);
  68        err += zc0301_write_reg(cam, 0x0189, 0x06);
  69        err += zc0301_write_reg(cam, 0x01AD, 0x00);
  70        err += zc0301_write_reg(cam, 0x01C5, 0x03);
  71        err += zc0301_write_reg(cam, 0x01CB, 0x13);
  72        err += zc0301_write_reg(cam, 0x0250, 0x08);
  73        err += zc0301_write_reg(cam, 0x0301, 0x08);
  74        err += zc0301_write_reg(cam, 0x018D, 0x70);
  75        err += zc0301_write_reg(cam, 0x0008, 0x03);
  76        err += zc0301_write_reg(cam, 0x01C6, 0x04);
  77        err += zc0301_write_reg(cam, 0x01CB, 0x07);
  78        err += zc0301_write_reg(cam, 0x0120, 0x11);
  79        err += zc0301_write_reg(cam, 0x0121, 0x37);
  80        err += zc0301_write_reg(cam, 0x0122, 0x58);
  81        err += zc0301_write_reg(cam, 0x0123, 0x79);
  82        err += zc0301_write_reg(cam, 0x0124, 0x91);
  83        err += zc0301_write_reg(cam, 0x0125, 0xA6);
  84        err += zc0301_write_reg(cam, 0x0126, 0xB8);
  85        err += zc0301_write_reg(cam, 0x0127, 0xC7);
  86        err += zc0301_write_reg(cam, 0x0128, 0xD3);
  87        err += zc0301_write_reg(cam, 0x0129, 0xDE);
  88        err += zc0301_write_reg(cam, 0x012A, 0xE6);
  89        err += zc0301_write_reg(cam, 0x012B, 0xED);
  90        err += zc0301_write_reg(cam, 0x012C, 0xF3);
  91        err += zc0301_write_reg(cam, 0x012D, 0xF8);
  92        err += zc0301_write_reg(cam, 0x012E, 0xFB);
  93        err += zc0301_write_reg(cam, 0x012F, 0xFF);
  94        err += zc0301_write_reg(cam, 0x0130, 0x26);
  95        err += zc0301_write_reg(cam, 0x0131, 0x23);
  96        err += zc0301_write_reg(cam, 0x0132, 0x20);
  97        err += zc0301_write_reg(cam, 0x0133, 0x1C);
  98        err += zc0301_write_reg(cam, 0x0134, 0x16);
  99        err += zc0301_write_reg(cam, 0x0135, 0x13);
 100        err += zc0301_write_reg(cam, 0x0136, 0x10);
 101        err += zc0301_write_reg(cam, 0x0137, 0x0D);
 102        err += zc0301_write_reg(cam, 0x0138, 0x0B);
 103        err += zc0301_write_reg(cam, 0x0139, 0x09);
 104        err += zc0301_write_reg(cam, 0x013A, 0x07);
 105        err += zc0301_write_reg(cam, 0x013B, 0x06);
 106        err += zc0301_write_reg(cam, 0x013C, 0x05);
 107        err += zc0301_write_reg(cam, 0x013D, 0x04);
 108        err += zc0301_write_reg(cam, 0x013E, 0x03);
 109        err += zc0301_write_reg(cam, 0x013F, 0x02);
 110        err += zc0301_write_reg(cam, 0x010A, 0x4C);
 111        err += zc0301_write_reg(cam, 0x010B, 0xF5);
 112        err += zc0301_write_reg(cam, 0x010C, 0xFF);
 113        err += zc0301_write_reg(cam, 0x010D, 0xF9);
 114        err += zc0301_write_reg(cam, 0x010E, 0x51);
 115        err += zc0301_write_reg(cam, 0x010F, 0xF5);
 116        err += zc0301_write_reg(cam, 0x0110, 0xFB);
 117        err += zc0301_write_reg(cam, 0x0111, 0xED);
 118        err += zc0301_write_reg(cam, 0x0112, 0x5F);
 119        err += zc0301_write_reg(cam, 0x0180, 0x00);
 120        err += zc0301_write_reg(cam, 0x0019, 0x00);
 121        err += zc0301_write_reg(cam, 0x0087, 0x20);
 122        err += zc0301_write_reg(cam, 0x0088, 0x21);
 123
 124        err += zc0301_i2c_write(cam, 0x20, 0x02);
 125        err += zc0301_i2c_write(cam, 0x21, 0x1B);
 126        err += zc0301_i2c_write(cam, 0x03, 0x44);
 127        err += zc0301_i2c_write(cam, 0x0E, 0x01);
 128        err += zc0301_i2c_write(cam, 0x0F, 0x00);
 129
 130        err += zc0301_write_reg(cam, 0x01A9, 0x14);
 131        err += zc0301_write_reg(cam, 0x01AA, 0x24);
 132        err += zc0301_write_reg(cam, 0x0190, 0x00);
 133        err += zc0301_write_reg(cam, 0x0191, 0x02);
 134        err += zc0301_write_reg(cam, 0x0192, 0x1B);
 135        err += zc0301_write_reg(cam, 0x0195, 0x00);
 136        err += zc0301_write_reg(cam, 0x0196, 0x00);
 137        err += zc0301_write_reg(cam, 0x0197, 0x4D);
 138        err += zc0301_write_reg(cam, 0x018C, 0x10);
 139        err += zc0301_write_reg(cam, 0x018F, 0x20);
 140        err += zc0301_write_reg(cam, 0x001D, 0x44);
 141        err += zc0301_write_reg(cam, 0x001E, 0x6F);
 142        err += zc0301_write_reg(cam, 0x001F, 0xAD);
 143        err += zc0301_write_reg(cam, 0x0020, 0xEB);
 144        err += zc0301_write_reg(cam, 0x0087, 0x0F);
 145        err += zc0301_write_reg(cam, 0x0088, 0x0E);
 146        err += zc0301_write_reg(cam, 0x0180, 0x40);
 147        err += zc0301_write_reg(cam, 0x0192, 0x1B);
 148        err += zc0301_write_reg(cam, 0x0191, 0x02);
 149        err += zc0301_write_reg(cam, 0x0190, 0x00);
 150        err += zc0301_write_reg(cam, 0x0116, 0x1D);
 151        err += zc0301_write_reg(cam, 0x0117, 0x40);
 152        err += zc0301_write_reg(cam, 0x0118, 0x99);
 153        err += zc0301_write_reg(cam, 0x0180, 0x42);
 154        err += zc0301_write_reg(cam, 0x0116, 0x1D);
 155        err += zc0301_write_reg(cam, 0x0117, 0x40);
 156        err += zc0301_write_reg(cam, 0x0118, 0x99);
 157        err += zc0301_write_reg(cam, 0x0007, 0x00);
 158
 159        err += zc0301_i2c_write(cam, 0x11, 0x01);
 160
 161        msleep(100);
 162
 163        return err;
 164}
 165
 166
 167static int pas202bcb_get_ctrl(struct zc0301_device* cam,
 168                              struct v4l2_control* ctrl)
 169{
 170        switch (ctrl->id) {
 171        case V4L2_CID_EXPOSURE:
 172                {
 173                        int r1 = zc0301_i2c_read(cam, 0x04, 1),
 174                            r2 = zc0301_i2c_read(cam, 0x05, 1);
 175                        if (r1 < 0 || r2 < 0)
 176                                return -EIO;
 177                        ctrl->value = (r1 << 6) | (r2 & 0x3f);
 178                }
 179                return 0;
 180        case V4L2_CID_RED_BALANCE:
 181                if ((ctrl->value = zc0301_i2c_read(cam, 0x09, 1)) < 0)
 182                        return -EIO;
 183                ctrl->value &= 0x0f;
 184                return 0;
 185        case V4L2_CID_BLUE_BALANCE:
 186                if ((ctrl->value = zc0301_i2c_read(cam, 0x07, 1)) < 0)
 187                        return -EIO;
 188                ctrl->value &= 0x0f;
 189                return 0;
 190        case V4L2_CID_GAIN:
 191                if ((ctrl->value = zc0301_i2c_read(cam, 0x10, 1)) < 0)
 192                        return -EIO;
 193                ctrl->value &= 0x1f;
 194                return 0;
 195        case ZC0301_V4L2_CID_GREEN_BALANCE:
 196                if ((ctrl->value = zc0301_i2c_read(cam, 0x08, 1)) < 0)
 197                        return -EIO;
 198                ctrl->value &= 0x0f;
 199                return 0;
 200        case ZC0301_V4L2_CID_DAC_MAGNITUDE:
 201                if ((ctrl->value = zc0301_i2c_read(cam, 0x0c, 1)) < 0)
 202                        return -EIO;
 203                return 0;
 204        default:
 205                return -EINVAL;
 206        }
 207}
 208
 209
 210static int pas202bcb_set_ctrl(struct zc0301_device* cam,
 211                              const struct v4l2_control* ctrl)
 212{
 213        int err = 0;
 214
 215        switch (ctrl->id) {
 216        case V4L2_CID_EXPOSURE:
 217                err += zc0301_i2c_write(cam, 0x04, ctrl->value >> 6);
 218                err += zc0301_i2c_write(cam, 0x05, ctrl->value & 0x3f);
 219                break;
 220        case V4L2_CID_RED_BALANCE:
 221                err += zc0301_i2c_write(cam, 0x09, ctrl->value);
 222                break;
 223        case V4L2_CID_BLUE_BALANCE:
 224                err += zc0301_i2c_write(cam, 0x07, ctrl->value);
 225                break;
 226        case V4L2_CID_GAIN:
 227                err += zc0301_i2c_write(cam, 0x10, ctrl->value);
 228                break;
 229        case ZC0301_V4L2_CID_GREEN_BALANCE:
 230                err += zc0301_i2c_write(cam, 0x08, ctrl->value);
 231                break;
 232        case ZC0301_V4L2_CID_DAC_MAGNITUDE:
 233                err += zc0301_i2c_write(cam, 0x0c, ctrl->value);
 234                break;
 235        default:
 236                return -EINVAL;
 237        }
 238        err += zc0301_i2c_write(cam, 0x11, 0x01);
 239
 240        return err ? -EIO : 0;
 241}
 242
 243
 244static struct zc0301_sensor pas202bcb = {
 245        .name = "PAS202BCB",
 246        .init = &pas202bcb_init,
 247        .qctrl = {
 248                {
 249                        .id = V4L2_CID_EXPOSURE,
 250                        .type = V4L2_CTRL_TYPE_INTEGER,
 251                        .name = "exposure",
 252                        .minimum = 0x01e5,
 253                        .maximum = 0x3fff,
 254                        .step = 0x0001,
 255                        .default_value = 0x01e5,
 256                        .flags = V4L2_CTRL_FLAG_DISABLED,
 257                },
 258                {
 259                        .id = V4L2_CID_GAIN,
 260                        .type = V4L2_CTRL_TYPE_INTEGER,
 261                        .name = "global gain",
 262                        .minimum = 0x00,
 263                        .maximum = 0x1f,
 264                        .step = 0x01,
 265                        .default_value = 0x0c,
 266                        .flags = V4L2_CTRL_FLAG_DISABLED,
 267                },
 268                {
 269                        .id = ZC0301_V4L2_CID_DAC_MAGNITUDE,
 270                        .type = V4L2_CTRL_TYPE_INTEGER,
 271                        .name = "DAC magnitude",
 272                        .minimum = 0x00,
 273                        .maximum = 0xff,
 274                        .step = 0x01,
 275                        .default_value = 0x00,
 276                        .flags = V4L2_CTRL_FLAG_DISABLED,
 277                },
 278                {
 279                        .id = V4L2_CID_RED_BALANCE,
 280                        .type = V4L2_CTRL_TYPE_INTEGER,
 281                        .name = "red balance",
 282                        .minimum = 0x00,
 283                        .maximum = 0x0f,
 284                        .step = 0x01,
 285                        .default_value = 0x01,
 286                        .flags = V4L2_CTRL_FLAG_DISABLED,
 287                },
 288                {
 289                        .id = V4L2_CID_BLUE_BALANCE,
 290                        .type = V4L2_CTRL_TYPE_INTEGER,
 291                        .name = "blue balance",
 292                        .minimum = 0x00,
 293                        .maximum = 0x0f,
 294                        .step = 0x01,
 295                        .default_value = 0x05,
 296                        .flags = V4L2_CTRL_FLAG_DISABLED,
 297                },
 298                {
 299                        .id = ZC0301_V4L2_CID_GREEN_BALANCE,
 300                        .type = V4L2_CTRL_TYPE_INTEGER,
 301                        .name = "green balance",
 302                        .minimum = 0x00,
 303                        .maximum = 0x0f,
 304                        .step = 0x01,
 305                        .default_value = 0x00,
 306                        .flags = V4L2_CTRL_FLAG_DISABLED,
 307                },
 308        },
 309        .get_ctrl = &pas202bcb_get_ctrl,
 310        .set_ctrl = &pas202bcb_set_ctrl,
 311        .cropcap = {
 312                .bounds = {
 313                        .left = 0,
 314                        .top = 0,
 315                        .width = 640,
 316                        .height = 480,
 317                },
 318                .defrect = {
 319                        .left = 0,
 320                        .top = 0,
 321                        .width = 640,
 322                        .height = 480,
 323                },
 324        },
 325        .pix_format = {
 326                .width = 640,
 327                .height = 480,
 328                .pixelformat = V4L2_PIX_FMT_JPEG,
 329                .priv = 8,
 330                .colorspace = V4L2_COLORSPACE_JPEG,
 331        },
 332};
 333
 334
 335int zc0301_probe_pas202bcb(struct zc0301_device* cam)
 336{
 337        int r0 = 0, r1 = 0, err = 0;
 338        unsigned int pid = 0;
 339
 340        err += zc0301_write_reg(cam, 0x0000, 0x01);
 341        err += zc0301_write_reg(cam, 0x0010, 0x0e);
 342        err += zc0301_write_reg(cam, 0x0001, 0x01);
 343        err += zc0301_write_reg(cam, 0x0012, 0x03);
 344        err += zc0301_write_reg(cam, 0x0012, 0x01);
 345        err += zc0301_write_reg(cam, 0x008d, 0x08);
 346
 347        msleep(10);
 348
 349        r0 = zc0301_i2c_read(cam, 0x00, 1);
 350        r1 = zc0301_i2c_read(cam, 0x01, 1);
 351
 352        if (r0 < 0 || r1 < 0 || err)
 353                return -EIO;
 354
 355        pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
 356        if (pid != 0x017)
 357                return -ENODEV;
 358
 359        zc0301_attach_sensor(cam, &pas202bcb);
 360
 361        return 0;
 362}
 363