linux/drivers/staging/dream/camera/mt9p012_fox.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 <linux/kernel.h>
  11#include <media/msm_camera.h>
  12#include <mach/gpio.h>
  13#include <mach/camera.h>
  14#include "mt9p012.h"
  15
  16/*=============================================================
  17    SENSOR REGISTER DEFINES
  18==============================================================*/
  19#define MT9P012_REG_MODEL_ID         0x0000
  20#define MT9P012_MODEL_ID             0x2801
  21#define REG_GROUPED_PARAMETER_HOLD   0x0104
  22#define GROUPED_PARAMETER_HOLD       0x0100
  23#define GROUPED_PARAMETER_UPDATE     0x0000
  24#define REG_COARSE_INT_TIME          0x3012
  25#define REG_VT_PIX_CLK_DIV           0x0300
  26#define REG_VT_SYS_CLK_DIV           0x0302
  27#define REG_PRE_PLL_CLK_DIV          0x0304
  28#define REG_PLL_MULTIPLIER           0x0306
  29#define REG_OP_PIX_CLK_DIV           0x0308
  30#define REG_OP_SYS_CLK_DIV           0x030A
  31#define REG_SCALE_M                  0x0404
  32#define REG_FRAME_LENGTH_LINES       0x300A
  33#define REG_LINE_LENGTH_PCK          0x300C
  34#define REG_X_ADDR_START             0x3004
  35#define REG_Y_ADDR_START             0x3002
  36#define REG_X_ADDR_END               0x3008
  37#define REG_Y_ADDR_END               0x3006
  38#define REG_X_OUTPUT_SIZE            0x034C
  39#define REG_Y_OUTPUT_SIZE            0x034E
  40#define REG_FINE_INTEGRATION_TIME    0x3014
  41#define REG_ROW_SPEED                0x3016
  42#define MT9P012_REG_RESET_REGISTER   0x301A
  43#define MT9P012_RESET_REGISTER_PWON  0x10CC
  44#define MT9P012_RESET_REGISTER_PWOFF 0x10C8
  45#define REG_READ_MODE                0x3040
  46#define REG_GLOBAL_GAIN              0x305E
  47#define REG_TEST_PATTERN_MODE        0x3070
  48
  49#define MT9P012_REV_7
  50
  51
  52enum mt9p012_test_mode {
  53        TEST_OFF,
  54        TEST_1,
  55        TEST_2,
  56        TEST_3
  57};
  58
  59enum mt9p012_resolution {
  60        QTR_SIZE,
  61        FULL_SIZE,
  62        INVALID_SIZE
  63};
  64
  65enum mt9p012_reg_update {
  66        /* Sensor egisters that need to be updated during initialization */
  67        REG_INIT,
  68        /* Sensor egisters that needs periodic I2C writes */
  69        UPDATE_PERIODIC,
  70        /* All the sensor Registers will be updated */
  71        UPDATE_ALL,
  72        /* Not valid update */
  73        UPDATE_INVALID
  74};
  75
  76enum mt9p012_setting {
  77        RES_PREVIEW,
  78        RES_CAPTURE
  79};
  80
  81/* actuator's Slave Address */
  82#define MT9P012_AF_I2C_ADDR   0x18
  83
  84/* AF Total steps parameters */
  85#define MT9P012_STEPS_NEAR_TO_CLOSEST_INF  32
  86#define MT9P012_TOTAL_STEPS_NEAR_TO_FAR    32
  87
  88#define MT9P012_MU5M0_PREVIEW_DUMMY_PIXELS 0
  89#define MT9P012_MU5M0_PREVIEW_DUMMY_LINES  0
  90
  91/* Time in milisecs for waiting for the sensor to reset.*/
  92#define MT9P012_RESET_DELAY_MSECS   66
  93
  94/* for 20 fps preview */
  95#define MT9P012_DEFAULT_CLOCK_RATE  24000000
  96#define MT9P012_DEFAULT_MAX_FPS     26 /* ???? */
  97
  98struct mt9p012_work {
  99        struct work_struct work;
 100};
 101static struct mt9p012_work *mt9p012_sensorw;
 102static struct i2c_client *mt9p012_client;
 103
 104struct mt9p012_ctrl {
 105        const struct msm_camera_sensor_info *sensordata;
 106
 107        int sensormode;
 108        uint32_t fps_divider; /* init to 1 * 0x00000400 */
 109        uint32_t pict_fps_divider; /* init to 1 * 0x00000400 */
 110
 111        uint16_t curr_lens_pos;
 112        uint16_t init_curr_lens_pos;
 113        uint16_t my_reg_gain;
 114        uint32_t my_reg_line_count;
 115
 116        enum mt9p012_resolution prev_res;
 117        enum mt9p012_resolution pict_res;
 118        enum mt9p012_resolution curr_res;
 119        enum mt9p012_test_mode  set_test;
 120};
 121
 122
 123static struct mt9p012_ctrl *mt9p012_ctrl;
 124static DECLARE_WAIT_QUEUE_HEAD(mt9p012_wait_queue);
 125DECLARE_MUTEX(mt9p012_sem);
 126
 127/*=============================================================
 128        EXTERNAL DECLARATIONS
 129==============================================================*/
 130extern struct mt9p012_reg mt9p012_regs; /* from mt9p012_reg.c */
 131
 132
 133
 134/*=============================================================*/
 135
 136static int mt9p012_i2c_rxdata(unsigned short saddr, unsigned char *rxdata,
 137        int length)
 138{
 139        struct i2c_msg msgs[] = {
 140                {
 141                        .addr   = saddr,
 142                        .flags = 0,
 143                        .len   = 2,
 144                        .buf   = rxdata,
 145                },
 146                {
 147                        .addr   = saddr,
 148                        .flags = I2C_M_RD,
 149                        .len   = length,
 150                        .buf   = rxdata,
 151                },
 152        };
 153
 154        if (i2c_transfer(mt9p012_client->adapter, msgs, 2) < 0) {
 155                CDBG("mt9p012_i2c_rxdata failed!\n");
 156                return -EIO;
 157        }
 158
 159        return 0;
 160}
 161
 162static int32_t mt9p012_i2c_read_w(unsigned short saddr, unsigned short raddr,
 163        unsigned short *rdata)
 164{
 165        int32_t rc = 0;
 166        unsigned char buf[4];
 167
 168        if (!rdata)
 169                return -EIO;
 170
 171        memset(buf, 0, sizeof(buf));
 172
 173        buf[0] = (raddr & 0xFF00)>>8;
 174        buf[1] = (raddr & 0x00FF);
 175
 176        rc = mt9p012_i2c_rxdata(saddr, buf, 2);
 177        if (rc < 0)
 178                return rc;
 179
 180        *rdata = buf[0] << 8 | buf[1];
 181
 182        if (rc < 0)
 183                CDBG("mt9p012_i2c_read failed!\n");
 184
 185        return rc;
 186}
 187
 188static int32_t mt9p012_i2c_txdata(unsigned short saddr, unsigned char *txdata,
 189        int length)
 190{
 191        struct i2c_msg msg[] = {
 192                {
 193                .addr  = saddr,
 194                .flags = 0,
 195                .len = length,
 196                .buf = txdata,
 197                },
 198        };
 199
 200        if (i2c_transfer(mt9p012_client->adapter, msg, 1) < 0) {
 201                CDBG("mt9p012_i2c_txdata failed\n");
 202                return -EIO;
 203        }
 204
 205        return 0;
 206}
 207
 208static int32_t mt9p012_i2c_write_b(unsigned short saddr, unsigned short baddr,
 209        unsigned short bdata)
 210{
 211        int32_t rc = -EIO;
 212        unsigned char buf[2];
 213
 214        memset(buf, 0, sizeof(buf));
 215        buf[0] = baddr;
 216        buf[1] = bdata;
 217        rc = mt9p012_i2c_txdata(saddr, buf, 2);
 218
 219        if (rc < 0)
 220                CDBG("i2c_write failed, saddr = 0x%x addr = 0x%x, val =0x%x!\n",
 221                saddr, baddr, bdata);
 222
 223        return rc;
 224}
 225
 226static int32_t mt9p012_i2c_write_w(unsigned short saddr, unsigned short waddr,
 227        unsigned short wdata)
 228{
 229        int32_t rc = -EIO;
 230        unsigned char buf[4];
 231
 232        memset(buf, 0, sizeof(buf));
 233        buf[0] = (waddr & 0xFF00)>>8;
 234        buf[1] = (waddr & 0x00FF);
 235        buf[2] = (wdata & 0xFF00)>>8;
 236        buf[3] = (wdata & 0x00FF);
 237
 238        rc = mt9p012_i2c_txdata(saddr, buf, 4);
 239
 240        if (rc < 0)
 241                CDBG("i2c_write_w failed, addr = 0x%x, val = 0x%x!\n",
 242                        waddr, wdata);
 243
 244        return rc;
 245}
 246
 247static int32_t mt9p012_i2c_write_w_table(
 248        struct mt9p012_i2c_reg_conf *reg_conf_tbl, int num)
 249{
 250        int i;
 251        int32_t rc = -EIO;
 252
 253        for (i = 0; i < num; i++) {
 254                rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 255                        reg_conf_tbl->waddr, reg_conf_tbl->wdata);
 256                if (rc < 0)
 257                        break;
 258                reg_conf_tbl++;
 259        }
 260
 261        return rc;
 262}
 263
 264static int32_t mt9p012_test(enum mt9p012_test_mode mo)
 265{
 266        int32_t rc = 0;
 267
 268        rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 269                REG_GROUPED_PARAMETER_HOLD,
 270                GROUPED_PARAMETER_HOLD);
 271        if (rc < 0)
 272                return rc;
 273
 274        if (mo == TEST_OFF)
 275                return 0;
 276        else {
 277                rc = mt9p012_i2c_write_w_table(mt9p012_regs.ttbl, mt9p012_regs.ttbl_size);
 278                if (rc < 0)
 279                        return rc;
 280
 281                rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 282                                REG_TEST_PATTERN_MODE, (uint16_t)mo);
 283                if (rc < 0)
 284                        return rc;
 285        }
 286
 287        rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 288                REG_GROUPED_PARAMETER_HOLD,
 289                GROUPED_PARAMETER_UPDATE);
 290        if (rc < 0)
 291                return rc;
 292
 293        return rc;
 294}
 295
 296static int32_t mt9p012_lens_shading_enable(uint8_t is_enable)
 297{
 298        int32_t rc = 0;
 299
 300        CDBG("%s: entered. enable = %d\n", __func__, is_enable);
 301
 302        rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 303                REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_HOLD);
 304        if (rc < 0)
 305                return rc;
 306
 307        rc = mt9p012_i2c_write_w(mt9p012_client->addr, 0x3780,
 308                ((uint16_t) is_enable) << 15);
 309        if (rc < 0)
 310                return rc;
 311
 312        rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 313                REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_UPDATE);
 314
 315        CDBG("%s: exiting. rc = %d\n", __func__, rc);
 316        return rc;
 317}
 318
 319static int32_t mt9p012_set_lc(void)
 320{
 321        int32_t rc;
 322
 323        rc = mt9p012_i2c_write_w_table(mt9p012_regs.lctbl, mt9p012_regs.lctbl_size);
 324        if (rc < 0)
 325                return rc;
 326
 327        rc = mt9p012_i2c_write_w_table(mt9p012_regs.rftbl, mt9p012_regs.rftbl_size);
 328
 329        return rc;
 330}
 331
 332static void mt9p012_get_pict_fps(uint16_t fps, uint16_t *pfps)
 333{
 334        /* input fps is preview fps in Q8 format */
 335        uint32_t divider;   /*Q10 */
 336        uint32_t pclk_mult; /*Q10 */
 337
 338        if (mt9p012_ctrl->prev_res == QTR_SIZE) {
 339                divider = (uint32_t)
 340                (((mt9p012_regs.reg_pat[RES_PREVIEW].frame_length_lines *
 341                mt9p012_regs.reg_pat[RES_PREVIEW].line_length_pck) * 0x00000400) /
 342                (mt9p012_regs.reg_pat[RES_CAPTURE].frame_length_lines *
 343                mt9p012_regs.reg_pat[RES_CAPTURE].line_length_pck));
 344
 345                pclk_mult =
 346                (uint32_t) ((mt9p012_regs.reg_pat[RES_CAPTURE].pll_multiplier *
 347                0x00000400) / (mt9p012_regs.reg_pat[RES_PREVIEW].pll_multiplier));
 348        } else {
 349                /* full size resolution used for preview. */
 350                divider   = 0x00000400;  /*1.0 */
 351                pclk_mult = 0x00000400;  /*1.0 */
 352        }
 353
 354        /* Verify PCLK settings and frame sizes. */
 355        *pfps = (uint16_t) (fps * divider * pclk_mult / 0x00000400 /
 356                0x00000400);
 357}
 358
 359static uint16_t mt9p012_get_prev_lines_pf(void)
 360{
 361        if (mt9p012_ctrl->prev_res == QTR_SIZE)
 362                return mt9p012_regs.reg_pat[RES_PREVIEW].frame_length_lines;
 363        else
 364                return mt9p012_regs.reg_pat[RES_CAPTURE].frame_length_lines;
 365}
 366
 367static uint16_t mt9p012_get_prev_pixels_pl(void)
 368{
 369        if (mt9p012_ctrl->prev_res == QTR_SIZE)
 370                return mt9p012_regs.reg_pat[RES_PREVIEW].line_length_pck;
 371        else
 372                return mt9p012_regs.reg_pat[RES_CAPTURE].line_length_pck;
 373}
 374
 375static uint16_t mt9p012_get_pict_lines_pf(void)
 376{
 377        return mt9p012_regs.reg_pat[RES_CAPTURE].frame_length_lines;
 378}
 379
 380static uint16_t mt9p012_get_pict_pixels_pl(void)
 381{
 382        return mt9p012_regs.reg_pat[RES_CAPTURE].line_length_pck;
 383}
 384
 385static uint32_t mt9p012_get_pict_max_exp_lc(void)
 386{
 387        uint16_t snapshot_lines_per_frame;
 388
 389        if (mt9p012_ctrl->pict_res == QTR_SIZE)
 390                snapshot_lines_per_frame =
 391                mt9p012_regs.reg_pat[RES_PREVIEW].frame_length_lines - 1;
 392        else
 393                snapshot_lines_per_frame =
 394                mt9p012_regs.reg_pat[RES_CAPTURE].frame_length_lines - 1;
 395
 396        return snapshot_lines_per_frame * 24;
 397}
 398
 399static int32_t mt9p012_set_fps(struct fps_cfg *fps)
 400{
 401        /* input is new fps in Q10 format */
 402        int32_t rc = 0;
 403
 404        mt9p012_ctrl->fps_divider = fps->fps_div;
 405        mt9p012_ctrl->pict_fps_divider = fps->pict_fps_div;
 406
 407        rc =
 408                mt9p012_i2c_write_w(mt9p012_client->addr,
 409                        REG_GROUPED_PARAMETER_HOLD,
 410                        GROUPED_PARAMETER_HOLD);
 411        if (rc < 0)
 412                return -EBUSY;
 413
 414        rc =
 415                mt9p012_i2c_write_w(mt9p012_client->addr,
 416                        REG_LINE_LENGTH_PCK,
 417                        (mt9p012_regs.reg_pat[RES_PREVIEW].line_length_pck *
 418                        fps->f_mult / 0x00000400));
 419        if (rc < 0)
 420                return rc;
 421
 422        rc =
 423                mt9p012_i2c_write_w(mt9p012_client->addr,
 424                        REG_GROUPED_PARAMETER_HOLD,
 425                        GROUPED_PARAMETER_UPDATE);
 426
 427        return rc;
 428}
 429
 430static int32_t mt9p012_write_exp_gain(uint16_t gain, uint32_t line)
 431{
 432        uint16_t max_legal_gain = 0x01FF;
 433        uint32_t line_length_ratio = 0x00000400;
 434        enum mt9p012_setting setting;
 435        int32_t rc = 0;
 436
 437        CDBG("Line:%d mt9p012_write_exp_gain \n", __LINE__);
 438
 439        if (mt9p012_ctrl->sensormode == SENSOR_PREVIEW_MODE) {
 440                mt9p012_ctrl->my_reg_gain = gain;
 441                mt9p012_ctrl->my_reg_line_count = (uint16_t)line;
 442        }
 443
 444        if (gain > max_legal_gain) {
 445                CDBG("Max legal gain Line:%d \n", __LINE__);
 446                gain = max_legal_gain;
 447        }
 448
 449        /* Verify no overflow */
 450        if (mt9p012_ctrl->sensormode != SENSOR_SNAPSHOT_MODE) {
 451                line = (uint32_t)(line * mt9p012_ctrl->fps_divider /
 452                        0x00000400);
 453                setting = RES_PREVIEW;
 454        } else {
 455                line = (uint32_t)(line * mt9p012_ctrl->pict_fps_divider /
 456                        0x00000400);
 457                setting = RES_CAPTURE;
 458        }
 459
 460        /* Set digital gain to 1 */
 461#ifdef MT9P012_REV_7
 462        gain |= 0x1000;
 463#else
 464        gain |= 0x0200;
 465#endif
 466
 467        if ((mt9p012_regs.reg_pat[setting].frame_length_lines - 1) < line) {
 468                line_length_ratio = (uint32_t) (line * 0x00000400) /
 469                (mt9p012_regs.reg_pat[setting].frame_length_lines - 1);
 470        } else
 471                line_length_ratio = 0x00000400;
 472
 473        rc =
 474                mt9p012_i2c_write_w(mt9p012_client->addr,
 475                        REG_GROUPED_PARAMETER_HOLD,
 476                        GROUPED_PARAMETER_HOLD);
 477        if (rc < 0) {
 478                CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
 479                return rc;
 480        }
 481
 482        rc =
 483                mt9p012_i2c_write_w(
 484                        mt9p012_client->addr,
 485                        REG_GLOBAL_GAIN, gain);
 486        if (rc < 0) {
 487                CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
 488                return rc;
 489        }
 490
 491        rc =
 492                mt9p012_i2c_write_w(mt9p012_client->addr,
 493                        REG_COARSE_INT_TIME,
 494                        line);
 495        if (rc < 0) {
 496                CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
 497                return rc;
 498        }
 499
 500        CDBG("mt9p012_write_exp_gain: gain = %d, line = %d\n", gain, line);
 501
 502        rc =
 503                mt9p012_i2c_write_w(mt9p012_client->addr,
 504                        REG_GROUPED_PARAMETER_HOLD,
 505                        GROUPED_PARAMETER_UPDATE);
 506        if (rc < 0)
 507                CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
 508
 509        return rc;
 510}
 511
 512static int32_t mt9p012_set_pict_exp_gain(uint16_t gain, uint32_t line)
 513{
 514        int32_t rc = 0;
 515
 516        CDBG("Line:%d mt9p012_set_pict_exp_gain \n", __LINE__);
 517
 518        rc =
 519                mt9p012_write_exp_gain(gain, line);
 520        if (rc < 0) {
 521                CDBG("Line:%d mt9p012_set_pict_exp_gain failed... \n",
 522                        __LINE__);
 523                return rc;
 524        }
 525
 526        rc =
 527        mt9p012_i2c_write_w(mt9p012_client->addr,
 528                MT9P012_REG_RESET_REGISTER,
 529                0x10CC | 0x0002);
 530        if (rc < 0) {
 531                CDBG("mt9p012_i2c_write_w failed... Line:%d \n", __LINE__);
 532                return rc;
 533        }
 534
 535        mdelay(5);
 536
 537        /* camera_timed_wait(snapshot_wait*exposure_ratio); */
 538        return rc;
 539}
 540
 541static int32_t mt9p012_setting(enum mt9p012_reg_update rupdate,
 542        enum mt9p012_setting rt)
 543{
 544        int32_t rc = 0;
 545
 546        switch (rupdate) {
 547        case UPDATE_PERIODIC:
 548        if (rt == RES_PREVIEW || rt == RES_CAPTURE) {
 549
 550                struct mt9p012_i2c_reg_conf ppc_tbl[] = {
 551                {REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_HOLD},
 552                {REG_ROW_SPEED, mt9p012_regs.reg_pat[rt].row_speed},
 553                {REG_X_ADDR_START, mt9p012_regs.reg_pat[rt].x_addr_start},
 554                {REG_X_ADDR_END, mt9p012_regs.reg_pat[rt].x_addr_end},
 555                {REG_Y_ADDR_START, mt9p012_regs.reg_pat[rt].y_addr_start},
 556                {REG_Y_ADDR_END, mt9p012_regs.reg_pat[rt].y_addr_end},
 557                {REG_READ_MODE, mt9p012_regs.reg_pat[rt].read_mode},
 558                {REG_SCALE_M, mt9p012_regs.reg_pat[rt].scale_m},
 559                {REG_X_OUTPUT_SIZE, mt9p012_regs.reg_pat[rt].x_output_size},
 560                {REG_Y_OUTPUT_SIZE, mt9p012_regs.reg_pat[rt].y_output_size},
 561
 562                {REG_LINE_LENGTH_PCK, mt9p012_regs.reg_pat[rt].line_length_pck},
 563                {REG_FRAME_LENGTH_LINES,
 564                        (mt9p012_regs.reg_pat[rt].frame_length_lines *
 565                        mt9p012_ctrl->fps_divider / 0x00000400)},
 566                {REG_COARSE_INT_TIME, mt9p012_regs.reg_pat[rt].coarse_int_time},
 567                {REG_FINE_INTEGRATION_TIME, mt9p012_regs.reg_pat[rt].fine_int_time},
 568                {REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_UPDATE},
 569                };
 570
 571                rc = mt9p012_i2c_write_w_table(&ppc_tbl[0],
 572                        ARRAY_SIZE(ppc_tbl));
 573                if (rc < 0)
 574                        return rc;
 575
 576                rc = mt9p012_test(mt9p012_ctrl->set_test);
 577                if (rc < 0)
 578                        return rc;
 579
 580                rc =
 581                        mt9p012_i2c_write_w(mt9p012_client->addr,
 582                        MT9P012_REG_RESET_REGISTER,
 583                        MT9P012_RESET_REGISTER_PWON | 0x0002);
 584                if (rc < 0)
 585                        return rc;
 586
 587                mdelay(5); /* 15? wait for sensor to transition*/
 588
 589                return rc;
 590        }
 591        break; /* UPDATE_PERIODIC */
 592
 593        case REG_INIT:
 594        if (rt == RES_PREVIEW || rt == RES_CAPTURE) {
 595                struct mt9p012_i2c_reg_conf ipc_tbl1[] = {
 596                {MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWOFF},
 597                {REG_VT_PIX_CLK_DIV, mt9p012_regs.reg_pat[rt].vt_pix_clk_div},
 598                {REG_VT_SYS_CLK_DIV, mt9p012_regs.reg_pat[rt].vt_sys_clk_div},
 599                {REG_PRE_PLL_CLK_DIV, mt9p012_regs.reg_pat[rt].pre_pll_clk_div},
 600                {REG_PLL_MULTIPLIER, mt9p012_regs.reg_pat[rt].pll_multiplier},
 601                {REG_OP_PIX_CLK_DIV, mt9p012_regs.reg_pat[rt].op_pix_clk_div},
 602                {REG_OP_SYS_CLK_DIV, mt9p012_regs.reg_pat[rt].op_sys_clk_div},
 603#ifdef MT9P012_REV_7
 604                {0x30B0, 0x0001},
 605                {0x308E, 0xE060},
 606                {0x3092, 0x0A52},
 607                {0x3094, 0x4656},
 608                {0x3096, 0x5652},
 609                {0x30CA, 0x8006},
 610                {0x312A, 0xDD02},
 611                {0x312C, 0x00E4},
 612                {0x3170, 0x299A},
 613#endif
 614                /* optimized settings for noise */
 615                {0x3088, 0x6FF6},
 616                {0x3154, 0x0282},
 617                {0x3156, 0x0381},
 618                {0x3162, 0x04CE},
 619                {0x0204, 0x0010},
 620                {0x0206, 0x0010},
 621                {0x0208, 0x0010},
 622                {0x020A, 0x0010},
 623                {0x020C, 0x0010},
 624                {MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWON},
 625                };
 626
 627                struct mt9p012_i2c_reg_conf ipc_tbl2[] = {
 628                {MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWOFF},
 629                {REG_VT_PIX_CLK_DIV, mt9p012_regs.reg_pat[rt].vt_pix_clk_div},
 630                {REG_VT_SYS_CLK_DIV, mt9p012_regs.reg_pat[rt].vt_sys_clk_div},
 631                {REG_PRE_PLL_CLK_DIV, mt9p012_regs.reg_pat[rt].pre_pll_clk_div},
 632                {REG_PLL_MULTIPLIER, mt9p012_regs.reg_pat[rt].pll_multiplier},
 633                {REG_OP_PIX_CLK_DIV, mt9p012_regs.reg_pat[rt].op_pix_clk_div},
 634                {REG_OP_SYS_CLK_DIV, mt9p012_regs.reg_pat[rt].op_sys_clk_div},
 635#ifdef MT9P012_REV_7
 636                {0x30B0, 0x0001},
 637                {0x308E, 0xE060},
 638                {0x3092, 0x0A52},
 639                {0x3094, 0x4656},
 640                {0x3096, 0x5652},
 641                {0x30CA, 0x8006},
 642                {0x312A, 0xDD02},
 643                {0x312C, 0x00E4},
 644                {0x3170, 0x299A},
 645#endif
 646                /* optimized settings for noise */
 647                {0x3088, 0x6FF6},
 648                {0x3154, 0x0282},
 649                {0x3156, 0x0381},
 650                {0x3162, 0x04CE},
 651                {0x0204, 0x0010},
 652                {0x0206, 0x0010},
 653                {0x0208, 0x0010},
 654                {0x020A, 0x0010},
 655                {0x020C, 0x0010},
 656                {MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWON},
 657                };
 658
 659                struct mt9p012_i2c_reg_conf ipc_tbl3[] = {
 660                {REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_HOLD},
 661                /* Set preview or snapshot mode */
 662                {REG_ROW_SPEED, mt9p012_regs.reg_pat[rt].row_speed},
 663                {REG_X_ADDR_START, mt9p012_regs.reg_pat[rt].x_addr_start},
 664                {REG_X_ADDR_END, mt9p012_regs.reg_pat[rt].x_addr_end},
 665                {REG_Y_ADDR_START, mt9p012_regs.reg_pat[rt].y_addr_start},
 666                {REG_Y_ADDR_END, mt9p012_regs.reg_pat[rt].y_addr_end},
 667                {REG_READ_MODE, mt9p012_regs.reg_pat[rt].read_mode},
 668                {REG_SCALE_M, mt9p012_regs.reg_pat[rt].scale_m},
 669                {REG_X_OUTPUT_SIZE, mt9p012_regs.reg_pat[rt].x_output_size},
 670                {REG_Y_OUTPUT_SIZE, mt9p012_regs.reg_pat[rt].y_output_size},
 671                {REG_LINE_LENGTH_PCK, mt9p012_regs.reg_pat[rt].line_length_pck},
 672                {REG_FRAME_LENGTH_LINES,
 673                        mt9p012_regs.reg_pat[rt].frame_length_lines},
 674                {REG_COARSE_INT_TIME, mt9p012_regs.reg_pat[rt].coarse_int_time},
 675                {REG_FINE_INTEGRATION_TIME, mt9p012_regs.reg_pat[rt].fine_int_time},
 676                {REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_UPDATE},
 677                };
 678
 679                /* reset fps_divider */
 680                mt9p012_ctrl->fps_divider = 1 * 0x0400;
 681
 682                rc = mt9p012_i2c_write_w_table(&ipc_tbl1[0],
 683                        ARRAY_SIZE(ipc_tbl1));
 684                if (rc < 0)
 685                        return rc;
 686
 687                rc = mt9p012_i2c_write_w_table(&ipc_tbl2[0],
 688                        ARRAY_SIZE(ipc_tbl2));
 689                if (rc < 0)
 690                        return rc;
 691
 692                mdelay(5);
 693
 694                rc = mt9p012_i2c_write_w_table(&ipc_tbl3[0],
 695                        ARRAY_SIZE(ipc_tbl3));
 696                if (rc < 0)
 697                        return rc;
 698
 699                /* load lens shading */
 700                rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 701                        REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_HOLD);
 702                if (rc < 0)
 703                        return rc;
 704
 705                rc = mt9p012_set_lc();
 706                if (rc < 0)
 707                        return rc;
 708
 709                rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 710                        REG_GROUPED_PARAMETER_HOLD, GROUPED_PARAMETER_UPDATE);
 711
 712                if (rc < 0)
 713                        return rc;
 714        }
 715        break; /* case REG_INIT: */
 716
 717        default:
 718                rc = -EINVAL;
 719                break;
 720        } /* switch (rupdate) */
 721
 722        return rc;
 723}
 724
 725static int32_t mt9p012_video_config(int mode, int res)
 726{
 727        int32_t rc;
 728
 729        switch (res) {
 730        case QTR_SIZE:
 731                rc = mt9p012_setting(UPDATE_PERIODIC, RES_PREVIEW);
 732                if (rc < 0)
 733                        return rc;
 734
 735                CDBG("mt9p012 sensor configuration done!\n");
 736                break;
 737
 738        case FULL_SIZE:
 739                rc =
 740                mt9p012_setting(UPDATE_PERIODIC, RES_CAPTURE);
 741                if (rc < 0)
 742                        return rc;
 743
 744                break;
 745
 746        default:
 747                return 0;
 748        } /* switch */
 749
 750        mt9p012_ctrl->prev_res = res;
 751        mt9p012_ctrl->curr_res = res;
 752        mt9p012_ctrl->sensormode = mode;
 753
 754        rc =
 755                mt9p012_write_exp_gain(mt9p012_ctrl->my_reg_gain,
 756                        mt9p012_ctrl->my_reg_line_count);
 757
 758        rc =
 759                mt9p012_i2c_write_w(mt9p012_client->addr,
 760                        MT9P012_REG_RESET_REGISTER,
 761                        0x10cc|0x0002);
 762
 763        return rc;
 764}
 765
 766static int32_t mt9p012_snapshot_config(int mode)
 767{
 768        int32_t rc = 0;
 769
 770        rc = mt9p012_setting(UPDATE_PERIODIC, RES_CAPTURE);
 771        if (rc < 0)
 772                return rc;
 773
 774        mt9p012_ctrl->curr_res = mt9p012_ctrl->pict_res;
 775
 776        mt9p012_ctrl->sensormode = mode;
 777
 778        return rc;
 779}
 780
 781static int32_t mt9p012_raw_snapshot_config(int mode)
 782{
 783        int32_t rc = 0;
 784
 785        rc = mt9p012_setting(UPDATE_PERIODIC, RES_CAPTURE);
 786        if (rc < 0)
 787                return rc;
 788
 789        mt9p012_ctrl->curr_res = mt9p012_ctrl->pict_res;
 790
 791        mt9p012_ctrl->sensormode = mode;
 792
 793        return rc;
 794}
 795
 796static int32_t mt9p012_power_down(void)
 797{
 798        int32_t rc = 0;
 799
 800        rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 801                MT9P012_REG_RESET_REGISTER,
 802                MT9P012_RESET_REGISTER_PWOFF);
 803
 804        mdelay(5);
 805        return rc;
 806}
 807
 808static int32_t mt9p012_move_focus(int direction, int32_t num_steps)
 809{
 810        int16_t step_direction;
 811        int16_t actual_step;
 812        int16_t next_position;
 813        uint8_t code_val_msb, code_val_lsb;
 814
 815        if (num_steps > MT9P012_TOTAL_STEPS_NEAR_TO_FAR)
 816                num_steps = MT9P012_TOTAL_STEPS_NEAR_TO_FAR;
 817        else if (num_steps == 0) {
 818                CDBG("mt9p012_move_focus failed at line %d ...\n", __LINE__);
 819                return -EINVAL;
 820        }
 821
 822        if (direction == MOVE_NEAR)
 823                step_direction = 16; /* 10bit */
 824        else if (direction == MOVE_FAR)
 825                step_direction = -16; /* 10 bit */
 826        else {
 827                CDBG("mt9p012_move_focus failed at line %d ...\n", __LINE__);
 828                return -EINVAL;
 829        }
 830
 831        if (mt9p012_ctrl->curr_lens_pos < mt9p012_ctrl->init_curr_lens_pos)
 832                mt9p012_ctrl->curr_lens_pos =
 833                        mt9p012_ctrl->init_curr_lens_pos;
 834
 835        actual_step = (int16_t)(step_direction * (int16_t)num_steps);
 836        next_position = (int16_t)(mt9p012_ctrl->curr_lens_pos + actual_step);
 837
 838        if (next_position > 1023)
 839                next_position = 1023;
 840        else if (next_position < 0)
 841                next_position = 0;
 842
 843        code_val_msb = next_position >> 4;
 844        code_val_lsb = (next_position & 0x000F) << 4;
 845        /* code_val_lsb |= mode_mask; */
 846
 847        /* Writing the digital code for current to the actuator */
 848        if (mt9p012_i2c_write_b(MT9P012_AF_I2C_ADDR >> 1,
 849                code_val_msb, code_val_lsb) < 0) {
 850                CDBG("mt9p012_move_focus failed at line %d ...\n", __LINE__);
 851                return -EBUSY;
 852        }
 853
 854        /* Storing the current lens Position */
 855        mt9p012_ctrl->curr_lens_pos = next_position;
 856
 857        return 0;
 858}
 859
 860static int32_t mt9p012_set_default_focus(void)
 861{
 862        int32_t rc = 0;
 863        uint8_t code_val_msb, code_val_lsb;
 864
 865        code_val_msb = 0x00;
 866        code_val_lsb = 0x00;
 867
 868        /* Write the digital code for current to the actuator */
 869        rc = mt9p012_i2c_write_b(MT9P012_AF_I2C_ADDR >> 1,
 870                code_val_msb, code_val_lsb);
 871
 872        mt9p012_ctrl->curr_lens_pos = 0;
 873        mt9p012_ctrl->init_curr_lens_pos = 0;
 874
 875        return rc;
 876}
 877
 878static int mt9p012_probe_init_done(const struct msm_camera_sensor_info *data)
 879{
 880        gpio_direction_output(data->sensor_reset, 0);
 881        gpio_free(data->sensor_reset);
 882        return 0;
 883}
 884
 885static int mt9p012_probe_init_sensor(const struct msm_camera_sensor_info *data)
 886{
 887        int32_t  rc;
 888        uint16_t chipid;
 889
 890        rc = gpio_request(data->sensor_reset, "mt9p012");
 891        if (!rc)
 892                gpio_direction_output(data->sensor_reset, 1);
 893        else
 894                goto init_probe_done;
 895
 896        mdelay(20);
 897
 898        /* RESET the sensor image part via I2C command */
 899        CDBG("mt9p012_sensor_init(): reseting sensor.\n");
 900        rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 901                MT9P012_REG_RESET_REGISTER, 0x10CC|0x0001);
 902        if (rc < 0) {
 903                CDBG("sensor reset failed. rc = %d\n", rc);
 904                goto init_probe_fail;
 905        }
 906
 907        mdelay(MT9P012_RESET_DELAY_MSECS);
 908
 909        /* 3. Read sensor Model ID: */
 910        rc = mt9p012_i2c_read_w(mt9p012_client->addr,
 911                MT9P012_REG_MODEL_ID, &chipid);
 912        if (rc < 0)
 913                goto init_probe_fail;
 914
 915        /* 4. Compare sensor ID to MT9T012VC ID: */
 916        if (chipid != MT9P012_MODEL_ID) {
 917                CDBG("mt9p012 wrong model_id = 0x%x\n", chipid);
 918                rc = -ENODEV;
 919                goto init_probe_fail;
 920        }
 921
 922        rc = mt9p012_i2c_write_w(mt9p012_client->addr, 0x306E, 0x9000);
 923        if (rc < 0) {
 924                CDBG("REV_7 write failed. rc = %d\n", rc);
 925                goto init_probe_fail;
 926        }
 927
 928        /* RESET_REGISTER, enable parallel interface and disable serialiser */
 929        CDBG("mt9p012_sensor_init(): enabling parallel interface.\n");
 930        rc = mt9p012_i2c_write_w(mt9p012_client->addr, 0x301A, 0x10CC);
 931        if (rc < 0) {
 932                CDBG("enable parallel interface failed. rc = %d\n", rc);
 933                goto init_probe_fail;
 934        }
 935
 936        /* To disable the 2 extra lines */
 937        rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 938                0x3064, 0x0805);
 939
 940        if (rc < 0) {
 941                CDBG("disable the 2 extra lines failed. rc = %d\n", rc);
 942                goto init_probe_fail;
 943        }
 944
 945        mdelay(MT9P012_RESET_DELAY_MSECS);
 946        goto init_probe_done;
 947
 948init_probe_fail:
 949        mt9p012_probe_init_done(data);
 950init_probe_done:
 951        return rc;
 952}
 953
 954static int mt9p012_sensor_open_init(const struct msm_camera_sensor_info *data)
 955{
 956        int32_t  rc;
 957
 958        mt9p012_ctrl = kzalloc(sizeof(struct mt9p012_ctrl), GFP_KERNEL);
 959        if (!mt9p012_ctrl) {
 960                CDBG("mt9p012_init failed!\n");
 961                rc = -ENOMEM;
 962                goto init_done;
 963        }
 964
 965        mt9p012_ctrl->fps_divider = 1 * 0x00000400;
 966        mt9p012_ctrl->pict_fps_divider = 1 * 0x00000400;
 967        mt9p012_ctrl->set_test = TEST_OFF;
 968        mt9p012_ctrl->prev_res = QTR_SIZE;
 969        mt9p012_ctrl->pict_res = FULL_SIZE;
 970
 971        if (data)
 972                mt9p012_ctrl->sensordata = data;
 973
 974        /* enable mclk first */
 975        msm_camio_clk_rate_set(MT9P012_DEFAULT_CLOCK_RATE);
 976        mdelay(20);
 977
 978        msm_camio_camif_pad_reg_reset();
 979        mdelay(20);
 980
 981        rc = mt9p012_probe_init_sensor(data);
 982        if (rc < 0)
 983                goto init_fail1;
 984
 985        if (mt9p012_ctrl->prev_res == QTR_SIZE)
 986                rc = mt9p012_setting(REG_INIT, RES_PREVIEW);
 987        else
 988                rc = mt9p012_setting(REG_INIT, RES_CAPTURE);
 989
 990        if (rc < 0) {
 991                CDBG("mt9p012_setting failed. rc = %d\n", rc);
 992                goto init_fail1;
 993        }
 994
 995        /* sensor : output enable */
 996        CDBG("mt9p012_sensor_open_init(): enabling output.\n");
 997        rc = mt9p012_i2c_write_w(mt9p012_client->addr,
 998                MT9P012_REG_RESET_REGISTER, MT9P012_RESET_REGISTER_PWON);
 999        if (rc < 0) {
1000                CDBG("sensor output enable failed. rc = %d\n", rc);
1001                goto init_fail1;
1002        }
1003
1004        /* TODO: enable AF actuator */
1005#if 0
1006        CDBG("enable AF actuator, gpio = %d\n",
1007                mt9p012_ctrl->sensordata->vcm_pwd);
1008        rc = gpio_request(mt9p012_ctrl->sensordata->vcm_pwd, "mt9p012");
1009        if (!rc)
1010                gpio_direction_output(mt9p012_ctrl->sensordata->vcm_pwd, 1);
1011        else {
1012                CDBG("mt9p012_ctrl gpio request failed!\n");
1013                goto init_fail1;
1014        }
1015        mdelay(20);
1016
1017        rc = mt9p012_set_default_focus();
1018#endif
1019        if (rc >= 0)
1020                goto init_done;
1021
1022        /* TODO:
1023         * gpio_direction_output(mt9p012_ctrl->sensordata->vcm_pwd, 0);
1024         * gpio_free(mt9p012_ctrl->sensordata->vcm_pwd); */
1025init_fail1:
1026        mt9p012_probe_init_done(data);
1027        kfree(mt9p012_ctrl);
1028init_done:
1029        return rc;
1030}
1031
1032static int mt9p012_init_client(struct i2c_client *client)
1033{
1034        /* Initialize the MSM_CAMI2C Chip */
1035        init_waitqueue_head(&mt9p012_wait_queue);
1036        return 0;
1037}
1038
1039static int32_t mt9p012_set_sensor_mode(int mode, int res)
1040{
1041        int32_t rc = 0;
1042
1043        switch (mode) {
1044        case SENSOR_PREVIEW_MODE:
1045                rc = mt9p012_video_config(mode, res);
1046                break;
1047
1048        case SENSOR_SNAPSHOT_MODE:
1049                rc = mt9p012_snapshot_config(mode);
1050                break;
1051
1052        case SENSOR_RAW_SNAPSHOT_MODE:
1053                rc = mt9p012_raw_snapshot_config(mode);
1054                break;
1055
1056        default:
1057                rc = -EINVAL;
1058                break;
1059        }
1060
1061        return rc;
1062}
1063
1064int mt9p012_sensor_config(void __user *argp)
1065{
1066        struct sensor_cfg_data cdata;
1067        int rc = 0;
1068
1069        if (copy_from_user(&cdata,
1070                        (void *)argp,
1071                        sizeof(struct sensor_cfg_data)))
1072                return -EFAULT;
1073
1074        down(&mt9p012_sem);
1075
1076                CDBG("%s: cfgtype = %d\n", __func__, cdata.cfgtype);
1077        switch (cdata.cfgtype) {
1078        case CFG_GET_PICT_FPS:
1079                mt9p012_get_pict_fps(cdata.cfg.gfps.prevfps,
1080                                &(cdata.cfg.gfps.pictfps));
1081
1082                if (copy_to_user((void *)argp, &cdata,
1083                                sizeof(struct sensor_cfg_data)))
1084                        rc = -EFAULT;
1085                break;
1086
1087        case CFG_GET_PREV_L_PF:
1088                cdata.cfg.prevl_pf = mt9p012_get_prev_lines_pf();
1089
1090                if (copy_to_user((void *)argp,
1091                                &cdata,
1092                                sizeof(struct sensor_cfg_data)))
1093                        rc = -EFAULT;
1094                break;
1095
1096        case CFG_GET_PREV_P_PL:
1097                cdata.cfg.prevp_pl = mt9p012_get_prev_pixels_pl();
1098
1099                if (copy_to_user((void *)argp,
1100                                &cdata,
1101                                sizeof(struct sensor_cfg_data)))
1102                        rc = -EFAULT;
1103                break;
1104
1105        case CFG_GET_PICT_L_PF:
1106                cdata.cfg.pictl_pf = mt9p012_get_pict_lines_pf();
1107
1108                if (copy_to_user((void *)argp,
1109                                &cdata,
1110                                sizeof(struct sensor_cfg_data)))
1111                        rc = -EFAULT;
1112                break;
1113
1114        case CFG_GET_PICT_P_PL:
1115                cdata.cfg.pictp_pl = mt9p012_get_pict_pixels_pl();
1116
1117                if (copy_to_user((void *)argp,
1118                                &cdata,
1119                                sizeof(struct sensor_cfg_data)))
1120                        rc = -EFAULT;
1121                break;
1122
1123        case CFG_GET_PICT_MAX_EXP_LC:
1124                cdata.cfg.pict_max_exp_lc =
1125                        mt9p012_get_pict_max_exp_lc();
1126
1127                if (copy_to_user((void *)argp,
1128                                &cdata,
1129                                sizeof(struct sensor_cfg_data)))
1130                        rc = -EFAULT;
1131                break;
1132
1133        case CFG_SET_FPS:
1134        case CFG_SET_PICT_FPS:
1135                rc = mt9p012_set_fps(&(cdata.cfg.fps));
1136                break;
1137
1138        case CFG_SET_EXP_GAIN:
1139                rc = mt9p012_write_exp_gain(cdata.cfg.exp_gain.gain,
1140                                cdata.cfg.exp_gain.line);
1141                break;
1142
1143        case CFG_SET_PICT_EXP_GAIN:
1144                CDBG("Line:%d CFG_SET_PICT_EXP_GAIN \n", __LINE__);
1145                rc = mt9p012_set_pict_exp_gain(cdata.cfg.exp_gain.gain,
1146                                cdata.cfg.exp_gain.line);
1147                break;
1148
1149        case CFG_SET_MODE:
1150                rc = mt9p012_set_sensor_mode(cdata.mode, cdata.rs);
1151                break;
1152
1153        case CFG_PWR_DOWN:
1154                rc = mt9p012_power_down();
1155                break;
1156
1157        case CFG_MOVE_FOCUS:
1158                CDBG("mt9p012_ioctl: CFG_MOVE_FOCUS: cdata.cfg.focus.dir=%d cdata.cfg.focus.steps=%d\n",
1159                                cdata.cfg.focus.dir, cdata.cfg.focus.steps);
1160                rc = mt9p012_move_focus(cdata.cfg.focus.dir,
1161                                        cdata.cfg.focus.steps);
1162                break;
1163
1164        case CFG_SET_DEFAULT_FOCUS:
1165                rc = mt9p012_set_default_focus();
1166                break;
1167
1168        case CFG_SET_LENS_SHADING:
1169                CDBG("%s: CFG_SET_LENS_SHADING\n", __func__);
1170                rc = mt9p012_lens_shading_enable(cdata.cfg.lens_shading);
1171                break;
1172
1173        case CFG_GET_AF_MAX_STEPS:
1174                cdata.max_steps = MT9P012_STEPS_NEAR_TO_CLOSEST_INF;
1175                if (copy_to_user((void *)argp,
1176                                &cdata,
1177                                sizeof(struct sensor_cfg_data)))
1178                        rc = -EFAULT;
1179                break;
1180
1181        case CFG_SET_EFFECT:
1182        default:
1183                rc = -EINVAL;
1184                break;
1185        }
1186
1187        up(&mt9p012_sem);
1188        return rc;
1189}
1190
1191int mt9p012_sensor_release(void)
1192{
1193        int rc = -EBADF;
1194
1195        down(&mt9p012_sem);
1196
1197        mt9p012_power_down();
1198
1199        gpio_direction_output(mt9p012_ctrl->sensordata->sensor_reset,
1200                0);
1201        gpio_free(mt9p012_ctrl->sensordata->sensor_reset);
1202
1203        gpio_direction_output(mt9p012_ctrl->sensordata->vcm_pwd, 0);
1204        gpio_free(mt9p012_ctrl->sensordata->vcm_pwd);
1205
1206        kfree(mt9p012_ctrl);
1207        mt9p012_ctrl = NULL;
1208
1209        CDBG("mt9p012_release completed\n");
1210
1211        up(&mt9p012_sem);
1212        return rc;
1213}
1214
1215static int mt9p012_i2c_probe(struct i2c_client *client,
1216        const struct i2c_device_id *id)
1217{
1218        int rc = 0;
1219        CDBG("mt9p012_probe called!\n");
1220
1221        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1222                CDBG("i2c_check_functionality failed\n");
1223                goto probe_failure;
1224        }
1225
1226        mt9p012_sensorw = kzalloc(sizeof(struct mt9p012_work), GFP_KERNEL);
1227        if (!mt9p012_sensorw) {
1228                CDBG("kzalloc failed.\n");
1229                rc = -ENOMEM;
1230                goto probe_failure;
1231        }
1232
1233        i2c_set_clientdata(client, mt9p012_sensorw);
1234        mt9p012_init_client(client);
1235        mt9p012_client = client;
1236
1237        mdelay(50);
1238
1239        CDBG("mt9p012_probe successed! rc = %d\n", rc);
1240        return 0;
1241
1242probe_failure:
1243        CDBG("mt9p012_probe failed! rc = %d\n", rc);
1244        return rc;
1245}
1246
1247static const struct i2c_device_id mt9p012_i2c_id[] = {
1248        { "mt9p012", 0},
1249        { }
1250};
1251
1252static struct i2c_driver mt9p012_i2c_driver = {
1253        .id_table = mt9p012_i2c_id,
1254        .probe  = mt9p012_i2c_probe,
1255        .remove = __exit_p(mt9p012_i2c_remove),
1256        .driver = {
1257                .name = "mt9p012",
1258        },
1259};
1260
1261static int mt9p012_sensor_probe(const struct msm_camera_sensor_info *info,
1262                                struct msm_sensor_ctrl *s)
1263{
1264        int rc = i2c_add_driver(&mt9p012_i2c_driver);
1265        if (rc < 0 || mt9p012_client == NULL) {
1266                rc = -ENOTSUPP;
1267                goto probe_done;
1268        }
1269
1270        msm_camio_clk_rate_set(MT9P012_DEFAULT_CLOCK_RATE);
1271        mdelay(20);
1272
1273        rc = mt9p012_probe_init_sensor(info);
1274        if (rc < 0)
1275                goto probe_done;
1276
1277        s->s_init = mt9p012_sensor_open_init;
1278        s->s_release = mt9p012_sensor_release;
1279        s->s_config  = mt9p012_sensor_config;
1280        mt9p012_probe_init_done(info);
1281
1282probe_done:
1283        CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
1284        return rc;
1285}
1286
1287static int __mt9p012_probe(struct platform_device *pdev)
1288{
1289        return msm_camera_drv_start(pdev, mt9p012_sensor_probe);
1290}
1291
1292static struct platform_driver msm_camera_driver = {
1293        .probe = __mt9p012_probe,
1294        .driver = {
1295                .name = "msm_camera_mt9p012",
1296                .owner = THIS_MODULE,
1297        },
1298};
1299
1300static int __init mt9p012_init(void)
1301{
1302        return platform_driver_register(&msm_camera_driver);
1303}
1304
1305module_init(mt9p012_init);
1306