linux/drivers/staging/dream/camera/mt9d112.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
   3 */
   4
   5#include <linux/delay.h>
   6#include <linux/types.h>
   7#include <linux/i2c.h>
   8#include <linux/uaccess.h>
   9#include <linux/miscdevice.h>
  10#include <media/msm_camera.h>
  11#include <mach/gpio.h>
  12#include "mt9d112.h"
  13
  14/* Micron MT9D112 Registers and their values */
  15/* Sensor Core Registers */
  16#define  REG_MT9D112_MODEL_ID 0x3000
  17#define  MT9D112_MODEL_ID     0x1580
  18
  19/*  SOC Registers Page 1  */
  20#define  REG_MT9D112_SENSOR_RESET     0x301A
  21#define  REG_MT9D112_STANDBY_CONTROL  0x3202
  22#define  REG_MT9D112_MCU_BOOT         0x3386
  23
  24struct mt9d112_work {
  25        struct work_struct work;
  26};
  27
  28static struct  mt9d112_work *mt9d112_sensorw;
  29static struct  i2c_client *mt9d112_client;
  30
  31struct mt9d112_ctrl {
  32        const struct msm_camera_sensor_info *sensordata;
  33};
  34
  35
  36static struct mt9d112_ctrl *mt9d112_ctrl;
  37
  38static DECLARE_WAIT_QUEUE_HEAD(mt9d112_wait_queue);
  39DECLARE_MUTEX(mt9d112_sem);
  40
  41
  42/*=============================================================
  43        EXTERNAL DECLARATIONS
  44==============================================================*/
  45extern struct mt9d112_reg mt9d112_regs;
  46
  47
  48/*=============================================================*/
  49
  50static int mt9d112_reset(const struct msm_camera_sensor_info *dev)
  51{
  52        int rc = 0;
  53
  54        rc = gpio_request(dev->sensor_reset, "mt9d112");
  55
  56        if (!rc) {
  57                rc = gpio_direction_output(dev->sensor_reset, 0);
  58                mdelay(20);
  59                rc = gpio_direction_output(dev->sensor_reset, 1);
  60        }
  61
  62        gpio_free(dev->sensor_reset);
  63        return rc;
  64}
  65
  66static int32_t mt9d112_i2c_txdata(unsigned short saddr,
  67        unsigned char *txdata, int length)
  68{
  69        struct i2c_msg msg[] = {
  70                {
  71                        .addr = saddr,
  72                        .flags = 0,
  73                        .len = length,
  74                        .buf = txdata,
  75                },
  76        };
  77
  78        if (i2c_transfer(mt9d112_client->adapter, msg, 1) < 0) {
  79                CDBG("mt9d112_i2c_txdata failed\n");
  80                return -EIO;
  81        }
  82
  83        return 0;
  84}
  85
  86static int32_t mt9d112_i2c_write(unsigned short saddr,
  87        unsigned short waddr, unsigned short wdata, enum mt9d112_width width)
  88{
  89        int32_t rc = -EIO;
  90        unsigned char buf[4];
  91
  92        memset(buf, 0, sizeof(buf));
  93        switch (width) {
  94        case WORD_LEN: {
  95                buf[0] = (waddr & 0xFF00)>>8;
  96                buf[1] = (waddr & 0x00FF);
  97                buf[2] = (wdata & 0xFF00)>>8;
  98                buf[3] = (wdata & 0x00FF);
  99
 100                rc = mt9d112_i2c_txdata(saddr, buf, 4);
 101        }
 102                break;
 103
 104        case BYTE_LEN: {
 105                buf[0] = waddr;
 106                buf[1] = wdata;
 107                rc = mt9d112_i2c_txdata(saddr, buf, 2);
 108        }
 109                break;
 110
 111        default:
 112                break;
 113        }
 114
 115        if (rc < 0)
 116                CDBG(
 117                "i2c_write failed, addr = 0x%x, val = 0x%x!\n",
 118                waddr, wdata);
 119
 120        return rc;
 121}
 122
 123static int32_t mt9d112_i2c_write_table(
 124        struct mt9d112_i2c_reg_conf const *reg_conf_tbl,
 125        int num_of_items_in_table)
 126{
 127        int i;
 128        int32_t rc = -EIO;
 129
 130        for (i = 0; i < num_of_items_in_table; i++) {
 131                rc = mt9d112_i2c_write(mt9d112_client->addr,
 132                        reg_conf_tbl->waddr, reg_conf_tbl->wdata,
 133                        reg_conf_tbl->width);
 134                if (rc < 0)
 135                        break;
 136                if (reg_conf_tbl->mdelay_time != 0)
 137                        mdelay(reg_conf_tbl->mdelay_time);
 138                reg_conf_tbl++;
 139        }
 140
 141        return rc;
 142}
 143
 144static int mt9d112_i2c_rxdata(unsigned short saddr,
 145        unsigned char *rxdata, int length)
 146{
 147        struct i2c_msg msgs[] = {
 148        {
 149                .addr   = saddr,
 150                .flags = 0,
 151                .len   = 2,
 152                .buf   = rxdata,
 153        },
 154        {
 155                .addr   = saddr,
 156                .flags = I2C_M_RD,
 157                .len   = length,
 158                .buf   = rxdata,
 159        },
 160        };
 161
 162        if (i2c_transfer(mt9d112_client->adapter, msgs, 2) < 0) {
 163                CDBG("mt9d112_i2c_rxdata failed!\n");
 164                return -EIO;
 165        }
 166
 167        return 0;
 168}
 169
 170static int32_t mt9d112_i2c_read(unsigned short   saddr,
 171        unsigned short raddr, unsigned short *rdata, enum mt9d112_width width)
 172{
 173        int32_t rc = 0;
 174        unsigned char buf[4];
 175
 176        if (!rdata)
 177                return -EIO;
 178
 179        memset(buf, 0, sizeof(buf));
 180
 181        switch (width) {
 182        case WORD_LEN: {
 183                buf[0] = (raddr & 0xFF00)>>8;
 184                buf[1] = (raddr & 0x00FF);
 185
 186                rc = mt9d112_i2c_rxdata(saddr, buf, 2);
 187                if (rc < 0)
 188                        return rc;
 189
 190                *rdata = buf[0] << 8 | buf[1];
 191        }
 192                break;
 193
 194        default:
 195                break;
 196        }
 197
 198        if (rc < 0)
 199                CDBG("mt9d112_i2c_read failed!\n");
 200
 201        return rc;
 202}
 203
 204static int32_t mt9d112_set_lens_roll_off(void)
 205{
 206        int32_t rc = 0;
 207        rc = mt9d112_i2c_write_table(&mt9d112_regs.rftbl[0],
 208                                                                 mt9d112_regs.rftbl_size);
 209        return rc;
 210}
 211
 212static long mt9d112_reg_init(void)
 213{
 214        int32_t array_length;
 215        int32_t i;
 216        long rc;
 217
 218        /* PLL Setup Start */
 219        rc = mt9d112_i2c_write_table(&mt9d112_regs.plltbl[0],
 220                                        mt9d112_regs.plltbl_size);
 221
 222        if (rc < 0)
 223                return rc;
 224        /* PLL Setup End   */
 225
 226        array_length = mt9d112_regs.prev_snap_reg_settings_size;
 227
 228        /* Configure sensor for Preview mode and Snapshot mode */
 229        for (i = 0; i < array_length; i++) {
 230                rc = mt9d112_i2c_write(mt9d112_client->addr,
 231                  mt9d112_regs.prev_snap_reg_settings[i].register_address,
 232                  mt9d112_regs.prev_snap_reg_settings[i].register_value,
 233                  WORD_LEN);
 234
 235                if (rc < 0)
 236                        return rc;
 237        }
 238
 239        /* Configure for Noise Reduction, Saturation and Aperture Correction */
 240        array_length = mt9d112_regs.noise_reduction_reg_settings_size;
 241
 242        for (i = 0; i < array_length; i++) {
 243                rc = mt9d112_i2c_write(mt9d112_client->addr,
 244                        mt9d112_regs.noise_reduction_reg_settings[i].register_address,
 245                        mt9d112_regs.noise_reduction_reg_settings[i].register_value,
 246                        WORD_LEN);
 247
 248                if (rc < 0)
 249                        return rc;
 250        }
 251
 252        /* Set Color Kill Saturation point to optimum value */
 253        rc =
 254        mt9d112_i2c_write(mt9d112_client->addr,
 255        0x35A4,
 256        0x0593,
 257        WORD_LEN);
 258        if (rc < 0)
 259                return rc;
 260
 261        rc = mt9d112_i2c_write_table(&mt9d112_regs.stbl[0],
 262                                        mt9d112_regs.stbl_size);
 263        if (rc < 0)
 264                return rc;
 265
 266        rc = mt9d112_set_lens_roll_off();
 267        if (rc < 0)
 268                return rc;
 269
 270        return 0;
 271}
 272
 273static long mt9d112_set_sensor_mode(int mode)
 274{
 275        uint16_t clock;
 276        long rc = 0;
 277
 278        switch (mode) {
 279        case SENSOR_PREVIEW_MODE:
 280                rc =
 281                        mt9d112_i2c_write(mt9d112_client->addr,
 282                                0x338C, 0xA20C, WORD_LEN);
 283                if (rc < 0)
 284                        return rc;
 285
 286                rc =
 287                        mt9d112_i2c_write(mt9d112_client->addr,
 288                                0x3390, 0x0004, WORD_LEN);
 289                if (rc < 0)
 290                        return rc;
 291
 292                rc =
 293                        mt9d112_i2c_write(mt9d112_client->addr,
 294                                0x338C, 0xA215, WORD_LEN);
 295                if (rc < 0)
 296                        return rc;
 297
 298                rc =
 299                        mt9d112_i2c_write(mt9d112_client->addr,
 300                                0x3390, 0x0004, WORD_LEN);
 301                if (rc < 0)
 302                        return rc;
 303
 304                rc =
 305                        mt9d112_i2c_write(mt9d112_client->addr,
 306                                0x338C, 0xA20B, WORD_LEN);
 307                if (rc < 0)
 308                        return rc;
 309
 310                rc =
 311                        mt9d112_i2c_write(mt9d112_client->addr,
 312                                0x3390, 0x0000, WORD_LEN);
 313                if (rc < 0)
 314                        return rc;
 315
 316                clock = 0x0250;
 317
 318                rc =
 319                        mt9d112_i2c_write(mt9d112_client->addr,
 320                                0x341C, clock, WORD_LEN);
 321                if (rc < 0)
 322                        return rc;
 323
 324                rc =
 325                        mt9d112_i2c_write(mt9d112_client->addr,
 326                                0x338C, 0xA103, WORD_LEN);
 327                if (rc < 0)
 328                        return rc;
 329
 330                rc =
 331                        mt9d112_i2c_write(mt9d112_client->addr,
 332                                0x3390, 0x0001, WORD_LEN);
 333                if (rc < 0)
 334                        return rc;
 335
 336                mdelay(5);
 337                break;
 338
 339        case SENSOR_SNAPSHOT_MODE:
 340                /* Switch to lower fps for Snapshot */
 341                rc =
 342                        mt9d112_i2c_write(mt9d112_client->addr,
 343                                0x341C, 0x0120, WORD_LEN);
 344                if (rc < 0)
 345                        return rc;
 346
 347                rc =
 348                        mt9d112_i2c_write(mt9d112_client->addr,
 349                                0x338C, 0xA120, WORD_LEN);
 350                if (rc < 0)
 351                        return rc;
 352
 353                rc =
 354                        mt9d112_i2c_write(mt9d112_client->addr,
 355                                0x3390, 0x0002, WORD_LEN);
 356                if (rc < 0)
 357                        return rc;
 358
 359                mdelay(5);
 360
 361                rc =
 362                        mt9d112_i2c_write(mt9d112_client->addr,
 363                                0x338C, 0xA103, WORD_LEN);
 364                if (rc < 0)
 365                        return rc;
 366
 367                rc =
 368                        mt9d112_i2c_write(mt9d112_client->addr,
 369                                0x3390, 0x0002, WORD_LEN);
 370                if (rc < 0)
 371                        return rc;
 372                break;
 373
 374        default:
 375                return -EINVAL;
 376        }
 377
 378        return 0;
 379}
 380
 381static long mt9d112_set_effect(int mode, int effect)
 382{
 383        uint16_t reg_addr;
 384        uint16_t reg_val;
 385        long rc = 0;
 386
 387        switch (mode) {
 388        case SENSOR_PREVIEW_MODE:
 389                /* Context A Special Effects */
 390                reg_addr = 0x2799;
 391                break;
 392
 393        case SENSOR_SNAPSHOT_MODE:
 394                /* Context B Special Effects */
 395                reg_addr = 0x279B;
 396                break;
 397
 398        default:
 399                reg_addr = 0x2799;
 400                break;
 401        }
 402
 403        switch (effect) {
 404        case CAMERA_EFFECT_OFF: {
 405                reg_val = 0x6440;
 406
 407                rc = mt9d112_i2c_write(mt9d112_client->addr,
 408                        0x338C, reg_addr, WORD_LEN);
 409                if (rc < 0)
 410                        return rc;
 411
 412                rc = mt9d112_i2c_write(mt9d112_client->addr,
 413                        0x3390, reg_val, WORD_LEN);
 414                if (rc < 0)
 415                        return rc;
 416        }
 417                        break;
 418
 419        case CAMERA_EFFECT_MONO: {
 420                reg_val = 0x6441;
 421                rc = mt9d112_i2c_write(mt9d112_client->addr,
 422                        0x338C, reg_addr, WORD_LEN);
 423                if (rc < 0)
 424                        return rc;
 425
 426                rc = mt9d112_i2c_write(mt9d112_client->addr,
 427                        0x3390, reg_val, WORD_LEN);
 428                if (rc < 0)
 429                        return rc;
 430        }
 431                break;
 432
 433        case CAMERA_EFFECT_NEGATIVE: {
 434                reg_val = 0x6443;
 435                rc = mt9d112_i2c_write(mt9d112_client->addr,
 436                        0x338C, reg_addr, WORD_LEN);
 437                if (rc < 0)
 438                        return rc;
 439
 440                rc = mt9d112_i2c_write(mt9d112_client->addr,
 441                        0x3390, reg_val, WORD_LEN);
 442                if (rc < 0)
 443                        return rc;
 444        }
 445                break;
 446
 447        case CAMERA_EFFECT_SOLARIZE: {
 448                reg_val = 0x6445;
 449                rc = mt9d112_i2c_write(mt9d112_client->addr,
 450                        0x338C, reg_addr, WORD_LEN);
 451                if (rc < 0)
 452                        return rc;
 453
 454                rc = mt9d112_i2c_write(mt9d112_client->addr,
 455                        0x3390, reg_val, WORD_LEN);
 456                if (rc < 0)
 457                        return rc;
 458        }
 459                break;
 460
 461        case CAMERA_EFFECT_SEPIA: {
 462                reg_val = 0x6442;
 463                rc = mt9d112_i2c_write(mt9d112_client->addr,
 464                        0x338C, reg_addr, WORD_LEN);
 465                if (rc < 0)
 466                        return rc;
 467
 468                rc = mt9d112_i2c_write(mt9d112_client->addr,
 469                        0x3390, reg_val, WORD_LEN);
 470                if (rc < 0)
 471                        return rc;
 472        }
 473                break;
 474
 475        case CAMERA_EFFECT_PASTEL:
 476        case CAMERA_EFFECT_MOSAIC:
 477        case CAMERA_EFFECT_RESIZE:
 478                return -EINVAL;
 479
 480        default: {
 481                reg_val = 0x6440;
 482                rc = mt9d112_i2c_write(mt9d112_client->addr,
 483                        0x338C, reg_addr, WORD_LEN);
 484                if (rc < 0)
 485                        return rc;
 486
 487                rc = mt9d112_i2c_write(mt9d112_client->addr,
 488                        0x3390, reg_val, WORD_LEN);
 489                if (rc < 0)
 490                        return rc;
 491
 492                return -EINVAL;
 493        }
 494        }
 495
 496        /* Refresh Sequencer */
 497        rc = mt9d112_i2c_write(mt9d112_client->addr,
 498                0x338C, 0xA103, WORD_LEN);
 499        if (rc < 0)
 500                return rc;
 501
 502        rc = mt9d112_i2c_write(mt9d112_client->addr,
 503                0x3390, 0x0005, WORD_LEN);
 504
 505        return rc;
 506}
 507
 508static int mt9d112_sensor_init_probe(const struct msm_camera_sensor_info *data)
 509{
 510        uint16_t model_id = 0;
 511        int rc = 0;
 512
 513        CDBG("init entry \n");
 514        rc = mt9d112_reset(data);
 515        if (rc < 0) {
 516                CDBG("reset failed!\n");
 517                goto init_probe_fail;
 518        }
 519
 520        mdelay(5);
 521
 522        /* Micron suggested Power up block Start:
 523        * Put MCU into Reset - Stop MCU */
 524        rc = mt9d112_i2c_write(mt9d112_client->addr,
 525                REG_MT9D112_MCU_BOOT, 0x0501, WORD_LEN);
 526        if (rc < 0)
 527                goto init_probe_fail;
 528
 529        /* Pull MCU from Reset - Start MCU */
 530        rc = mt9d112_i2c_write(mt9d112_client->addr,
 531                REG_MT9D112_MCU_BOOT, 0x0500, WORD_LEN);
 532        if (rc < 0)
 533                goto init_probe_fail;
 534
 535        mdelay(5);
 536
 537        /* Micron Suggested - Power up block */
 538        rc = mt9d112_i2c_write(mt9d112_client->addr,
 539                REG_MT9D112_SENSOR_RESET, 0x0ACC, WORD_LEN);
 540        if (rc < 0)
 541                goto init_probe_fail;
 542
 543        rc = mt9d112_i2c_write(mt9d112_client->addr,
 544                REG_MT9D112_STANDBY_CONTROL, 0x0008, WORD_LEN);
 545        if (rc < 0)
 546                goto init_probe_fail;
 547
 548        /* FUSED_DEFECT_CORRECTION */
 549        rc = mt9d112_i2c_write(mt9d112_client->addr,
 550                0x33F4, 0x031D, WORD_LEN);
 551        if (rc < 0)
 552                goto init_probe_fail;
 553
 554        mdelay(5);
 555
 556        /* Micron suggested Power up block End */
 557        /* Read the Model ID of the sensor */
 558        rc = mt9d112_i2c_read(mt9d112_client->addr,
 559                REG_MT9D112_MODEL_ID, &model_id, WORD_LEN);
 560        if (rc < 0)
 561                goto init_probe_fail;
 562
 563        CDBG("mt9d112 model_id = 0x%x\n", model_id);
 564
 565        /* Check if it matches it with the value in Datasheet */
 566        if (model_id != MT9D112_MODEL_ID) {
 567                rc = -EINVAL;
 568                goto init_probe_fail;
 569        }
 570
 571        rc = mt9d112_reg_init();
 572        if (rc < 0)
 573                goto init_probe_fail;
 574
 575        return rc;
 576
 577init_probe_fail:
 578        return rc;
 579}
 580
 581int mt9d112_sensor_init(const struct msm_camera_sensor_info *data)
 582{
 583        int rc = 0;
 584
 585        mt9d112_ctrl = kzalloc(sizeof(struct mt9d112_ctrl), GFP_KERNEL);
 586        if (!mt9d112_ctrl) {
 587                CDBG("mt9d112_init failed!\n");
 588                rc = -ENOMEM;
 589                goto init_done;
 590        }
 591
 592        if (data)
 593                mt9d112_ctrl->sensordata = data;
 594
 595        /* Input MCLK = 24MHz */
 596        msm_camio_clk_rate_set(24000000);
 597        mdelay(5);
 598
 599        msm_camio_camif_pad_reg_reset();
 600
 601        rc = mt9d112_sensor_init_probe(data);
 602        if (rc < 0) {
 603                CDBG("mt9d112_sensor_init failed!\n");
 604                goto init_fail;
 605        }
 606
 607init_done:
 608        return rc;
 609
 610init_fail:
 611        kfree(mt9d112_ctrl);
 612        return rc;
 613}
 614
 615static int mt9d112_init_client(struct i2c_client *client)
 616{
 617        /* Initialize the MSM_CAMI2C Chip */
 618        init_waitqueue_head(&mt9d112_wait_queue);
 619        return 0;
 620}
 621
 622int mt9d112_sensor_config(void __user *argp)
 623{
 624        struct sensor_cfg_data cfg_data;
 625        long   rc = 0;
 626
 627        if (copy_from_user(&cfg_data,
 628                        (void *)argp,
 629                        sizeof(struct sensor_cfg_data)))
 630                return -EFAULT;
 631
 632        /* down(&mt9d112_sem); */
 633
 634        CDBG("mt9d112_ioctl, cfgtype = %d, mode = %d\n",
 635                cfg_data.cfgtype, cfg_data.mode);
 636
 637                switch (cfg_data.cfgtype) {
 638                case CFG_SET_MODE:
 639                        rc = mt9d112_set_sensor_mode(
 640                                                cfg_data.mode);
 641                        break;
 642
 643                case CFG_SET_EFFECT:
 644                        rc = mt9d112_set_effect(cfg_data.mode,
 645                                                cfg_data.cfg.effect);
 646                        break;
 647
 648                case CFG_GET_AF_MAX_STEPS:
 649                default:
 650                        rc = -EINVAL;
 651                        break;
 652                }
 653
 654        /* up(&mt9d112_sem); */
 655
 656        return rc;
 657}
 658
 659int mt9d112_sensor_release(void)
 660{
 661        int rc = 0;
 662
 663        /* down(&mt9d112_sem); */
 664
 665        kfree(mt9d112_ctrl);
 666        /* up(&mt9d112_sem); */
 667
 668        return rc;
 669}
 670
 671static int mt9d112_i2c_probe(struct i2c_client *client,
 672        const struct i2c_device_id *id)
 673{
 674        int rc = 0;
 675        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 676                rc = -ENOTSUPP;
 677                goto probe_failure;
 678        }
 679
 680        mt9d112_sensorw =
 681                kzalloc(sizeof(struct mt9d112_work), GFP_KERNEL);
 682
 683        if (!mt9d112_sensorw) {
 684                rc = -ENOMEM;
 685                goto probe_failure;
 686        }
 687
 688        i2c_set_clientdata(client, mt9d112_sensorw);
 689        mt9d112_init_client(client);
 690        mt9d112_client = client;
 691
 692        CDBG("mt9d112_probe succeeded!\n");
 693
 694        return 0;
 695
 696probe_failure:
 697        kfree(mt9d112_sensorw);
 698        mt9d112_sensorw = NULL;
 699        CDBG("mt9d112_probe failed!\n");
 700        return rc;
 701}
 702
 703static const struct i2c_device_id mt9d112_i2c_id[] = {
 704        { "mt9d112", 0},
 705        { },
 706};
 707
 708static struct i2c_driver mt9d112_i2c_driver = {
 709        .id_table = mt9d112_i2c_id,
 710        .probe  = mt9d112_i2c_probe,
 711        .remove = __exit_p(mt9d112_i2c_remove),
 712        .driver = {
 713                .name = "mt9d112",
 714        },
 715};
 716
 717static int mt9d112_sensor_probe(const struct msm_camera_sensor_info *info,
 718                                struct msm_sensor_ctrl *s)
 719{
 720        int rc = i2c_add_driver(&mt9d112_i2c_driver);
 721        if (rc < 0 || mt9d112_client == NULL) {
 722                rc = -ENOTSUPP;
 723                goto probe_done;
 724        }
 725
 726        /* Input MCLK = 24MHz */
 727        msm_camio_clk_rate_set(24000000);
 728        mdelay(5);
 729
 730        rc = mt9d112_sensor_init_probe(info);
 731        if (rc < 0)
 732                goto probe_done;
 733
 734        s->s_init = mt9d112_sensor_init;
 735        s->s_release = mt9d112_sensor_release;
 736        s->s_config  = mt9d112_sensor_config;
 737
 738probe_done:
 739        CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
 740        return rc;
 741}
 742
 743static int __mt9d112_probe(struct platform_device *pdev)
 744{
 745        return msm_camera_drv_start(pdev, mt9d112_sensor_probe);
 746}
 747
 748static struct platform_driver msm_camera_driver = {
 749        .probe = __mt9d112_probe,
 750        .driver = {
 751                .name = "msm_camera_mt9d112",
 752                .owner = THIS_MODULE,
 753        },
 754};
 755
 756static int __init mt9d112_init(void)
 757{
 758        return platform_driver_register(&msm_camera_driver);
 759}
 760
 761module_init(mt9d112_init);
 762