linux/drivers/media/video/sn9c102/sn9c102_ov7630.c
<<
>>
Prefs
   1/***************************************************************************
   2 * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera      *
   3 * Controllers                                                             *
   4 *                                                                         *
   5 * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
   6 *                                                                         *
   7 * This program is free software; you can redistribute it and/or modify    *
   8 * it under the terms of the GNU General Public License as published by    *
   9 * the Free Software Foundation; either version 2 of the License, or       *
  10 * (at your option) any later version.                                     *
  11 *                                                                         *
  12 * This program is distributed in the hope that it will be useful,         *
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
  15 * GNU General Public License for more details.                            *
  16 *                                                                         *
  17 * You should have received a copy of the GNU General Public License       *
  18 * along with this program; if not, write to the Free Software             *
  19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
  20 ***************************************************************************/
  21
  22#include "sn9c102_sensor.h"
  23#include "sn9c102_devtable.h"
  24
  25
  26static int ov7630_init(struct sn9c102_device* cam)
  27{
  28        int err = 0;
  29
  30        switch (sn9c102_get_bridge(cam)) {
  31        case BRIDGE_SN9C101:
  32        case BRIDGE_SN9C102:
  33                err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
  34                                               {0x0f, 0x18}, {0x50, 0x19});
  35
  36                err += sn9c102_i2c_write(cam, 0x12, 0x8d);
  37                err += sn9c102_i2c_write(cam, 0x12, 0x0d);
  38                err += sn9c102_i2c_write(cam, 0x11, 0x00);
  39                err += sn9c102_i2c_write(cam, 0x15, 0x35);
  40                err += sn9c102_i2c_write(cam, 0x16, 0x03);
  41                err += sn9c102_i2c_write(cam, 0x17, 0x1c);
  42                err += sn9c102_i2c_write(cam, 0x18, 0xbd);
  43                err += sn9c102_i2c_write(cam, 0x19, 0x06);
  44                err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
  45                err += sn9c102_i2c_write(cam, 0x1b, 0x04);
  46                err += sn9c102_i2c_write(cam, 0x20, 0x44);
  47                err += sn9c102_i2c_write(cam, 0x23, 0xee);
  48                err += sn9c102_i2c_write(cam, 0x26, 0xa0);
  49                err += sn9c102_i2c_write(cam, 0x27, 0x9a);
  50                err += sn9c102_i2c_write(cam, 0x28, 0x20);
  51                err += sn9c102_i2c_write(cam, 0x29, 0x30);
  52                err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
  53                err += sn9c102_i2c_write(cam, 0x30, 0x24);
  54                err += sn9c102_i2c_write(cam, 0x32, 0x86);
  55                err += sn9c102_i2c_write(cam, 0x60, 0xa9);
  56                err += sn9c102_i2c_write(cam, 0x61, 0x42);
  57                err += sn9c102_i2c_write(cam, 0x65, 0x00);
  58                err += sn9c102_i2c_write(cam, 0x69, 0x38);
  59                err += sn9c102_i2c_write(cam, 0x6f, 0x88);
  60                err += sn9c102_i2c_write(cam, 0x70, 0x0b);
  61                err += sn9c102_i2c_write(cam, 0x71, 0x00);
  62                err += sn9c102_i2c_write(cam, 0x74, 0x21);
  63                err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
  64                break;
  65        case BRIDGE_SN9C103:
  66                err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
  67                                               {0x1a, 0x04}, {0x20, 0x05},
  68                                               {0x20, 0x06}, {0x20, 0x07},
  69                                               {0x03, 0x10}, {0x0a, 0x14},
  70                                               {0x60, 0x17}, {0x0f, 0x18},
  71                                               {0x50, 0x19}, {0x1d, 0x1a},
  72                                               {0x10, 0x1b}, {0x02, 0x1c},
  73                                               {0x03, 0x1d}, {0x0f, 0x1e},
  74                                               {0x0c, 0x1f}, {0x00, 0x20},
  75                                               {0x10, 0x21}, {0x20, 0x22},
  76                                               {0x30, 0x23}, {0x40, 0x24},
  77                                               {0x50, 0x25}, {0x60, 0x26},
  78                                               {0x70, 0x27}, {0x80, 0x28},
  79                                               {0x90, 0x29}, {0xa0, 0x2a},
  80                                               {0xb0, 0x2b}, {0xc0, 0x2c},
  81                                               {0xd0, 0x2d}, {0xe0, 0x2e},
  82                                               {0xf0, 0x2f}, {0xff, 0x30});
  83
  84                err += sn9c102_i2c_write(cam, 0x12, 0x8d);
  85                err += sn9c102_i2c_write(cam, 0x12, 0x0d);
  86                err += sn9c102_i2c_write(cam, 0x15, 0x34);
  87                err += sn9c102_i2c_write(cam, 0x11, 0x01);
  88                err += sn9c102_i2c_write(cam, 0x1b, 0x04);
  89                err += sn9c102_i2c_write(cam, 0x20, 0x44);
  90                err += sn9c102_i2c_write(cam, 0x23, 0xee);
  91                err += sn9c102_i2c_write(cam, 0x26, 0xa0);
  92                err += sn9c102_i2c_write(cam, 0x27, 0x9a);
  93                err += sn9c102_i2c_write(cam, 0x28, 0x20);
  94                err += sn9c102_i2c_write(cam, 0x29, 0x30);
  95                err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
  96                err += sn9c102_i2c_write(cam, 0x30, 0x24);
  97                err += sn9c102_i2c_write(cam, 0x32, 0x86);
  98                err += sn9c102_i2c_write(cam, 0x60, 0xa9);
  99                err += sn9c102_i2c_write(cam, 0x61, 0x42);
 100                err += sn9c102_i2c_write(cam, 0x65, 0x00);
 101                err += sn9c102_i2c_write(cam, 0x69, 0x38);
 102                err += sn9c102_i2c_write(cam, 0x6f, 0x88);
 103                err += sn9c102_i2c_write(cam, 0x70, 0x0b);
 104                err += sn9c102_i2c_write(cam, 0x71, 0x00);
 105                err += sn9c102_i2c_write(cam, 0x74, 0x21);
 106                err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
 107                break;
 108        case BRIDGE_SN9C105:
 109        case BRIDGE_SN9C120:
 110        err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
 111                                       {0x1a, 0x04}, {0x03, 0x10},
 112                                       {0x0a, 0x14}, {0xe2, 0x17},
 113                                       {0x0b, 0x18}, {0x00, 0x19},
 114                                       {0x1d, 0x1a}, {0x10, 0x1b},
 115                                       {0x02, 0x1c}, {0x03, 0x1d},
 116                                       {0x0f, 0x1e}, {0x0c, 0x1f},
 117                                       {0x00, 0x20}, {0x24, 0x21},
 118                                       {0x3b, 0x22}, {0x47, 0x23},
 119                                       {0x60, 0x24}, {0x71, 0x25},
 120                                       {0x80, 0x26}, {0x8f, 0x27},
 121                                       {0x9d, 0x28}, {0xaa, 0x29},
 122                                       {0xb8, 0x2a}, {0xc4, 0x2b},
 123                                       {0xd1, 0x2c}, {0xdd, 0x2d},
 124                                       {0xe8, 0x2e}, {0xf4, 0x2f},
 125                                       {0xff, 0x30}, {0x00, 0x3f},
 126                                       {0xc7, 0x40}, {0x01, 0x41},
 127                                       {0x44, 0x42}, {0x00, 0x43},
 128                                       {0x44, 0x44}, {0x00, 0x45},
 129                                       {0x44, 0x46}, {0x00, 0x47},
 130                                       {0xc7, 0x48}, {0x01, 0x49},
 131                                       {0xc7, 0x4a}, {0x01, 0x4b},
 132                                       {0xc7, 0x4c}, {0x01, 0x4d},
 133                                       {0x44, 0x4e}, {0x00, 0x4f},
 134                                       {0x44, 0x50}, {0x00, 0x51},
 135                                       {0x44, 0x52}, {0x00, 0x53},
 136                                       {0xc7, 0x54}, {0x01, 0x55},
 137                                       {0xc7, 0x56}, {0x01, 0x57},
 138                                       {0xc7, 0x58}, {0x01, 0x59},
 139                                       {0x44, 0x5a}, {0x00, 0x5b},
 140                                       {0x44, 0x5c}, {0x00, 0x5d},
 141                                       {0x44, 0x5e}, {0x00, 0x5f},
 142                                       {0xc7, 0x60}, {0x01, 0x61},
 143                                       {0xc7, 0x62}, {0x01, 0x63},
 144                                       {0xc7, 0x64}, {0x01, 0x65},
 145                                       {0x44, 0x66}, {0x00, 0x67},
 146                                       {0x44, 0x68}, {0x00, 0x69},
 147                                       {0x44, 0x6a}, {0x00, 0x6b},
 148                                       {0xc7, 0x6c}, {0x01, 0x6d},
 149                                       {0xc7, 0x6e}, {0x01, 0x6f},
 150                                       {0xc7, 0x70}, {0x01, 0x71},
 151                                       {0x44, 0x72}, {0x00, 0x73},
 152                                       {0x44, 0x74}, {0x00, 0x75},
 153                                       {0x44, 0x76}, {0x00, 0x77},
 154                                       {0xc7, 0x78}, {0x01, 0x79},
 155                                       {0xc7, 0x7a}, {0x01, 0x7b},
 156                                       {0xc7, 0x7c}, {0x01, 0x7d},
 157                                       {0x44, 0x7e}, {0x00, 0x7f},
 158                                       {0x17, 0x84}, {0x00, 0x85},
 159                                       {0x2e, 0x86}, {0x00, 0x87},
 160                                       {0x09, 0x88}, {0x00, 0x89},
 161                                       {0xe8, 0x8a}, {0x0f, 0x8b},
 162                                       {0xda, 0x8c}, {0x0f, 0x8d},
 163                                       {0x40, 0x8e}, {0x00, 0x8f},
 164                                       {0x37, 0x90}, {0x00, 0x91},
 165                                       {0xcf, 0x92}, {0x0f, 0x93},
 166                                       {0xfa, 0x94}, {0x0f, 0x95},
 167                                       {0x00, 0x96}, {0x00, 0x97},
 168                                       {0x00, 0x98}, {0x66, 0x99},
 169                                       {0x00, 0x9a}, {0x40, 0x9b},
 170                                       {0x20, 0x9c}, {0x00, 0x9d},
 171                                       {0x00, 0x9e}, {0x00, 0x9f},
 172                                       {0x2d, 0xc0}, {0x2d, 0xc1},
 173                                       {0x3a, 0xc2}, {0x00, 0xc3},
 174                                       {0x04, 0xc4}, {0x3f, 0xc5},
 175                                       {0x00, 0xc6}, {0x00, 0xc7},
 176                                       {0x50, 0xc8}, {0x3c, 0xc9},
 177                                       {0x28, 0xca}, {0xd8, 0xcb},
 178                                       {0x14, 0xcc}, {0xec, 0xcd},
 179                                       {0x32, 0xce}, {0xdd, 0xcf},
 180                                       {0x32, 0xd0}, {0xdd, 0xd1},
 181                                       {0x6a, 0xd2}, {0x50, 0xd3},
 182                                       {0x60, 0xd4}, {0x00, 0xd5},
 183                                       {0x00, 0xd6});
 184
 185                err += sn9c102_i2c_write(cam, 0x12, 0x80);
 186                err += sn9c102_i2c_write(cam, 0x12, 0x48);
 187                err += sn9c102_i2c_write(cam, 0x01, 0x80);
 188                err += sn9c102_i2c_write(cam, 0x02, 0x80);
 189                err += sn9c102_i2c_write(cam, 0x03, 0x80);
 190                err += sn9c102_i2c_write(cam, 0x04, 0x10);
 191                err += sn9c102_i2c_write(cam, 0x05, 0x20);
 192                err += sn9c102_i2c_write(cam, 0x06, 0x80);
 193                err += sn9c102_i2c_write(cam, 0x11, 0x00);
 194                err += sn9c102_i2c_write(cam, 0x0c, 0x20);
 195                err += sn9c102_i2c_write(cam, 0x0d, 0x20);
 196                err += sn9c102_i2c_write(cam, 0x15, 0x80);
 197                err += sn9c102_i2c_write(cam, 0x16, 0x03);
 198                err += sn9c102_i2c_write(cam, 0x17, 0x1b);
 199                err += sn9c102_i2c_write(cam, 0x18, 0xbd);
 200                err += sn9c102_i2c_write(cam, 0x19, 0x05);
 201                err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
 202                err += sn9c102_i2c_write(cam, 0x1b, 0x04);
 203                err += sn9c102_i2c_write(cam, 0x21, 0x1b);
 204                err += sn9c102_i2c_write(cam, 0x22, 0x00);
 205                err += sn9c102_i2c_write(cam, 0x23, 0xde);
 206                err += sn9c102_i2c_write(cam, 0x24, 0x10);
 207                err += sn9c102_i2c_write(cam, 0x25, 0x8a);
 208                err += sn9c102_i2c_write(cam, 0x26, 0xa0);
 209                err += sn9c102_i2c_write(cam, 0x27, 0xca);
 210                err += sn9c102_i2c_write(cam, 0x28, 0xa2);
 211                err += sn9c102_i2c_write(cam, 0x29, 0x74);
 212                err += sn9c102_i2c_write(cam, 0x2a, 0x88);
 213                err += sn9c102_i2c_write(cam, 0x2b, 0x34);
 214                err += sn9c102_i2c_write(cam, 0x2c, 0x88);
 215                err += sn9c102_i2c_write(cam, 0x2e, 0x00);
 216                err += sn9c102_i2c_write(cam, 0x2f, 0x00);
 217                err += sn9c102_i2c_write(cam, 0x30, 0x00);
 218                err += sn9c102_i2c_write(cam, 0x32, 0xc2);
 219                err += sn9c102_i2c_write(cam, 0x33, 0x08);
 220                err += sn9c102_i2c_write(cam, 0x4c, 0x40);
 221                err += sn9c102_i2c_write(cam, 0x4d, 0xf3);
 222                err += sn9c102_i2c_write(cam, 0x60, 0x05);
 223                err += sn9c102_i2c_write(cam, 0x61, 0x40);
 224                err += sn9c102_i2c_write(cam, 0x62, 0x12);
 225                err += sn9c102_i2c_write(cam, 0x63, 0x57);
 226                err += sn9c102_i2c_write(cam, 0x64, 0x73);
 227                err += sn9c102_i2c_write(cam, 0x65, 0x00);
 228                err += sn9c102_i2c_write(cam, 0x66, 0x55);
 229                err += sn9c102_i2c_write(cam, 0x67, 0x01);
 230                err += sn9c102_i2c_write(cam, 0x68, 0xac);
 231                err += sn9c102_i2c_write(cam, 0x69, 0x38);
 232                err += sn9c102_i2c_write(cam, 0x6f, 0x1f);
 233                err += sn9c102_i2c_write(cam, 0x70, 0x01);
 234                err += sn9c102_i2c_write(cam, 0x71, 0x00);
 235                err += sn9c102_i2c_write(cam, 0x72, 0x10);
 236                err += sn9c102_i2c_write(cam, 0x73, 0x50);
 237                err += sn9c102_i2c_write(cam, 0x74, 0x20);
 238                err += sn9c102_i2c_write(cam, 0x76, 0x01);
 239                err += sn9c102_i2c_write(cam, 0x77, 0xf3);
 240                err += sn9c102_i2c_write(cam, 0x78, 0x90);
 241                err += sn9c102_i2c_write(cam, 0x79, 0x98);
 242                err += sn9c102_i2c_write(cam, 0x7a, 0x98);
 243                err += sn9c102_i2c_write(cam, 0x7b, 0x00);
 244                err += sn9c102_i2c_write(cam, 0x7c, 0x38);
 245                err += sn9c102_i2c_write(cam, 0x7d, 0xff);
 246                break;
 247        default:
 248                break;
 249        }
 250
 251        return err;
 252}
 253
 254
 255static int ov7630_get_ctrl(struct sn9c102_device* cam,
 256                           struct v4l2_control* ctrl)
 257{
 258        enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
 259        int err = 0;
 260
 261        switch (ctrl->id) {
 262        case V4L2_CID_EXPOSURE:
 263                if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
 264                        return -EIO;
 265                break;
 266        case V4L2_CID_RED_BALANCE:
 267                if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
 268                        ctrl->value = sn9c102_pread_reg(cam, 0x05);
 269                else
 270                        ctrl->value = sn9c102_pread_reg(cam, 0x07);
 271                break;
 272        case V4L2_CID_BLUE_BALANCE:
 273                ctrl->value = sn9c102_pread_reg(cam, 0x06);
 274                break;
 275        case SN9C102_V4L2_CID_GREEN_BALANCE:
 276                if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
 277                        ctrl->value = sn9c102_pread_reg(cam, 0x07);
 278                else
 279                        ctrl->value = sn9c102_pread_reg(cam, 0x05);
 280                break;
 281                break;
 282        case V4L2_CID_GAIN:
 283                if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
 284                        return -EIO;
 285                ctrl->value &= 0x3f;
 286                break;
 287        case V4L2_CID_DO_WHITE_BALANCE:
 288                if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
 289                        return -EIO;
 290                ctrl->value &= 0x3f;
 291                break;
 292        case V4L2_CID_WHITENESS:
 293                if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
 294                        return -EIO;
 295                ctrl->value &= 0x3f;
 296                break;
 297        case V4L2_CID_AUTOGAIN:
 298                if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
 299                        return -EIO;
 300                ctrl->value &= 0x01;
 301                break;
 302        case V4L2_CID_VFLIP:
 303                if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0)
 304                        return -EIO;
 305                ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
 306                break;
 307        case SN9C102_V4L2_CID_GAMMA:
 308                if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0)
 309                        return -EIO;
 310                ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
 311                break;
 312        case SN9C102_V4L2_CID_BAND_FILTER:
 313                if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0)
 314                        return -EIO;
 315                ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
 316                break;
 317        default:
 318                return -EINVAL;
 319        }
 320
 321        return err ? -EIO : 0;
 322}
 323
 324
 325static int ov7630_set_ctrl(struct sn9c102_device* cam,
 326                           const struct v4l2_control* ctrl)
 327{
 328        enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
 329        int err = 0;
 330
 331        switch (ctrl->id) {
 332        case V4L2_CID_EXPOSURE:
 333                err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
 334                break;
 335        case V4L2_CID_RED_BALANCE:
 336                if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
 337                        err += sn9c102_write_reg(cam, ctrl->value, 0x05);
 338                else
 339                        err += sn9c102_write_reg(cam, ctrl->value, 0x07);
 340                break;
 341        case V4L2_CID_BLUE_BALANCE:
 342                err += sn9c102_write_reg(cam, ctrl->value, 0x06);
 343                break;
 344        case SN9C102_V4L2_CID_GREEN_BALANCE:
 345                if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
 346                        err += sn9c102_write_reg(cam, ctrl->value, 0x07);
 347                else
 348                        err += sn9c102_write_reg(cam, ctrl->value, 0x05);
 349                break;
 350        case V4L2_CID_GAIN:
 351                err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
 352                break;
 353        case V4L2_CID_DO_WHITE_BALANCE:
 354                err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
 355                break;
 356        case V4L2_CID_WHITENESS:
 357                err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
 358                break;
 359        case V4L2_CID_AUTOGAIN:
 360                err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
 361                                                    (ctrl->value << 1));
 362                break;
 363        case V4L2_CID_VFLIP:
 364                err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
 365                break;
 366        case SN9C102_V4L2_CID_GAMMA:
 367                err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
 368                break;
 369        case SN9C102_V4L2_CID_BAND_FILTER:
 370                err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
 371                break;
 372        default:
 373                return -EINVAL;
 374        }
 375
 376        return err ? -EIO : 0;
 377}
 378
 379
 380static int ov7630_set_crop(struct sn9c102_device* cam,
 381                           const struct v4l2_rect* rect)
 382{
 383        struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 384        int err = 0;
 385        u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
 386
 387        switch (sn9c102_get_bridge(cam)) {
 388        case BRIDGE_SN9C101:
 389        case BRIDGE_SN9C102:
 390        case BRIDGE_SN9C103:
 391                h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
 392                break;
 393        case BRIDGE_SN9C105:
 394        case BRIDGE_SN9C120:
 395                h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
 396                break;
 397        default:
 398                break;
 399        }
 400
 401        err += sn9c102_write_reg(cam, h_start, 0x12);
 402        err += sn9c102_write_reg(cam, v_start, 0x13);
 403
 404        return err;
 405}
 406
 407
 408static int ov7630_set_pix_format(struct sn9c102_device* cam,
 409                                 const struct v4l2_pix_format* pix)
 410{
 411        int err = 0;
 412
 413        switch (sn9c102_get_bridge(cam)) {
 414        case BRIDGE_SN9C101:
 415        case BRIDGE_SN9C102:
 416        case BRIDGE_SN9C103:
 417                if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8)
 418                        err += sn9c102_write_reg(cam, 0x50, 0x19);
 419                else
 420                        err += sn9c102_write_reg(cam, 0x20, 0x19);
 421                break;
 422        case BRIDGE_SN9C105:
 423        case BRIDGE_SN9C120:
 424                if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
 425                        err += sn9c102_write_reg(cam, 0xe5, 0x17);
 426                        err += sn9c102_i2c_write(cam, 0x11, 0x04);
 427                } else {
 428                        err += sn9c102_write_reg(cam, 0xe2, 0x17);
 429                        err += sn9c102_i2c_write(cam, 0x11, 0x02);
 430                }
 431                break;
 432        default:
 433                break;
 434        }
 435
 436        return err;
 437}
 438
 439
 440static const struct sn9c102_sensor ov7630 = {
 441        .name = "OV7630",
 442        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 443        .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 |
 444                            BRIDGE_SN9C105 | BRIDGE_SN9C120,
 445        .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
 446        .frequency = SN9C102_I2C_100KHZ,
 447        .interface = SN9C102_I2C_2WIRES,
 448        .i2c_slave_id = 0x21,
 449        .init = &ov7630_init,
 450        .qctrl = {
 451                {
 452                        .id = V4L2_CID_GAIN,
 453                        .type = V4L2_CTRL_TYPE_INTEGER,
 454                        .name = "global gain",
 455                        .minimum = 0x00,
 456                        .maximum = 0x3f,
 457                        .step = 0x01,
 458                        .default_value = 0x14,
 459                        .flags = 0,
 460                },
 461                {
 462                        .id = V4L2_CID_EXPOSURE,
 463                        .type = V4L2_CTRL_TYPE_INTEGER,
 464                        .name = "exposure",
 465                        .minimum = 0x00,
 466                        .maximum = 0xff,
 467                        .step = 0x01,
 468                        .default_value = 0x60,
 469                        .flags = 0,
 470                },
 471                {
 472                        .id = V4L2_CID_WHITENESS,
 473                        .type = V4L2_CTRL_TYPE_INTEGER,
 474                        .name = "white balance background: red",
 475                        .minimum = 0x00,
 476                        .maximum = 0x3f,
 477                        .step = 0x01,
 478                        .default_value = 0x20,
 479                        .flags = 0,
 480                },
 481                {
 482                        .id = V4L2_CID_DO_WHITE_BALANCE,
 483                        .type = V4L2_CTRL_TYPE_INTEGER,
 484                        .name = "white balance background: blue",
 485                        .minimum = 0x00,
 486                        .maximum = 0x3f,
 487                        .step = 0x01,
 488                        .default_value = 0x20,
 489                        .flags = 0,
 490                },
 491                {
 492                        .id = V4L2_CID_RED_BALANCE,
 493                        .type = V4L2_CTRL_TYPE_INTEGER,
 494                        .name = "red balance",
 495                        .minimum = 0x00,
 496                        .maximum = 0x7f,
 497                        .step = 0x01,
 498                        .default_value = 0x20,
 499                        .flags = 0,
 500                },
 501                {
 502                        .id = V4L2_CID_BLUE_BALANCE,
 503                        .type = V4L2_CTRL_TYPE_INTEGER,
 504                        .name = "blue balance",
 505                        .minimum = 0x00,
 506                        .maximum = 0x7f,
 507                        .step = 0x01,
 508                        .default_value = 0x20,
 509                        .flags = 0,
 510                },
 511                {
 512                        .id = V4L2_CID_AUTOGAIN,
 513                        .type = V4L2_CTRL_TYPE_BOOLEAN,
 514                        .name = "auto adjust",
 515                        .minimum = 0x00,
 516                        .maximum = 0x01,
 517                        .step = 0x01,
 518                        .default_value = 0x00,
 519                        .flags = 0,
 520                },
 521                {
 522                        .id = V4L2_CID_VFLIP,
 523                        .type = V4L2_CTRL_TYPE_BOOLEAN,
 524                        .name = "vertical flip",
 525                        .minimum = 0x00,
 526                        .maximum = 0x01,
 527                        .step = 0x01,
 528                        .default_value = 0x01,
 529                        .flags = 0,
 530                },
 531                {
 532                        .id = SN9C102_V4L2_CID_GREEN_BALANCE,
 533                        .type = V4L2_CTRL_TYPE_INTEGER,
 534                        .name = "green balance",
 535                        .minimum = 0x00,
 536                        .maximum = 0x7f,
 537                        .step = 0x01,
 538                        .default_value = 0x20,
 539                        .flags = 0,
 540                },
 541                {
 542                        .id = SN9C102_V4L2_CID_BAND_FILTER,
 543                        .type = V4L2_CTRL_TYPE_BOOLEAN,
 544                        .name = "band filter",
 545                        .minimum = 0x00,
 546                        .maximum = 0x01,
 547                        .step = 0x01,
 548                        .default_value = 0x00,
 549                        .flags = 0,
 550                },
 551                {
 552                        .id = SN9C102_V4L2_CID_GAMMA,
 553                        .type = V4L2_CTRL_TYPE_BOOLEAN,
 554                        .name = "rgb gamma",
 555                        .minimum = 0x00,
 556                        .maximum = 0x01,
 557                        .step = 0x01,
 558                        .default_value = 0x00,
 559                        .flags = 0,
 560                },
 561        },
 562        .get_ctrl = &ov7630_get_ctrl,
 563        .set_ctrl = &ov7630_set_ctrl,
 564        .cropcap = {
 565                .bounds = {
 566                        .left = 0,
 567                        .top = 0,
 568                        .width = 640,
 569                        .height = 480,
 570                },
 571                .defrect = {
 572                        .left = 0,
 573                        .top = 0,
 574                        .width = 640,
 575                        .height = 480,
 576                },
 577        },
 578        .set_crop = &ov7630_set_crop,
 579        .pix_format = {
 580                .width = 640,
 581                .height = 480,
 582                .pixelformat = V4L2_PIX_FMT_SN9C10X,
 583                .priv = 8,
 584        },
 585        .set_pix_format = &ov7630_set_pix_format
 586};
 587
 588
 589int sn9c102_probe_ov7630(struct sn9c102_device* cam)
 590{
 591        int pid, ver, err = 0;
 592
 593        switch (sn9c102_get_bridge(cam)) {
 594        case BRIDGE_SN9C101:
 595        case BRIDGE_SN9C102:
 596                err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
 597                                               {0x28, 0x17});
 598                break;
 599        case BRIDGE_SN9C103: /* do _not_ change anything! */
 600                err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
 601                                               {0x28, 0x17}, {0x44, 0x02});
 602                pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
 603                if (err || pid < 0) /* try a different initialization */
 604                        err += sn9c102_write_const_regs(cam, {0x01, 0x01},
 605                                                        {0x00, 0x01});
 606                break;
 607        case BRIDGE_SN9C105:
 608        case BRIDGE_SN9C120:
 609                err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
 610                                               {0x29, 0x01}, {0x74, 0x02},
 611                                               {0x0e, 0x01}, {0x44, 0x01});
 612                break;
 613        default:
 614                break;
 615        }
 616
 617        pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
 618        ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
 619        if (err || pid < 0 || ver < 0)
 620                return -EIO;
 621        if (pid != 0x76 || ver != 0x31)
 622                return -ENODEV;
 623        sn9c102_attach_sensor(cam, &ov7630);
 624
 625        return 0;
 626}
 627