linux/drivers/media/video/sn9c102/sn9c102_hv7131r.c
<<
>>
Prefs
   1/***************************************************************************
   2 * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera     *
   3 * Controllers                                                             *
   4 *                                                                         *
   5 * Copyright (C) 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 hv7131r_init(struct sn9c102_device* cam)
  27{
  28        int err = 0;
  29
  30        switch (sn9c102_get_bridge(cam)) {
  31        case BRIDGE_SN9C103:
  32                err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04},
  33                                               {0x20, 0x05}, {0x20, 0x06},
  34                                               {0x03, 0x10}, {0x00, 0x14},
  35                                               {0x60, 0x17}, {0x0a, 0x18},
  36                                               {0xf0, 0x19}, {0x1d, 0x1a},
  37                                               {0x10, 0x1b}, {0x02, 0x1c},
  38                                               {0x03, 0x1d}, {0x0f, 0x1e},
  39                                               {0x0c, 0x1f}, {0x00, 0x20},
  40                                               {0x10, 0x21}, {0x20, 0x22},
  41                                               {0x30, 0x23}, {0x40, 0x24},
  42                                               {0x50, 0x25}, {0x60, 0x26},
  43                                               {0x70, 0x27}, {0x80, 0x28},
  44                                               {0x90, 0x29}, {0xa0, 0x2a},
  45                                               {0xb0, 0x2b}, {0xc0, 0x2c},
  46                                               {0xd0, 0x2d}, {0xe0, 0x2e},
  47                                               {0xf0, 0x2f}, {0xff, 0x30});
  48                break;
  49        case BRIDGE_SN9C105:
  50        case BRIDGE_SN9C120:
  51                err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
  52                                               {0x00, 0x03}, {0x1a, 0x04},
  53                                               {0x44, 0x05}, {0x3e, 0x06},
  54                                               {0x1a, 0x07}, {0x03, 0x10},
  55                                               {0x08, 0x14}, {0xa3, 0x17},
  56                                               {0x4b, 0x18}, {0x00, 0x19},
  57                                               {0x1d, 0x1a}, {0x10, 0x1b},
  58                                               {0x02, 0x1c}, {0x03, 0x1d},
  59                                               {0x0f, 0x1e}, {0x0c, 0x1f},
  60                                               {0x00, 0x20}, {0x29, 0x21},
  61                                               {0x40, 0x22}, {0x54, 0x23},
  62                                               {0x66, 0x24}, {0x76, 0x25},
  63                                               {0x85, 0x26}, {0x94, 0x27},
  64                                               {0xa1, 0x28}, {0xae, 0x29},
  65                                               {0xbb, 0x2a}, {0xc7, 0x2b},
  66                                               {0xd3, 0x2c}, {0xde, 0x2d},
  67                                               {0xea, 0x2e}, {0xf4, 0x2f},
  68                                               {0xff, 0x30}, {0x00, 0x3F},
  69                                               {0xC7, 0x40}, {0x01, 0x41},
  70                                               {0x44, 0x42}, {0x00, 0x43},
  71                                               {0x44, 0x44}, {0x00, 0x45},
  72                                               {0x44, 0x46}, {0x00, 0x47},
  73                                               {0xC7, 0x48}, {0x01, 0x49},
  74                                               {0xC7, 0x4A}, {0x01, 0x4B},
  75                                               {0xC7, 0x4C}, {0x01, 0x4D},
  76                                               {0x44, 0x4E}, {0x00, 0x4F},
  77                                               {0x44, 0x50}, {0x00, 0x51},
  78                                               {0x44, 0x52}, {0x00, 0x53},
  79                                               {0xC7, 0x54}, {0x01, 0x55},
  80                                               {0xC7, 0x56}, {0x01, 0x57},
  81                                               {0xC7, 0x58}, {0x01, 0x59},
  82                                               {0x44, 0x5A}, {0x00, 0x5B},
  83                                               {0x44, 0x5C}, {0x00, 0x5D},
  84                                               {0x44, 0x5E}, {0x00, 0x5F},
  85                                               {0xC7, 0x60}, {0x01, 0x61},
  86                                               {0xC7, 0x62}, {0x01, 0x63},
  87                                               {0xC7, 0x64}, {0x01, 0x65},
  88                                               {0x44, 0x66}, {0x00, 0x67},
  89                                               {0x44, 0x68}, {0x00, 0x69},
  90                                               {0x44, 0x6A}, {0x00, 0x6B},
  91                                               {0xC7, 0x6C}, {0x01, 0x6D},
  92                                               {0xC7, 0x6E}, {0x01, 0x6F},
  93                                               {0xC7, 0x70}, {0x01, 0x71},
  94                                               {0x44, 0x72}, {0x00, 0x73},
  95                                               {0x44, 0x74}, {0x00, 0x75},
  96                                               {0x44, 0x76}, {0x00, 0x77},
  97                                               {0xC7, 0x78}, {0x01, 0x79},
  98                                               {0xC7, 0x7A}, {0x01, 0x7B},
  99                                               {0xC7, 0x7C}, {0x01, 0x7D},
 100                                               {0x44, 0x7E}, {0x00, 0x7F},
 101                                               {0x14, 0x84}, {0x00, 0x85},
 102                                               {0x27, 0x86}, {0x00, 0x87},
 103                                               {0x07, 0x88}, {0x00, 0x89},
 104                                               {0xEC, 0x8A}, {0x0f, 0x8B},
 105                                               {0xD8, 0x8C}, {0x0f, 0x8D},
 106                                               {0x3D, 0x8E}, {0x00, 0x8F},
 107                                               {0x3D, 0x90}, {0x00, 0x91},
 108                                               {0xCD, 0x92}, {0x0f, 0x93},
 109                                               {0xf7, 0x94}, {0x0f, 0x95},
 110                                               {0x0C, 0x96}, {0x00, 0x97},
 111                                               {0x00, 0x98}, {0x66, 0x99},
 112                                               {0x05, 0x9A}, {0x00, 0x9B},
 113                                               {0x04, 0x9C}, {0x00, 0x9D},
 114                                               {0x08, 0x9E}, {0x00, 0x9F},
 115                                               {0x2D, 0xC0}, {0x2D, 0xC1},
 116                                               {0x3A, 0xC2}, {0x05, 0xC3},
 117                                               {0x04, 0xC4}, {0x3F, 0xC5},
 118                                               {0x00, 0xC6}, {0x00, 0xC7},
 119                                               {0x50, 0xC8}, {0x3C, 0xC9},
 120                                               {0x28, 0xCA}, {0xD8, 0xCB},
 121                                               {0x14, 0xCC}, {0xEC, 0xCD},
 122                                               {0x32, 0xCE}, {0xDD, 0xCF},
 123                                               {0x32, 0xD0}, {0xDD, 0xD1},
 124                                               {0x6A, 0xD2}, {0x50, 0xD3},
 125                                               {0x00, 0xD4}, {0x00, 0xD5},
 126                                               {0x00, 0xD6});
 127                break;
 128        default:
 129                break;
 130        }
 131
 132        err += sn9c102_i2c_write(cam, 0x20, 0x00);
 133        err += sn9c102_i2c_write(cam, 0x21, 0xd6);
 134        err += sn9c102_i2c_write(cam, 0x25, 0x06);
 135
 136        return err;
 137}
 138
 139
 140static int hv7131r_get_ctrl(struct sn9c102_device* cam,
 141                            struct v4l2_control* ctrl)
 142{
 143        switch (ctrl->id) {
 144        case V4L2_CID_GAIN:
 145                if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
 146                        return -EIO;
 147                return 0;
 148        case V4L2_CID_RED_BALANCE:
 149                if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
 150                        return -EIO;
 151                ctrl->value = ctrl->value & 0x3f;
 152                return 0;
 153        case V4L2_CID_BLUE_BALANCE:
 154                if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
 155                        return -EIO;
 156                ctrl->value = ctrl->value & 0x3f;
 157                return 0;
 158        case SN9C102_V4L2_CID_GREEN_BALANCE:
 159                if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
 160                        return -EIO;
 161                ctrl->value = ctrl->value & 0x3f;
 162                return 0;
 163        case V4L2_CID_BLACK_LEVEL:
 164                if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0)
 165                        return -EIO;
 166                ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
 167                return 0;
 168        default:
 169                return -EINVAL;
 170        }
 171}
 172
 173
 174static int hv7131r_set_ctrl(struct sn9c102_device* cam,
 175                            const struct v4l2_control* ctrl)
 176{
 177        int err = 0;
 178
 179        switch (ctrl->id) {
 180        case V4L2_CID_GAIN:
 181                err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
 182                break;
 183        case V4L2_CID_RED_BALANCE:
 184                err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
 185                break;
 186        case V4L2_CID_BLUE_BALANCE:
 187                err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
 188                break;
 189        case SN9C102_V4L2_CID_GREEN_BALANCE:
 190                err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
 191                break;
 192        case V4L2_CID_BLACK_LEVEL:
 193                {
 194                        int r = sn9c102_i2c_read(cam, 0x01);
 195                        if (r < 0)
 196                                return -EIO;
 197                        err += sn9c102_i2c_write(cam, 0x01,
 198                                                 (ctrl->value<<3) | (r&0xf7));
 199                }
 200                break;
 201        default:
 202                return -EINVAL;
 203        }
 204
 205        return err ? -EIO : 0;
 206}
 207
 208
 209static int hv7131r_set_crop(struct sn9c102_device* cam,
 210                            const struct v4l2_rect* rect)
 211{
 212        struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 213        int err = 0;
 214        u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
 215           v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
 216
 217        err += sn9c102_write_reg(cam, h_start, 0x12);
 218        err += sn9c102_write_reg(cam, v_start, 0x13);
 219
 220        return err;
 221}
 222
 223
 224static int hv7131r_set_pix_format(struct sn9c102_device* cam,
 225                                  const struct v4l2_pix_format* pix)
 226{
 227        int err = 0;
 228
 229        switch (sn9c102_get_bridge(cam)) {
 230        case BRIDGE_SN9C103:
 231                if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
 232                        err += sn9c102_write_reg(cam, 0xa0, 0x19);
 233                        err += sn9c102_i2c_write(cam, 0x01, 0x04);
 234                } else {
 235                        err += sn9c102_write_reg(cam, 0x30, 0x19);
 236                        err += sn9c102_i2c_write(cam, 0x01, 0x04);
 237                }
 238                break;
 239        case BRIDGE_SN9C105:
 240        case BRIDGE_SN9C120:
 241                if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
 242                        err += sn9c102_write_reg(cam, 0xa5, 0x17);
 243                        err += sn9c102_i2c_write(cam, 0x01, 0x24);
 244                } else {
 245                        err += sn9c102_write_reg(cam, 0xa3, 0x17);
 246                        err += sn9c102_i2c_write(cam, 0x01, 0x04);
 247                }
 248                break;
 249        default:
 250                break;
 251        }
 252
 253        return err;
 254}
 255
 256
 257static const struct sn9c102_sensor hv7131r = {
 258        .name = "HV7131R",
 259        .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 260        .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
 261        .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
 262        .frequency = SN9C102_I2C_100KHZ,
 263        .interface = SN9C102_I2C_2WIRES,
 264        .i2c_slave_id = 0x11,
 265        .init = &hv7131r_init,
 266        .qctrl = {
 267                {
 268                        .id = V4L2_CID_GAIN,
 269                        .type = V4L2_CTRL_TYPE_INTEGER,
 270                        .name = "global gain",
 271                        .minimum = 0x00,
 272                        .maximum = 0xff,
 273                        .step = 0x01,
 274                        .default_value = 0x40,
 275                        .flags = 0,
 276                },
 277                {
 278                        .id = V4L2_CID_RED_BALANCE,
 279                        .type = V4L2_CTRL_TYPE_INTEGER,
 280                        .name = "red balance",
 281                        .minimum = 0x00,
 282                        .maximum = 0x3f,
 283                        .step = 0x01,
 284                        .default_value = 0x08,
 285                        .flags = 0,
 286                },
 287                {
 288                        .id = V4L2_CID_BLUE_BALANCE,
 289                        .type = V4L2_CTRL_TYPE_INTEGER,
 290                        .name = "blue balance",
 291                        .minimum = 0x00,
 292                        .maximum = 0x3f,
 293                        .step = 0x01,
 294                        .default_value = 0x1a,
 295                        .flags = 0,
 296                },
 297                {
 298                        .id = SN9C102_V4L2_CID_GREEN_BALANCE,
 299                        .type = V4L2_CTRL_TYPE_INTEGER,
 300                        .name = "green balance",
 301                        .minimum = 0x00,
 302                        .maximum = 0x3f,
 303                        .step = 0x01,
 304                        .default_value = 0x2f,
 305                        .flags = 0,
 306                },
 307                {
 308                        .id = V4L2_CID_BLACK_LEVEL,
 309                        .type = V4L2_CTRL_TYPE_BOOLEAN,
 310                        .name = "auto black level compensation",
 311                        .minimum = 0x00,
 312                        .maximum = 0x01,
 313                        .step = 0x01,
 314                        .default_value = 0x00,
 315                        .flags = 0,
 316                },
 317        },
 318        .get_ctrl = &hv7131r_get_ctrl,
 319        .set_ctrl = &hv7131r_set_ctrl,
 320        .cropcap = {
 321                .bounds = {
 322                        .left = 0,
 323                        .top = 0,
 324                        .width = 640,
 325                        .height = 480,
 326                },
 327                .defrect = {
 328                        .left = 0,
 329                        .top = 0,
 330                        .width = 640,
 331                        .height = 480,
 332                },
 333        },
 334        .set_crop = &hv7131r_set_crop,
 335        .pix_format = {
 336                .width = 640,
 337                .height = 480,
 338                .pixelformat = V4L2_PIX_FMT_SBGGR8,
 339                .priv = 8,
 340        },
 341        .set_pix_format = &hv7131r_set_pix_format
 342};
 343
 344
 345int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
 346{
 347        int devid, err;
 348
 349        err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02},
 350                                       {0x34, 0x01}, {0x20, 0x17},
 351                                       {0x34, 0x01}, {0x46, 0x01});
 352
 353        devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
 354        if (err || devid < 0)
 355                return -EIO;
 356
 357        if (devid != 0x02)
 358                return -ENODEV;
 359
 360        sn9c102_attach_sensor(cam, &hv7131r);
 361
 362        return 0;
 363}
 364