linux/drivers/media/video/mt9v011.c
<<
>>
Prefs
   1/*
   2 * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor
   3 *
   4 * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
   5 * This code is placed under the terms of the GNU General Public License v2
   6 */
   7
   8#include <linux/i2c.h>
   9#include <linux/videodev2.h>
  10#include <linux/delay.h>
  11#include <asm/div64.h>
  12#include <media/v4l2-device.h>
  13#include "mt9v011.h"
  14#include <media/v4l2-i2c-drv.h>
  15#include <media/v4l2-chip-ident.h>
  16
  17MODULE_DESCRIPTION("Micron mt9v011 sensor driver");
  18MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
  19MODULE_LICENSE("GPL");
  20
  21
  22static int debug;
  23module_param(debug, int, 0);
  24MODULE_PARM_DESC(debug, "Debug level (0-2)");
  25
  26/* supported controls */
  27static struct v4l2_queryctrl mt9v011_qctrl[] = {
  28        {
  29                .id = V4L2_CID_GAIN,
  30                .type = V4L2_CTRL_TYPE_INTEGER,
  31                .name = "Gain",
  32                .minimum = 0,
  33                .maximum = (1 << 10) - 1,
  34                .step = 1,
  35                .default_value = 0x0020,
  36                .flags = 0,
  37        }, {
  38                .id = V4L2_CID_RED_BALANCE,
  39                .type = V4L2_CTRL_TYPE_INTEGER,
  40                .name = "Red Balance",
  41                .minimum = -1 << 9,
  42                .maximum = (1 << 9) - 1,
  43                .step = 1,
  44                .default_value = 0,
  45                .flags = 0,
  46        }, {
  47                .id = V4L2_CID_BLUE_BALANCE,
  48                .type = V4L2_CTRL_TYPE_INTEGER,
  49                .name = "Blue Balance",
  50                .minimum = -1 << 9,
  51                .maximum = (1 << 9) - 1,
  52                .step = 1,
  53                .default_value = 0,
  54                .flags = 0,
  55        }, {
  56                .id      = V4L2_CID_HFLIP,
  57                .type    = V4L2_CTRL_TYPE_BOOLEAN,
  58                .name    = "Mirror",
  59                .minimum = 0,
  60                .maximum = 1,
  61                .step    = 1,
  62                .default_value = 0,
  63                .flags = 0,
  64        }, {
  65                .id      = V4L2_CID_VFLIP,
  66                .type    = V4L2_CTRL_TYPE_BOOLEAN,
  67                .name    = "Vflip",
  68                .minimum = 0,
  69                .maximum = 1,
  70                .step    = 1,
  71                .default_value = 0,
  72                .flags = 0,
  73        }, {
  74        }
  75};
  76
  77struct mt9v011 {
  78        struct v4l2_subdev sd;
  79        unsigned width, height;
  80        unsigned xtal;
  81        unsigned hflip:1;
  82        unsigned vflip:1;
  83
  84        u16 global_gain, red_bal, blue_bal;
  85};
  86
  87static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd)
  88{
  89        return container_of(sd, struct mt9v011, sd);
  90}
  91
  92static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr)
  93{
  94        struct i2c_client *c = v4l2_get_subdevdata(sd);
  95        __be16 buffer;
  96        int rc, val;
  97
  98        rc = i2c_master_send(c, &addr, 1);
  99        if (rc != 1)
 100                v4l2_dbg(0, debug, sd,
 101                         "i2c i/o error: rc == %d (should be 1)\n", rc);
 102
 103        msleep(10);
 104
 105        rc = i2c_master_recv(c, (char *)&buffer, 2);
 106        if (rc != 2)
 107                v4l2_dbg(0, debug, sd,
 108                         "i2c i/o error: rc == %d (should be 2)\n", rc);
 109
 110        val = be16_to_cpu(buffer);
 111
 112        v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val);
 113
 114        return val;
 115}
 116
 117static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr,
 118                                 u16 value)
 119{
 120        struct i2c_client *c = v4l2_get_subdevdata(sd);
 121        unsigned char buffer[3];
 122        int rc;
 123
 124        buffer[0] = addr;
 125        buffer[1] = value >> 8;
 126        buffer[2] = value & 0xff;
 127
 128        v4l2_dbg(2, debug, sd,
 129                 "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value);
 130        rc = i2c_master_send(c, buffer, 3);
 131        if (rc != 3)
 132                v4l2_dbg(0, debug, sd,
 133                         "i2c i/o error: rc == %d (should be 3)\n", rc);
 134}
 135
 136
 137struct i2c_reg_value {
 138        unsigned char reg;
 139        u16           value;
 140};
 141
 142/*
 143 * Values used at the original driver
 144 * Some values are marked as Reserved at the datasheet
 145 */
 146static const struct i2c_reg_value mt9v011_init_default[] = {
 147                { R0D_MT9V011_RESET, 0x0001 },
 148                { R0D_MT9V011_RESET, 0x0000 },
 149
 150                { R0C_MT9V011_SHUTTER_DELAY, 0x0000 },
 151                { R09_MT9V011_SHUTTER_WIDTH, 0x1fc },
 152
 153                { R0A_MT9V011_CLK_SPEED, 0x0000 },
 154                { R1E_MT9V011_DIGITAL_ZOOM,  0x0000 },
 155
 156                { R07_MT9V011_OUT_CTRL, 0x0002 },       /* chip enable */
 157};
 158
 159static void set_balance(struct v4l2_subdev *sd)
 160{
 161        struct mt9v011 *core = to_mt9v011(sd);
 162        u16 green1_gain, green2_gain, blue_gain, red_gain;
 163
 164        green1_gain = core->global_gain;
 165        green2_gain = core->global_gain;
 166
 167        blue_gain = core->global_gain +
 168                    core->global_gain * core->blue_bal / (1 << 9);
 169
 170        red_gain = core->global_gain +
 171                   core->global_gain * core->blue_bal / (1 << 9);
 172
 173        mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain);
 174        mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN,  green1_gain);
 175        mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain);
 176        mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain);
 177}
 178
 179static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator)
 180{
 181        struct mt9v011 *core = to_mt9v011(sd);
 182        unsigned height, width, hblank, vblank, speed;
 183        unsigned row_time, t_time;
 184        u64 frames_per_ms;
 185        unsigned tmp;
 186
 187        height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
 188        width = mt9v011_read(sd, R04_MT9V011_WIDTH);
 189        hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
 190        vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
 191        speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED);
 192
 193        row_time = (width + 113 + hblank) * (speed + 2);
 194        t_time = row_time * (height + vblank + 1);
 195
 196        frames_per_ms = core->xtal * 1000l;
 197        do_div(frames_per_ms, t_time);
 198        tmp = frames_per_ms;
 199
 200        v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n",
 201                tmp / 1000, tmp % 1000, t_time);
 202
 203        if (numerator && denominator) {
 204                *numerator = 1000;
 205                *denominator = (u32)frames_per_ms;
 206        }
 207}
 208
 209static u16 calc_speed(struct v4l2_subdev *sd, u32 numerator, u32 denominator)
 210{
 211        struct mt9v011 *core = to_mt9v011(sd);
 212        unsigned height, width, hblank, vblank;
 213        unsigned row_time, line_time;
 214        u64 t_time, speed;
 215
 216        /* Avoid bogus calculus */
 217        if (!numerator || !denominator)
 218                return 0;
 219
 220        height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
 221        width = mt9v011_read(sd, R04_MT9V011_WIDTH);
 222        hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
 223        vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
 224
 225        row_time = width + 113 + hblank;
 226        line_time = height + vblank + 1;
 227
 228        t_time = core->xtal * ((u64)numerator);
 229        /* round to the closest value */
 230        t_time += denominator / 2;
 231        do_div(t_time, denominator);
 232
 233        speed = t_time;
 234        do_div(speed, row_time * line_time);
 235
 236        /* Avoid having a negative value for speed */
 237        if (speed < 2)
 238                speed = 0;
 239        else
 240                speed -= 2;
 241
 242        /* Avoid speed overflow */
 243        if (speed > 15)
 244                return 15;
 245
 246        return (u16)speed;
 247}
 248
 249static void set_res(struct v4l2_subdev *sd)
 250{
 251        struct mt9v011 *core = to_mt9v011(sd);
 252        unsigned vstart, hstart;
 253
 254        /*
 255         * The mt9v011 doesn't have scaling. So, in order to select the desired
 256         * resolution, we're cropping at the middle of the sensor.
 257         * hblank and vblank should be adjusted, in order to warrant that
 258         * we'll preserve the line timings for 30 fps, no matter what resolution
 259         * is selected.
 260         * NOTE: datasheet says that width (and height) should be filled with
 261         * width-1. However, this doesn't work, since one pixel per line will
 262         * be missing.
 263         */
 264
 265        hstart = 14 + (640 - core->width) / 2;
 266        mt9v011_write(sd, R02_MT9V011_COLSTART, hstart);
 267        mt9v011_write(sd, R04_MT9V011_WIDTH, core->width);
 268        mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width);
 269
 270        vstart = 8 + (480 - core->height) / 2;
 271        mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart);
 272        mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height);
 273        mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height);
 274
 275        calc_fps(sd, NULL, NULL);
 276};
 277
 278static void set_read_mode(struct v4l2_subdev *sd)
 279{
 280        struct mt9v011 *core = to_mt9v011(sd);
 281        unsigned mode = 0x1000;
 282
 283        if (core->hflip)
 284                mode |= 0x4000;
 285
 286        if (core->vflip)
 287                mode |= 0x8000;
 288
 289        mt9v011_write(sd, R20_MT9V011_READ_MODE, mode);
 290}
 291
 292static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
 293{
 294        int i;
 295
 296        for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++)
 297                mt9v011_write(sd, mt9v011_init_default[i].reg,
 298                               mt9v011_init_default[i].value);
 299
 300        set_balance(sd);
 301        set_res(sd);
 302        set_read_mode(sd);
 303
 304        return 0;
 305};
 306
 307static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 308{
 309        struct mt9v011 *core = to_mt9v011(sd);
 310
 311        v4l2_dbg(1, debug, sd, "g_ctrl called\n");
 312
 313        switch (ctrl->id) {
 314        case V4L2_CID_GAIN:
 315                ctrl->value = core->global_gain;
 316                return 0;
 317        case V4L2_CID_RED_BALANCE:
 318                ctrl->value = core->red_bal;
 319                return 0;
 320        case V4L2_CID_BLUE_BALANCE:
 321                ctrl->value = core->blue_bal;
 322                return 0;
 323        case V4L2_CID_HFLIP:
 324                ctrl->value = core->hflip ? 1 : 0;
 325                return 0;
 326        case V4L2_CID_VFLIP:
 327                ctrl->value = core->vflip ? 1 : 0;
 328                return 0;
 329        }
 330        return -EINVAL;
 331}
 332
 333static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 334{
 335        int i;
 336
 337        v4l2_dbg(1, debug, sd, "queryctrl called\n");
 338
 339        for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++)
 340                if (qc->id && qc->id == mt9v011_qctrl[i].id) {
 341                        memcpy(qc, &(mt9v011_qctrl[i]),
 342                               sizeof(*qc));
 343                        return 0;
 344                }
 345
 346        return -EINVAL;
 347}
 348
 349
 350static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 351{
 352        struct mt9v011 *core = to_mt9v011(sd);
 353        u8 i, n;
 354        n = ARRAY_SIZE(mt9v011_qctrl);
 355
 356        for (i = 0; i < n; i++) {
 357                if (ctrl->id != mt9v011_qctrl[i].id)
 358                        continue;
 359                if (ctrl->value < mt9v011_qctrl[i].minimum ||
 360                    ctrl->value > mt9v011_qctrl[i].maximum)
 361                        return -ERANGE;
 362                v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n",
 363                                        ctrl->id, ctrl->value);
 364                break;
 365        }
 366
 367        switch (ctrl->id) {
 368        case V4L2_CID_GAIN:
 369                core->global_gain = ctrl->value;
 370                break;
 371        case V4L2_CID_RED_BALANCE:
 372                core->red_bal = ctrl->value;
 373                break;
 374        case V4L2_CID_BLUE_BALANCE:
 375                core->blue_bal = ctrl->value;
 376                break;
 377        case V4L2_CID_HFLIP:
 378                core->hflip = ctrl->value;
 379                set_read_mode(sd);
 380                return 0;
 381        case V4L2_CID_VFLIP:
 382                core->vflip = ctrl->value;
 383                set_read_mode(sd);
 384                return 0;
 385        default:
 386                return -EINVAL;
 387        }
 388
 389        set_balance(sd);
 390
 391        return 0;
 392}
 393
 394static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
 395{
 396        if (fmt->index > 0)
 397                return -EINVAL;
 398
 399        fmt->flags = 0;
 400        strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG");
 401        fmt->pixelformat = V4L2_PIX_FMT_SGRBG8;
 402
 403        return 0;
 404}
 405
 406static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
 407{
 408        struct v4l2_pix_format *pix = &fmt->fmt.pix;
 409
 410        if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8)
 411                return -EINVAL;
 412
 413        v4l_bound_align_image(&pix->width, 48, 639, 1,
 414                              &pix->height, 32, 480, 1, 0);
 415
 416        return 0;
 417}
 418
 419static int mt9v011_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
 420{
 421        struct v4l2_captureparm *cp = &parms->parm.capture;
 422
 423        if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 424                return -EINVAL;
 425
 426        memset(cp, 0, sizeof(struct v4l2_captureparm));
 427        cp->capability = V4L2_CAP_TIMEPERFRAME;
 428        calc_fps(sd,
 429                 &cp->timeperframe.numerator,
 430                 &cp->timeperframe.denominator);
 431
 432        return 0;
 433}
 434
 435static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
 436{
 437        struct v4l2_captureparm *cp = &parms->parm.capture;
 438        struct v4l2_fract *tpf = &cp->timeperframe;
 439        u16 speed;
 440
 441        if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 442                return -EINVAL;
 443        if (cp->extendedmode != 0)
 444                return -EINVAL;
 445
 446        speed = calc_speed(sd, tpf->numerator, tpf->denominator);
 447
 448        mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed);
 449        v4l2_dbg(1, debug, sd, "Setting speed to %d\n", speed);
 450
 451        /* Recalculate and update fps info */
 452        calc_fps(sd, &tpf->numerator, &tpf->denominator);
 453
 454        return 0;
 455}
 456
 457static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
 458{
 459        struct v4l2_pix_format *pix = &fmt->fmt.pix;
 460        struct mt9v011 *core = to_mt9v011(sd);
 461        int rc;
 462
 463        rc = mt9v011_try_fmt(sd, fmt);
 464        if (rc < 0)
 465                return -EINVAL;
 466
 467        core->width = pix->width;
 468        core->height = pix->height;
 469
 470        set_res(sd);
 471
 472        return 0;
 473}
 474
 475static int mt9v011_s_config(struct v4l2_subdev *sd, int dumb, void *data)
 476{
 477        struct mt9v011 *core = to_mt9v011(sd);
 478        unsigned *xtal = data;
 479
 480        v4l2_dbg(1, debug, sd, "s_config called\n");
 481
 482        if (xtal) {
 483                core->xtal = *xtal;
 484                v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n",
 485                         *xtal / 1000000, (*xtal / 1000) % 1000);
 486        }
 487
 488        return 0;
 489}
 490
 491
 492#ifdef CONFIG_VIDEO_ADV_DEBUG
 493static int mt9v011_g_register(struct v4l2_subdev *sd,
 494                              struct v4l2_dbg_register *reg)
 495{
 496        struct i2c_client *client = v4l2_get_subdevdata(sd);
 497
 498        if (!v4l2_chip_match_i2c_client(client, &reg->match))
 499                return -EINVAL;
 500        if (!capable(CAP_SYS_ADMIN))
 501                return -EPERM;
 502
 503        reg->val = mt9v011_read(sd, reg->reg & 0xff);
 504        reg->size = 2;
 505
 506        return 0;
 507}
 508
 509static int mt9v011_s_register(struct v4l2_subdev *sd,
 510                              struct v4l2_dbg_register *reg)
 511{
 512        struct i2c_client *client = v4l2_get_subdevdata(sd);
 513
 514        if (!v4l2_chip_match_i2c_client(client, &reg->match))
 515                return -EINVAL;
 516        if (!capable(CAP_SYS_ADMIN))
 517                return -EPERM;
 518
 519        mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff);
 520
 521        return 0;
 522}
 523#endif
 524
 525static int mt9v011_g_chip_ident(struct v4l2_subdev *sd,
 526                                struct v4l2_dbg_chip_ident *chip)
 527{
 528        u16 version;
 529        struct i2c_client *client = v4l2_get_subdevdata(sd);
 530
 531        version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION);
 532
 533        return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011,
 534                                          version);
 535}
 536
 537static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
 538        .queryctrl = mt9v011_queryctrl,
 539        .g_ctrl = mt9v011_g_ctrl,
 540        .s_ctrl = mt9v011_s_ctrl,
 541        .reset = mt9v011_reset,
 542        .s_config = mt9v011_s_config,
 543        .g_chip_ident = mt9v011_g_chip_ident,
 544#ifdef CONFIG_VIDEO_ADV_DEBUG
 545        .g_register = mt9v011_g_register,
 546        .s_register = mt9v011_s_register,
 547#endif
 548};
 549
 550static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
 551        .enum_fmt = mt9v011_enum_fmt,
 552        .try_fmt = mt9v011_try_fmt,
 553        .s_fmt = mt9v011_s_fmt,
 554        .g_parm = mt9v011_g_parm,
 555        .s_parm = mt9v011_s_parm,
 556};
 557
 558static const struct v4l2_subdev_ops mt9v011_ops = {
 559        .core  = &mt9v011_core_ops,
 560        .video = &mt9v011_video_ops,
 561};
 562
 563
 564/****************************************************************************
 565                        I2C Client & Driver
 566 ****************************************************************************/
 567
 568static int mt9v011_probe(struct i2c_client *c,
 569                         const struct i2c_device_id *id)
 570{
 571        u16 version;
 572        struct mt9v011 *core;
 573        struct v4l2_subdev *sd;
 574
 575        /* Check if the adapter supports the needed features */
 576        if (!i2c_check_functionality(c->adapter,
 577             I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
 578                return -EIO;
 579
 580        core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL);
 581        if (!core)
 582                return -ENOMEM;
 583
 584        sd = &core->sd;
 585        v4l2_i2c_subdev_init(sd, c, &mt9v011_ops);
 586
 587        /* Check if the sensor is really a MT9V011 */
 588        version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION);
 589        if ((version != MT9V011_VERSION) &&
 590            (version != MT9V011_REV_B_VERSION)) {
 591                v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n",
 592                          version);
 593                kfree(core);
 594                return -EINVAL;
 595        }
 596
 597        core->global_gain = 0x0024;
 598        core->width  = 640;
 599        core->height = 480;
 600        core->xtal = 27000000;  /* Hz */
 601
 602        v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n",
 603                 c->addr << 1, c->adapter->name, version);
 604
 605        return 0;
 606}
 607
 608static int mt9v011_remove(struct i2c_client *c)
 609{
 610        struct v4l2_subdev *sd = i2c_get_clientdata(c);
 611
 612        v4l2_dbg(1, debug, sd,
 613                "mt9v011.c: removing mt9v011 adapter on address 0x%x\n",
 614                c->addr << 1);
 615
 616        v4l2_device_unregister_subdev(sd);
 617        kfree(to_mt9v011(sd));
 618        return 0;
 619}
 620
 621/* ----------------------------------------------------------------------- */
 622
 623static const struct i2c_device_id mt9v011_id[] = {
 624        { "mt9v011", 0 },
 625        { }
 626};
 627MODULE_DEVICE_TABLE(i2c, mt9v011_id);
 628
 629static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 630        .name = "mt9v011",
 631        .probe = mt9v011_probe,
 632        .remove = mt9v011_remove,
 633        .id_table = mt9v011_id,
 634};
 635