linux/drivers/media/video/mt9v022.c
<<
>>
Prefs
   1/*
   2 * Driver for MT9V022 CMOS Image Sensor from Micron
   3 *
   4 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/videodev2.h>
  12#include <linux/slab.h>
  13#include <linux/i2c.h>
  14#include <linux/delay.h>
  15#include <linux/log2.h>
  16
  17#include <media/v4l2-subdev.h>
  18#include <media/v4l2-chip-ident.h>
  19#include <media/soc_camera.h>
  20
  21/*
  22 * mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
  23 * The platform has to define ctruct i2c_board_info objects and link to them
  24 * from struct soc_camera_link
  25 */
  26
  27static char *sensor_type;
  28module_param(sensor_type, charp, S_IRUGO);
  29MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
  30
  31/* mt9v022 selected register addresses */
  32#define MT9V022_CHIP_VERSION            0x00
  33#define MT9V022_COLUMN_START            0x01
  34#define MT9V022_ROW_START               0x02
  35#define MT9V022_WINDOW_HEIGHT           0x03
  36#define MT9V022_WINDOW_WIDTH            0x04
  37#define MT9V022_HORIZONTAL_BLANKING     0x05
  38#define MT9V022_VERTICAL_BLANKING       0x06
  39#define MT9V022_CHIP_CONTROL            0x07
  40#define MT9V022_SHUTTER_WIDTH1          0x08
  41#define MT9V022_SHUTTER_WIDTH2          0x09
  42#define MT9V022_SHUTTER_WIDTH_CTRL      0x0a
  43#define MT9V022_TOTAL_SHUTTER_WIDTH     0x0b
  44#define MT9V022_RESET                   0x0c
  45#define MT9V022_READ_MODE               0x0d
  46#define MT9V022_MONITOR_MODE            0x0e
  47#define MT9V022_PIXEL_OPERATION_MODE    0x0f
  48#define MT9V022_LED_OUT_CONTROL         0x1b
  49#define MT9V022_ADC_MODE_CONTROL        0x1c
  50#define MT9V022_ANALOG_GAIN             0x35
  51#define MT9V022_BLACK_LEVEL_CALIB_CTRL  0x47
  52#define MT9V022_PIXCLK_FV_LV            0x74
  53#define MT9V022_DIGITAL_TEST_PATTERN    0x7f
  54#define MT9V022_AEC_AGC_ENABLE          0xAF
  55#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH 0xBD
  56
  57/* Progressive scan, master, defaults */
  58#define MT9V022_CHIP_CONTROL_DEFAULT    0x188
  59
  60#define MT9V022_MAX_WIDTH               752
  61#define MT9V022_MAX_HEIGHT              480
  62#define MT9V022_MIN_WIDTH               48
  63#define MT9V022_MIN_HEIGHT              32
  64#define MT9V022_COLUMN_SKIP             1
  65#define MT9V022_ROW_SKIP                4
  66
  67/* MT9V022 has only one fixed colorspace per pixelcode */
  68struct mt9v022_datafmt {
  69        enum v4l2_mbus_pixelcode        code;
  70        enum v4l2_colorspace            colorspace;
  71};
  72
  73/* Find a data format by a pixel code in an array */
  74static const struct mt9v022_datafmt *mt9v022_find_datafmt(
  75        enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt,
  76        int n)
  77{
  78        int i;
  79        for (i = 0; i < n; i++)
  80                if (fmt[i].code == code)
  81                        return fmt + i;
  82
  83        return NULL;
  84}
  85
  86static const struct mt9v022_datafmt mt9v022_colour_fmts[] = {
  87        /*
  88         * Order important: first natively supported,
  89         * second supported with a GPIO extender
  90         */
  91        {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
  92        {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
  93};
  94
  95static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
  96        /* Order important - see above */
  97        {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
  98        {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
  99};
 100
 101struct mt9v022 {
 102        struct v4l2_subdev subdev;
 103        struct v4l2_rect rect;  /* Sensor window */
 104        const struct mt9v022_datafmt *fmt;
 105        const struct mt9v022_datafmt *fmts;
 106        int num_fmts;
 107        int model;      /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
 108        u16 chip_control;
 109        unsigned short y_skip_top;      /* Lines to skip at the top */
 110};
 111
 112static struct mt9v022 *to_mt9v022(const struct i2c_client *client)
 113{
 114        return container_of(i2c_get_clientdata(client), struct mt9v022, subdev);
 115}
 116
 117static int reg_read(struct i2c_client *client, const u8 reg)
 118{
 119        s32 data = i2c_smbus_read_word_data(client, reg);
 120        return data < 0 ? data : swab16(data);
 121}
 122
 123static int reg_write(struct i2c_client *client, const u8 reg,
 124                     const u16 data)
 125{
 126        return i2c_smbus_write_word_data(client, reg, swab16(data));
 127}
 128
 129static int reg_set(struct i2c_client *client, const u8 reg,
 130                   const u16 data)
 131{
 132        int ret;
 133
 134        ret = reg_read(client, reg);
 135        if (ret < 0)
 136                return ret;
 137        return reg_write(client, reg, ret | data);
 138}
 139
 140static int reg_clear(struct i2c_client *client, const u8 reg,
 141                     const u16 data)
 142{
 143        int ret;
 144
 145        ret = reg_read(client, reg);
 146        if (ret < 0)
 147                return ret;
 148        return reg_write(client, reg, ret & ~data);
 149}
 150
 151static int mt9v022_init(struct i2c_client *client)
 152{
 153        struct mt9v022 *mt9v022 = to_mt9v022(client);
 154        int ret;
 155
 156        /*
 157         * Almost the default mode: master, parallel, simultaneous, and an
 158         * undocumented bit 0x200, which is present in table 7, but not in 8,
 159         * plus snapshot mode to disable scan for now
 160         */
 161        mt9v022->chip_control |= 0x10;
 162        ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
 163        if (!ret)
 164                ret = reg_write(client, MT9V022_READ_MODE, 0x300);
 165
 166        /* All defaults */
 167        if (!ret)
 168                /* AEC, AGC on */
 169                ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3);
 170        if (!ret)
 171                ret = reg_write(client, MT9V022_ANALOG_GAIN, 16);
 172        if (!ret)
 173                ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480);
 174        if (!ret)
 175                ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
 176        if (!ret)
 177                /* default - auto */
 178                ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
 179        if (!ret)
 180                ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0);
 181
 182        return ret;
 183}
 184
 185static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
 186{
 187        struct i2c_client *client = v4l2_get_subdevdata(sd);
 188        struct mt9v022 *mt9v022 = to_mt9v022(client);
 189
 190        if (enable)
 191                /* Switch to master "normal" mode */
 192                mt9v022->chip_control &= ~0x10;
 193        else
 194                /* Switch to snapshot mode */
 195                mt9v022->chip_control |= 0x10;
 196
 197        if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0)
 198                return -EIO;
 199        return 0;
 200}
 201
 202static int mt9v022_set_bus_param(struct soc_camera_device *icd,
 203                                 unsigned long flags)
 204{
 205        struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
 206        struct mt9v022 *mt9v022 = to_mt9v022(client);
 207        struct soc_camera_link *icl = to_soc_camera_link(icd);
 208        unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
 209        int ret;
 210        u16 pixclk = 0;
 211
 212        /* Only one width bit may be set */
 213        if (!is_power_of_2(width_flag))
 214                return -EINVAL;
 215
 216        if (icl->set_bus_param) {
 217                ret = icl->set_bus_param(icl, width_flag);
 218                if (ret)
 219                        return ret;
 220        } else {
 221                /*
 222                 * Without board specific bus width settings we only support the
 223                 * sensors native bus width
 224                 */
 225                if (width_flag != SOCAM_DATAWIDTH_10)
 226                        return -EINVAL;
 227        }
 228
 229        flags = soc_camera_apply_sensor_flags(icl, flags);
 230
 231        if (flags & SOCAM_PCLK_SAMPLE_FALLING)
 232                pixclk |= 0x10;
 233
 234        if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH))
 235                pixclk |= 0x1;
 236
 237        if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
 238                pixclk |= 0x2;
 239
 240        ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
 241        if (ret < 0)
 242                return ret;
 243
 244        if (!(flags & SOCAM_MASTER))
 245                mt9v022->chip_control &= ~0x8;
 246
 247        ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
 248        if (ret < 0)
 249                return ret;
 250
 251        dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
 252                pixclk, mt9v022->chip_control);
 253
 254        return 0;
 255}
 256
 257static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
 258{
 259        struct soc_camera_link *icl = to_soc_camera_link(icd);
 260        unsigned int flags = SOCAM_MASTER | SOCAM_SLAVE |
 261                SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
 262                SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
 263                SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
 264                SOCAM_DATA_ACTIVE_HIGH;
 265
 266        if (icl->query_bus_param)
 267                flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
 268        else
 269                flags |= SOCAM_DATAWIDTH_10;
 270
 271        return soc_camera_apply_sensor_flags(icl, flags);
 272}
 273
 274static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 275{
 276        struct i2c_client *client = v4l2_get_subdevdata(sd);
 277        struct mt9v022 *mt9v022 = to_mt9v022(client);
 278        struct v4l2_rect rect = a->c;
 279        int ret;
 280
 281        /* Bayer format - even size lengths */
 282        if (mt9v022->fmts == mt9v022_colour_fmts) {
 283                rect.width      = ALIGN(rect.width, 2);
 284                rect.height     = ALIGN(rect.height, 2);
 285                /* Let the user play with the starting pixel */
 286        }
 287
 288        soc_camera_limit_side(&rect.left, &rect.width,
 289                     MT9V022_COLUMN_SKIP, MT9V022_MIN_WIDTH, MT9V022_MAX_WIDTH);
 290
 291        soc_camera_limit_side(&rect.top, &rect.height,
 292                     MT9V022_ROW_SKIP, MT9V022_MIN_HEIGHT, MT9V022_MAX_HEIGHT);
 293
 294        /* Like in example app. Contradicts the datasheet though */
 295        ret = reg_read(client, MT9V022_AEC_AGC_ENABLE);
 296        if (ret >= 0) {
 297                if (ret & 1) /* Autoexposure */
 298                        ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
 299                                        rect.height + mt9v022->y_skip_top + 43);
 300                else
 301                        ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
 302                                        rect.height + mt9v022->y_skip_top + 43);
 303        }
 304        /* Setup frame format: defaults apart from width and height */
 305        if (!ret)
 306                ret = reg_write(client, MT9V022_COLUMN_START, rect.left);
 307        if (!ret)
 308                ret = reg_write(client, MT9V022_ROW_START, rect.top);
 309        if (!ret)
 310                /*
 311                 * Default 94, Phytec driver says:
 312                 * "width + horizontal blank >= 660"
 313                 */
 314                ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
 315                                rect.width > 660 - 43 ? 43 :
 316                                660 - rect.width);
 317        if (!ret)
 318                ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45);
 319        if (!ret)
 320                ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width);
 321        if (!ret)
 322                ret = reg_write(client, MT9V022_WINDOW_HEIGHT,
 323                                rect.height + mt9v022->y_skip_top);
 324
 325        if (ret < 0)
 326                return ret;
 327
 328        dev_dbg(&client->dev, "Frame %dx%d pixel\n", rect.width, rect.height);
 329
 330        mt9v022->rect = rect;
 331
 332        return 0;
 333}
 334
 335static int mt9v022_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 336{
 337        struct i2c_client *client = v4l2_get_subdevdata(sd);
 338        struct mt9v022 *mt9v022 = to_mt9v022(client);
 339
 340        a->c    = mt9v022->rect;
 341        a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 342
 343        return 0;
 344}
 345
 346static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 347{
 348        a->bounds.left                  = MT9V022_COLUMN_SKIP;
 349        a->bounds.top                   = MT9V022_ROW_SKIP;
 350        a->bounds.width                 = MT9V022_MAX_WIDTH;
 351        a->bounds.height                = MT9V022_MAX_HEIGHT;
 352        a->defrect                      = a->bounds;
 353        a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 354        a->pixelaspect.numerator        = 1;
 355        a->pixelaspect.denominator      = 1;
 356
 357        return 0;
 358}
 359
 360static int mt9v022_g_fmt(struct v4l2_subdev *sd,
 361                         struct v4l2_mbus_framefmt *mf)
 362{
 363        struct i2c_client *client = v4l2_get_subdevdata(sd);
 364        struct mt9v022 *mt9v022 = to_mt9v022(client);
 365
 366        mf->width       = mt9v022->rect.width;
 367        mf->height      = mt9v022->rect.height;
 368        mf->code        = mt9v022->fmt->code;
 369        mf->colorspace  = mt9v022->fmt->colorspace;
 370        mf->field       = V4L2_FIELD_NONE;
 371
 372        return 0;
 373}
 374
 375static int mt9v022_s_fmt(struct v4l2_subdev *sd,
 376                         struct v4l2_mbus_framefmt *mf)
 377{
 378        struct i2c_client *client = v4l2_get_subdevdata(sd);
 379        struct mt9v022 *mt9v022 = to_mt9v022(client);
 380        struct v4l2_crop a = {
 381                .c = {
 382                        .left   = mt9v022->rect.left,
 383                        .top    = mt9v022->rect.top,
 384                        .width  = mf->width,
 385                        .height = mf->height,
 386                },
 387        };
 388        int ret;
 389
 390        /*
 391         * The caller provides a supported format, as verified per call to
 392         * icd->try_fmt(), datawidth is from our supported format list
 393         */
 394        switch (mf->code) {
 395        case V4L2_MBUS_FMT_Y8_1X8:
 396        case V4L2_MBUS_FMT_Y10_1X10:
 397                if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
 398                        return -EINVAL;
 399                break;
 400        case V4L2_MBUS_FMT_SBGGR8_1X8:
 401        case V4L2_MBUS_FMT_SBGGR10_1X10:
 402                if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
 403                        return -EINVAL;
 404                break;
 405        default:
 406                return -EINVAL;
 407        }
 408
 409        /* No support for scaling on this camera, just crop. */
 410        ret = mt9v022_s_crop(sd, &a);
 411        if (!ret) {
 412                mf->width       = mt9v022->rect.width;
 413                mf->height      = mt9v022->rect.height;
 414                mt9v022->fmt    = mt9v022_find_datafmt(mf->code,
 415                                        mt9v022->fmts, mt9v022->num_fmts);
 416                mf->colorspace  = mt9v022->fmt->colorspace;
 417        }
 418
 419        return ret;
 420}
 421
 422static int mt9v022_try_fmt(struct v4l2_subdev *sd,
 423                           struct v4l2_mbus_framefmt *mf)
 424{
 425        struct i2c_client *client = v4l2_get_subdevdata(sd);
 426        struct mt9v022 *mt9v022 = to_mt9v022(client);
 427        const struct mt9v022_datafmt *fmt;
 428        int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
 429                mf->code == V4L2_MBUS_FMT_SBGGR10_1X10;
 430
 431        v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH,
 432                MT9V022_MAX_WIDTH, align,
 433                &mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top,
 434                MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0);
 435
 436        fmt = mt9v022_find_datafmt(mf->code, mt9v022->fmts,
 437                                   mt9v022->num_fmts);
 438        if (!fmt) {
 439                fmt = mt9v022->fmt;
 440                mf->code = fmt->code;
 441        }
 442
 443        mf->colorspace  = fmt->colorspace;
 444
 445        return 0;
 446}
 447
 448static int mt9v022_g_chip_ident(struct v4l2_subdev *sd,
 449                                struct v4l2_dbg_chip_ident *id)
 450{
 451        struct i2c_client *client = v4l2_get_subdevdata(sd);
 452        struct mt9v022 *mt9v022 = to_mt9v022(client);
 453
 454        if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
 455                return -EINVAL;
 456
 457        if (id->match.addr != client->addr)
 458                return -ENODEV;
 459
 460        id->ident       = mt9v022->model;
 461        id->revision    = 0;
 462
 463        return 0;
 464}
 465
 466#ifdef CONFIG_VIDEO_ADV_DEBUG
 467static int mt9v022_g_register(struct v4l2_subdev *sd,
 468                              struct v4l2_dbg_register *reg)
 469{
 470        struct i2c_client *client = v4l2_get_subdevdata(sd);
 471
 472        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
 473                return -EINVAL;
 474
 475        if (reg->match.addr != client->addr)
 476                return -ENODEV;
 477
 478        reg->size = 2;
 479        reg->val = reg_read(client, reg->reg);
 480
 481        if (reg->val > 0xffff)
 482                return -EIO;
 483
 484        return 0;
 485}
 486
 487static int mt9v022_s_register(struct v4l2_subdev *sd,
 488                              struct v4l2_dbg_register *reg)
 489{
 490        struct i2c_client *client = v4l2_get_subdevdata(sd);
 491
 492        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
 493                return -EINVAL;
 494
 495        if (reg->match.addr != client->addr)
 496                return -ENODEV;
 497
 498        if (reg_write(client, reg->reg, reg->val) < 0)
 499                return -EIO;
 500
 501        return 0;
 502}
 503#endif
 504
 505static const struct v4l2_queryctrl mt9v022_controls[] = {
 506        {
 507                .id             = V4L2_CID_VFLIP,
 508                .type           = V4L2_CTRL_TYPE_BOOLEAN,
 509                .name           = "Flip Vertically",
 510                .minimum        = 0,
 511                .maximum        = 1,
 512                .step           = 1,
 513                .default_value  = 0,
 514        }, {
 515                .id             = V4L2_CID_HFLIP,
 516                .type           = V4L2_CTRL_TYPE_BOOLEAN,
 517                .name           = "Flip Horizontally",
 518                .minimum        = 0,
 519                .maximum        = 1,
 520                .step           = 1,
 521                .default_value  = 0,
 522        }, {
 523                .id             = V4L2_CID_GAIN,
 524                .type           = V4L2_CTRL_TYPE_INTEGER,
 525                .name           = "Analog Gain",
 526                .minimum        = 64,
 527                .maximum        = 127,
 528                .step           = 1,
 529                .default_value  = 64,
 530                .flags          = V4L2_CTRL_FLAG_SLIDER,
 531        }, {
 532                .id             = V4L2_CID_EXPOSURE,
 533                .type           = V4L2_CTRL_TYPE_INTEGER,
 534                .name           = "Exposure",
 535                .minimum        = 1,
 536                .maximum        = 255,
 537                .step           = 1,
 538                .default_value  = 255,
 539                .flags          = V4L2_CTRL_FLAG_SLIDER,
 540        }, {
 541                .id             = V4L2_CID_AUTOGAIN,
 542                .type           = V4L2_CTRL_TYPE_BOOLEAN,
 543                .name           = "Automatic Gain",
 544                .minimum        = 0,
 545                .maximum        = 1,
 546                .step           = 1,
 547                .default_value  = 1,
 548        }, {
 549                .id             = V4L2_CID_EXPOSURE_AUTO,
 550                .type           = V4L2_CTRL_TYPE_BOOLEAN,
 551                .name           = "Automatic Exposure",
 552                .minimum        = 0,
 553                .maximum        = 1,
 554                .step           = 1,
 555                .default_value  = 1,
 556        }
 557};
 558
 559static struct soc_camera_ops mt9v022_ops = {
 560        .set_bus_param          = mt9v022_set_bus_param,
 561        .query_bus_param        = mt9v022_query_bus_param,
 562        .controls               = mt9v022_controls,
 563        .num_controls           = ARRAY_SIZE(mt9v022_controls),
 564};
 565
 566static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 567{
 568        struct i2c_client *client = v4l2_get_subdevdata(sd);
 569        const struct v4l2_queryctrl *qctrl;
 570        unsigned long range;
 571        int data;
 572
 573        qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
 574
 575        switch (ctrl->id) {
 576        case V4L2_CID_VFLIP:
 577                data = reg_read(client, MT9V022_READ_MODE);
 578                if (data < 0)
 579                        return -EIO;
 580                ctrl->value = !!(data & 0x10);
 581                break;
 582        case V4L2_CID_HFLIP:
 583                data = reg_read(client, MT9V022_READ_MODE);
 584                if (data < 0)
 585                        return -EIO;
 586                ctrl->value = !!(data & 0x20);
 587                break;
 588        case V4L2_CID_EXPOSURE_AUTO:
 589                data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
 590                if (data < 0)
 591                        return -EIO;
 592                ctrl->value = !!(data & 0x1);
 593                break;
 594        case V4L2_CID_AUTOGAIN:
 595                data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
 596                if (data < 0)
 597                        return -EIO;
 598                ctrl->value = !!(data & 0x2);
 599                break;
 600        case V4L2_CID_GAIN:
 601                data = reg_read(client, MT9V022_ANALOG_GAIN);
 602                if (data < 0)
 603                        return -EIO;
 604
 605                range = qctrl->maximum - qctrl->minimum;
 606                ctrl->value = ((data - 16) * range + 24) / 48 + qctrl->minimum;
 607
 608                break;
 609        case V4L2_CID_EXPOSURE:
 610                data = reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH);
 611                if (data < 0)
 612                        return -EIO;
 613
 614                range = qctrl->maximum - qctrl->minimum;
 615                ctrl->value = ((data - 1) * range + 239) / 479 + qctrl->minimum;
 616
 617                break;
 618        }
 619        return 0;
 620}
 621
 622static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 623{
 624        int data;
 625        struct i2c_client *client = v4l2_get_subdevdata(sd);
 626        const struct v4l2_queryctrl *qctrl;
 627
 628        qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
 629        if (!qctrl)
 630                return -EINVAL;
 631
 632        switch (ctrl->id) {
 633        case V4L2_CID_VFLIP:
 634                if (ctrl->value)
 635                        data = reg_set(client, MT9V022_READ_MODE, 0x10);
 636                else
 637                        data = reg_clear(client, MT9V022_READ_MODE, 0x10);
 638                if (data < 0)
 639                        return -EIO;
 640                break;
 641        case V4L2_CID_HFLIP:
 642                if (ctrl->value)
 643                        data = reg_set(client, MT9V022_READ_MODE, 0x20);
 644                else
 645                        data = reg_clear(client, MT9V022_READ_MODE, 0x20);
 646                if (data < 0)
 647                        return -EIO;
 648                break;
 649        case V4L2_CID_GAIN:
 650                /* mt9v022 has minimum == default */
 651                if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
 652                        return -EINVAL;
 653                else {
 654                        unsigned long range = qctrl->maximum - qctrl->minimum;
 655                        /* Valid values 16 to 64, 32 to 64 must be even. */
 656                        unsigned long gain = ((ctrl->value - qctrl->minimum) *
 657                                              48 + range / 2) / range + 16;
 658                        if (gain >= 32)
 659                                gain &= ~1;
 660                        /*
 661                         * The user wants to set gain manually, hope, she
 662                         * knows, what she's doing... Switch AGC off.
 663                         */
 664
 665                        if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
 666                                return -EIO;
 667
 668                        dev_dbg(&client->dev, "Setting gain from %d to %lu\n",
 669                                reg_read(client, MT9V022_ANALOG_GAIN), gain);
 670                        if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0)
 671                                return -EIO;
 672                }
 673                break;
 674        case V4L2_CID_EXPOSURE:
 675                /* mt9v022 has maximum == default */
 676                if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
 677                        return -EINVAL;
 678                else {
 679                        unsigned long range = qctrl->maximum - qctrl->minimum;
 680                        unsigned long shutter = ((ctrl->value - qctrl->minimum) *
 681                                                 479 + range / 2) / range + 1;
 682                        /*
 683                         * The user wants to set shutter width manually, hope,
 684                         * she knows, what she's doing... Switch AEC off.
 685                         */
 686
 687                        if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
 688                                return -EIO;
 689
 690                        dev_dbg(&client->dev, "Shutter width from %d to %lu\n",
 691                                reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
 692                                shutter);
 693                        if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
 694                                      shutter) < 0)
 695                                return -EIO;
 696                }
 697                break;
 698        case V4L2_CID_AUTOGAIN:
 699                if (ctrl->value)
 700                        data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2);
 701                else
 702                        data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2);
 703                if (data < 0)
 704                        return -EIO;
 705                break;
 706        case V4L2_CID_EXPOSURE_AUTO:
 707                if (ctrl->value)
 708                        data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
 709                else
 710                        data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
 711                if (data < 0)
 712                        return -EIO;
 713                break;
 714        }
 715        return 0;
 716}
 717
 718/*
 719 * Interface active, can use i2c. If it fails, it can indeed mean, that
 720 * this wasn't our capture interface, so, we wait for the right one
 721 */
 722static int mt9v022_video_probe(struct soc_camera_device *icd,
 723                               struct i2c_client *client)
 724{
 725        struct mt9v022 *mt9v022 = to_mt9v022(client);
 726        struct soc_camera_link *icl = to_soc_camera_link(icd);
 727        s32 data;
 728        int ret;
 729        unsigned long flags;
 730
 731        if (!icd->dev.parent ||
 732            to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
 733                return -ENODEV;
 734
 735        /* Read out the chip version register */
 736        data = reg_read(client, MT9V022_CHIP_VERSION);
 737
 738        /* must be 0x1311 or 0x1313 */
 739        if (data != 0x1311 && data != 0x1313) {
 740                ret = -ENODEV;
 741                dev_info(&client->dev, "No MT9V022 found, ID register 0x%x\n",
 742                         data);
 743                goto ei2c;
 744        }
 745
 746        /* Soft reset */
 747        ret = reg_write(client, MT9V022_RESET, 1);
 748        if (ret < 0)
 749                goto ei2c;
 750        /* 15 clock cycles */
 751        udelay(200);
 752        if (reg_read(client, MT9V022_RESET)) {
 753                dev_err(&client->dev, "Resetting MT9V022 failed!\n");
 754                if (ret > 0)
 755                        ret = -EIO;
 756                goto ei2c;
 757        }
 758
 759        /* Set monochrome or colour sensor type */
 760        if (sensor_type && (!strcmp("colour", sensor_type) ||
 761                            !strcmp("color", sensor_type))) {
 762                ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
 763                mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
 764                mt9v022->fmts = mt9v022_colour_fmts;
 765        } else {
 766                ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11);
 767                mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
 768                mt9v022->fmts = mt9v022_monochrome_fmts;
 769        }
 770
 771        if (ret < 0)
 772                goto ei2c;
 773
 774        mt9v022->num_fmts = 0;
 775
 776        /*
 777         * This is a 10bit sensor, so by default we only allow 10bit.
 778         * The platform may support different bus widths due to
 779         * different routing of the data lines.
 780         */
 781        if (icl->query_bus_param)
 782                flags = icl->query_bus_param(icl);
 783        else
 784                flags = SOCAM_DATAWIDTH_10;
 785
 786        if (flags & SOCAM_DATAWIDTH_10)
 787                mt9v022->num_fmts++;
 788        else
 789                mt9v022->fmts++;
 790
 791        if (flags & SOCAM_DATAWIDTH_8)
 792                mt9v022->num_fmts++;
 793
 794        mt9v022->fmt = &mt9v022->fmts[0];
 795
 796        dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
 797                 data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
 798                 "monochrome" : "colour");
 799
 800        ret = mt9v022_init(client);
 801        if (ret < 0)
 802                dev_err(&client->dev, "Failed to initialise the camera\n");
 803
 804ei2c:
 805        return ret;
 806}
 807
 808static void mt9v022_video_remove(struct soc_camera_device *icd)
 809{
 810        struct soc_camera_link *icl = to_soc_camera_link(icd);
 811
 812        dev_dbg(&icd->dev, "Video removed: %p, %p\n",
 813                icd->dev.parent, icd->vdev);
 814        if (icl->free_bus)
 815                icl->free_bus(icl);
 816}
 817
 818static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
 819{
 820        struct i2c_client *client = v4l2_get_subdevdata(sd);
 821        struct mt9v022 *mt9v022 = to_mt9v022(client);
 822
 823        *lines = mt9v022->y_skip_top;
 824
 825        return 0;
 826}
 827
 828static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
 829        .g_ctrl         = mt9v022_g_ctrl,
 830        .s_ctrl         = mt9v022_s_ctrl,
 831        .g_chip_ident   = mt9v022_g_chip_ident,
 832#ifdef CONFIG_VIDEO_ADV_DEBUG
 833        .g_register     = mt9v022_g_register,
 834        .s_register     = mt9v022_s_register,
 835#endif
 836};
 837
 838static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
 839                            enum v4l2_mbus_pixelcode *code)
 840{
 841        struct i2c_client *client = v4l2_get_subdevdata(sd);
 842        struct mt9v022 *mt9v022 = to_mt9v022(client);
 843
 844        if (index >= mt9v022->num_fmts)
 845                return -EINVAL;
 846
 847        *code = mt9v022->fmts[index].code;
 848        return 0;
 849}
 850
 851static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
 852        .s_stream       = mt9v022_s_stream,
 853        .s_mbus_fmt     = mt9v022_s_fmt,
 854        .g_mbus_fmt     = mt9v022_g_fmt,
 855        .try_mbus_fmt   = mt9v022_try_fmt,
 856        .s_crop         = mt9v022_s_crop,
 857        .g_crop         = mt9v022_g_crop,
 858        .cropcap        = mt9v022_cropcap,
 859        .enum_mbus_fmt  = mt9v022_enum_fmt,
 860};
 861
 862static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
 863        .g_skip_top_lines       = mt9v022_g_skip_top_lines,
 864};
 865
 866static struct v4l2_subdev_ops mt9v022_subdev_ops = {
 867        .core   = &mt9v022_subdev_core_ops,
 868        .video  = &mt9v022_subdev_video_ops,
 869        .sensor = &mt9v022_subdev_sensor_ops,
 870};
 871
 872static int mt9v022_probe(struct i2c_client *client,
 873                         const struct i2c_device_id *did)
 874{
 875        struct mt9v022 *mt9v022;
 876        struct soc_camera_device *icd = client->dev.platform_data;
 877        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
 878        struct soc_camera_link *icl;
 879        int ret;
 880
 881        if (!icd) {
 882                dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
 883                return -EINVAL;
 884        }
 885
 886        icl = to_soc_camera_link(icd);
 887        if (!icl) {
 888                dev_err(&client->dev, "MT9V022 driver needs platform data\n");
 889                return -EINVAL;
 890        }
 891
 892        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
 893                dev_warn(&adapter->dev,
 894                         "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
 895                return -EIO;
 896        }
 897
 898        mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL);
 899        if (!mt9v022)
 900                return -ENOMEM;
 901
 902        v4l2_i2c_subdev_init(&mt9v022->subdev, client, &mt9v022_subdev_ops);
 903
 904        mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
 905
 906        icd->ops                = &mt9v022_ops;
 907        /*
 908         * MT9V022 _really_ corrupts the first read out line.
 909         * TODO: verify on i.MX31
 910         */
 911        mt9v022->y_skip_top     = 1;
 912        mt9v022->rect.left      = MT9V022_COLUMN_SKIP;
 913        mt9v022->rect.top       = MT9V022_ROW_SKIP;
 914        mt9v022->rect.width     = MT9V022_MAX_WIDTH;
 915        mt9v022->rect.height    = MT9V022_MAX_HEIGHT;
 916
 917        ret = mt9v022_video_probe(icd, client);
 918        if (ret) {
 919                icd->ops = NULL;
 920                kfree(mt9v022);
 921        }
 922
 923        return ret;
 924}
 925
 926static int mt9v022_remove(struct i2c_client *client)
 927{
 928        struct mt9v022 *mt9v022 = to_mt9v022(client);
 929        struct soc_camera_device *icd = client->dev.platform_data;
 930
 931        icd->ops = NULL;
 932        mt9v022_video_remove(icd);
 933        kfree(mt9v022);
 934
 935        return 0;
 936}
 937static const struct i2c_device_id mt9v022_id[] = {
 938        { "mt9v022", 0 },
 939        { }
 940};
 941MODULE_DEVICE_TABLE(i2c, mt9v022_id);
 942
 943static struct i2c_driver mt9v022_i2c_driver = {
 944        .driver = {
 945                .name = "mt9v022",
 946        },
 947        .probe          = mt9v022_probe,
 948        .remove         = mt9v022_remove,
 949        .id_table       = mt9v022_id,
 950};
 951
 952static int __init mt9v022_mod_init(void)
 953{
 954        return i2c_add_driver(&mt9v022_i2c_driver);
 955}
 956
 957static void __exit mt9v022_mod_exit(void)
 958{
 959        i2c_del_driver(&mt9v022_i2c_driver);
 960}
 961
 962module_init(mt9v022_mod_init);
 963module_exit(mt9v022_mod_exit);
 964
 965MODULE_DESCRIPTION("Micron MT9V022 Camera driver");
 966MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
 967MODULE_LICENSE("GPL");
 968