linux/drivers/media/usb/gspca/m5602/m5602_ov9650.c
<<
>>
Prefs
   1
   2/*
   3 * Driver for the ov9650 sensor
   4 *
   5 * Copyright (C) 2008 Erik Andrén
   6 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
   7 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
   8 *
   9 * Portions of code to USB interface and ALi driver software,
  10 * Copyright (c) 2006 Willem Duinker
  11 * v4l2 interface modeled after the V4L2 driver
  12 * for SN9C10x PC Camera Controllers
  13 *
  14 * This program is free software; you can redistribute it and/or
  15 * modify it under the terms of the GNU General Public License as
  16 * published by the Free Software Foundation, version 2.
  17 *
  18 */
  19
  20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  21
  22#include "m5602_ov9650.h"
  23
  24static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl);
  25static void ov9650_dump_registers(struct sd *sd);
  26
  27static const unsigned char preinit_ov9650[][3] = {
  28        /* [INITCAM] */
  29        {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
  30        {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
  31        {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
  32        {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
  33        {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
  34        {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
  35
  36        {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
  37        {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
  38        {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
  39        {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
  40        {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
  41        {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
  42        {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
  43        {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
  44        /* Reset chip */
  45        {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
  46        /* Enable double clock */
  47        {SENSOR, OV9650_CLKRC, 0x80},
  48        /* Do something out of spec with the power */
  49        {SENSOR, OV9650_OFON, 0x40}
  50};
  51
  52static const unsigned char init_ov9650[][3] = {
  53        /* [INITCAM] */
  54        {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
  55        {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
  56        {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
  57        {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
  58        {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
  59        {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
  60
  61        {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
  62        {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
  63        {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
  64        {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
  65        {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
  66        {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
  67        {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
  68        {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
  69
  70        /* Reset chip */
  71        {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
  72        /* One extra reset is needed in order to make the sensor behave
  73           properly when resuming from ram, could be a timing issue */
  74        {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
  75
  76        /* Enable double clock */
  77        {SENSOR, OV9650_CLKRC, 0x80},
  78        /* Do something out of spec with the power */
  79        {SENSOR, OV9650_OFON, 0x40},
  80
  81        /* Set fast AGC/AEC algorithm with unlimited step size */
  82        {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
  83                              OV9650_AEC_UNLIM_STEP_SIZE},
  84
  85        {SENSOR, OV9650_CHLF, 0x10},
  86        {SENSOR, OV9650_ARBLM, 0xbf},
  87        {SENSOR, OV9650_ACOM38, 0x81},
  88        /* Turn off color matrix coefficient double option */
  89        {SENSOR, OV9650_COM16, 0x00},
  90        /* Enable color matrix for RGB/YUV, Delay Y channel,
  91        set output Y/UV delay to 1 */
  92        {SENSOR, OV9650_COM13, 0x19},
  93        /* Enable digital BLC, Set output mode to U Y V Y */
  94        {SENSOR, OV9650_TSLB, 0x0c},
  95        /* Limit the AGC/AEC stable upper region */
  96        {SENSOR, OV9650_COM24, 0x00},
  97        /* Enable HREF and some out of spec things */
  98        {SENSOR, OV9650_COM12, 0x73},
  99        /* Set all DBLC offset signs to positive and
 100        do some out of spec stuff */
 101        {SENSOR, OV9650_DBLC1, 0xdf},
 102        {SENSOR, OV9650_COM21, 0x06},
 103        {SENSOR, OV9650_RSVD35, 0x91},
 104        /* Necessary, no camera stream without it */
 105        {SENSOR, OV9650_RSVD16, 0x06},
 106        {SENSOR, OV9650_RSVD94, 0x99},
 107        {SENSOR, OV9650_RSVD95, 0x99},
 108        {SENSOR, OV9650_RSVD96, 0x04},
 109        /* Enable full range output */
 110        {SENSOR, OV9650_COM15, 0x0},
 111        /* Enable HREF at optical black, enable ADBLC bias,
 112        enable ADBLC, reset timings at format change */
 113        {SENSOR, OV9650_COM6, 0x4b},
 114        /* Subtract 32 from the B channel bias */
 115        {SENSOR, OV9650_BBIAS, 0xa0},
 116        /* Subtract 32 from the Gb channel bias */
 117        {SENSOR, OV9650_GbBIAS, 0xa0},
 118        /* Do not bypass the analog BLC and to some out of spec stuff */
 119        {SENSOR, OV9650_Gr_COM, 0x00},
 120        /* Subtract 32 from the R channel bias */
 121        {SENSOR, OV9650_RBIAS, 0xa0},
 122        /* Subtract 32 from the R channel bias */
 123        {SENSOR, OV9650_RBIAS, 0x0},
 124        {SENSOR, OV9650_COM26, 0x80},
 125        {SENSOR, OV9650_ACOMA9, 0x98},
 126        /* Set the AGC/AEC stable region upper limit */
 127        {SENSOR, OV9650_AEW, 0x68},
 128        /* Set the AGC/AEC stable region lower limit */
 129        {SENSOR, OV9650_AEB, 0x5c},
 130        /* Set the high and low limit nibbles to 3 */
 131        {SENSOR, OV9650_VPT, 0xc3},
 132        /* Set the Automatic Gain Ceiling (AGC) to 128x,
 133        drop VSYNC at frame drop,
 134        limit exposure timing,
 135        drop frame when the AEC step is larger than the exposure gap */
 136        {SENSOR, OV9650_COM9, 0x6e},
 137        /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
 138        and set PWDN to SLVS (slave mode vertical sync) */
 139        {SENSOR, OV9650_COM10, 0x42},
 140        /* Set horizontal column start high to default value */
 141        {SENSOR, OV9650_HSTART, 0x1a}, /* 210 */
 142        /* Set horizontal column end */
 143        {SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */
 144        /* Complementing register to the two writes above */
 145        {SENSOR, OV9650_HREF, 0xb2},
 146        /* Set vertical row start high bits */
 147        {SENSOR, OV9650_VSTRT, 0x02},
 148        /* Set vertical row end low bits */
 149        {SENSOR, OV9650_VSTOP, 0x7e},
 150        /* Set complementing vertical frame control */
 151        {SENSOR, OV9650_VREF, 0x10},
 152        {SENSOR, OV9650_ADC, 0x04},
 153        {SENSOR, OV9650_HV, 0x40},
 154
 155        /* Enable denoise, and white-pixel erase */
 156        {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
 157                 OV9650_WHITE_PIXEL_ENABLE |
 158                 OV9650_WHITE_PIXEL_OPTION},
 159
 160        /* Enable VARIOPIXEL */
 161        {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
 162        {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
 163
 164        /* Put the sensor in soft sleep mode */
 165        {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
 166};
 167
 168static const unsigned char res_init_ov9650[][3] = {
 169        {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
 170
 171        {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
 172        {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
 173        {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
 174        {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
 175        {BRIDGE, M5602_XB_SIG_INI, 0x01}
 176};
 177
 178/* Vertically and horizontally flips the image if matched, needed for machines
 179   where the sensor is mounted upside down */
 180static
 181    const
 182        struct dmi_system_id ov9650_flip_dmi_table[] = {
 183        {
 184                .ident = "ASUS A6Ja",
 185                .matches = {
 186                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 187                        DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
 188                }
 189        },
 190        {
 191                .ident = "ASUS A6JC",
 192                .matches = {
 193                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 194                        DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
 195                }
 196        },
 197        {
 198                .ident = "ASUS A6K",
 199                .matches = {
 200                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 201                        DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
 202                }
 203        },
 204        {
 205                .ident = "ASUS A6Kt",
 206                .matches = {
 207                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 208                        DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
 209                }
 210        },
 211        {
 212                .ident = "ASUS A6VA",
 213                .matches = {
 214                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 215                        DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
 216                }
 217        },
 218        {
 219
 220                .ident = "ASUS A6VC",
 221                .matches = {
 222                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 223                        DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
 224                }
 225        },
 226        {
 227                .ident = "ASUS A6VM",
 228                .matches = {
 229                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 230                        DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
 231                }
 232        },
 233        {
 234                .ident = "ASUS A7V",
 235                .matches = {
 236                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 237                        DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
 238                }
 239        },
 240        {
 241                .ident = "Alienware Aurora m9700",
 242                .matches = {
 243                        DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
 244                        DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
 245                }
 246        },
 247        {}
 248};
 249
 250static struct v4l2_pix_format ov9650_modes[] = {
 251        {
 252                176,
 253                144,
 254                V4L2_PIX_FMT_SBGGR8,
 255                V4L2_FIELD_NONE,
 256                .sizeimage =
 257                        176 * 144,
 258                .bytesperline = 176,
 259                .colorspace = V4L2_COLORSPACE_SRGB,
 260                .priv = 9
 261        }, {
 262                320,
 263                240,
 264                V4L2_PIX_FMT_SBGGR8,
 265                V4L2_FIELD_NONE,
 266                .sizeimage =
 267                        320 * 240,
 268                .bytesperline = 320,
 269                .colorspace = V4L2_COLORSPACE_SRGB,
 270                .priv = 8
 271        }, {
 272                352,
 273                288,
 274                V4L2_PIX_FMT_SBGGR8,
 275                V4L2_FIELD_NONE,
 276                .sizeimage =
 277                        352 * 288,
 278                .bytesperline = 352,
 279                .colorspace = V4L2_COLORSPACE_SRGB,
 280                .priv = 9
 281        }, {
 282                640,
 283                480,
 284                V4L2_PIX_FMT_SBGGR8,
 285                V4L2_FIELD_NONE,
 286                .sizeimage =
 287                        640 * 480,
 288                .bytesperline = 640,
 289                .colorspace = V4L2_COLORSPACE_SRGB,
 290                .priv = 9
 291        }
 292};
 293
 294static const struct v4l2_ctrl_ops ov9650_ctrl_ops = {
 295        .s_ctrl = ov9650_s_ctrl,
 296};
 297
 298int ov9650_probe(struct sd *sd)
 299{
 300        int err = 0;
 301        u8 prod_id = 0, ver_id = 0, i;
 302        struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 303
 304        if (force_sensor) {
 305                if (force_sensor == OV9650_SENSOR) {
 306                        pr_info("Forcing an %s sensor\n", ov9650.name);
 307                        goto sensor_found;
 308                }
 309                /* If we want to force another sensor,
 310                   don't try to probe this one */
 311                return -ENODEV;
 312        }
 313
 314        gspca_dbg(gspca_dev, D_PROBE, "Probing for an ov9650 sensor\n");
 315
 316        /* Run the pre-init before probing the sensor */
 317        for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
 318                u8 data = preinit_ov9650[i][2];
 319                if (preinit_ov9650[i][0] == SENSOR)
 320                        err = m5602_write_sensor(sd,
 321                                preinit_ov9650[i][1], &data, 1);
 322                else
 323                        err = m5602_write_bridge(sd,
 324                                preinit_ov9650[i][1], data);
 325        }
 326
 327        if (err < 0)
 328                return err;
 329
 330        if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
 331                return -ENODEV;
 332
 333        if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
 334                return -ENODEV;
 335
 336        if ((prod_id == 0x96) && (ver_id == 0x52)) {
 337                pr_info("Detected an ov9650 sensor\n");
 338                goto sensor_found;
 339        }
 340        return -ENODEV;
 341
 342sensor_found:
 343        sd->gspca_dev.cam.cam_mode = ov9650_modes;
 344        sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
 345
 346        return 0;
 347}
 348
 349int ov9650_init(struct sd *sd)
 350{
 351        int i, err = 0;
 352        u8 data;
 353
 354        if (dump_sensor)
 355                ov9650_dump_registers(sd);
 356
 357        for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
 358                data = init_ov9650[i][2];
 359                if (init_ov9650[i][0] == SENSOR)
 360                        err = m5602_write_sensor(sd, init_ov9650[i][1],
 361                                                  &data, 1);
 362                else
 363                        err = m5602_write_bridge(sd, init_ov9650[i][1], data);
 364        }
 365
 366        return 0;
 367}
 368
 369int ov9650_init_controls(struct sd *sd)
 370{
 371        struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
 372
 373        sd->gspca_dev.vdev.ctrl_handler = hdl;
 374        v4l2_ctrl_handler_init(hdl, 9);
 375
 376        sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
 377                                               V4L2_CID_AUTO_WHITE_BALANCE,
 378                                               0, 1, 1, 1);
 379        sd->red_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
 380                                        V4L2_CID_RED_BALANCE, 0, 255, 1,
 381                                        RED_GAIN_DEFAULT);
 382        sd->blue_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
 383                                        V4L2_CID_BLUE_BALANCE, 0, 255, 1,
 384                                        BLUE_GAIN_DEFAULT);
 385
 386        sd->autoexpo = v4l2_ctrl_new_std_menu(hdl, &ov9650_ctrl_ops,
 387                          V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO);
 388        sd->expo = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_EXPOSURE,
 389                          0, 0x1ff, 4, EXPOSURE_DEFAULT);
 390
 391        sd->autogain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
 392                                         V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 393        sd->gain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_GAIN, 0,
 394                                     0x3ff, 1, GAIN_DEFAULT);
 395
 396        sd->hflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_HFLIP,
 397                                      0, 1, 1, 0);
 398        sd->vflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_VFLIP,
 399                                      0, 1, 1, 0);
 400
 401        if (hdl->error) {
 402                pr_err("Could not initialize controls\n");
 403                return hdl->error;
 404        }
 405
 406        v4l2_ctrl_auto_cluster(3, &sd->auto_white_bal, 0, false);
 407        v4l2_ctrl_auto_cluster(2, &sd->autoexpo, 0, false);
 408        v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
 409        v4l2_ctrl_cluster(2, &sd->hflip);
 410
 411        return 0;
 412}
 413
 414int ov9650_start(struct sd *sd)
 415{
 416        u8 data;
 417        int i, err = 0;
 418        struct cam *cam = &sd->gspca_dev.cam;
 419
 420        int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
 421        int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
 422        int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 423        int hor_offs = OV9650_LEFT_OFFSET;
 424        struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 425
 426        if ((!dmi_check_system(ov9650_flip_dmi_table) &&
 427                sd->vflip->val) ||
 428                (dmi_check_system(ov9650_flip_dmi_table) &&
 429                !sd->vflip->val))
 430                ver_offs--;
 431
 432        if (width <= 320)
 433                hor_offs /= 2;
 434
 435        /* Synthesize the vsync/hsync setup */
 436        for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
 437                if (res_init_ov9650[i][0] == BRIDGE)
 438                        err = m5602_write_bridge(sd, res_init_ov9650[i][1],
 439                                res_init_ov9650[i][2]);
 440                else if (res_init_ov9650[i][0] == SENSOR) {
 441                        data = res_init_ov9650[i][2];
 442                        err = m5602_write_sensor(sd,
 443                                res_init_ov9650[i][1], &data, 1);
 444                }
 445        }
 446        if (err < 0)
 447                return err;
 448
 449        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
 450                                 ((ver_offs >> 8) & 0xff));
 451        if (err < 0)
 452                return err;
 453
 454        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
 455        if (err < 0)
 456                return err;
 457
 458        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
 459        if (err < 0)
 460                return err;
 461
 462        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
 463        if (err < 0)
 464                return err;
 465
 466        err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
 467        if (err < 0)
 468                return err;
 469
 470        for (i = 0; i < 2 && !err; i++)
 471                err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
 472        if (err < 0)
 473                return err;
 474
 475        err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
 476        if (err < 0)
 477                return err;
 478
 479        err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
 480        if (err < 0)
 481                return err;
 482
 483        err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
 484                                 (hor_offs >> 8) & 0xff);
 485        if (err < 0)
 486                return err;
 487
 488        err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
 489        if (err < 0)
 490                return err;
 491
 492        err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
 493                                 ((width + hor_offs) >> 8) & 0xff);
 494        if (err < 0)
 495                return err;
 496
 497        err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
 498                                 ((width + hor_offs) & 0xff));
 499        if (err < 0)
 500                return err;
 501
 502        err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
 503        if (err < 0)
 504                return err;
 505
 506        switch (width) {
 507        case 640:
 508                gspca_dbg(gspca_dev, D_CONF, "Configuring camera for VGA mode\n");
 509
 510                data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
 511                       OV9650_RAW_RGB_SELECT;
 512                err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
 513                break;
 514
 515        case 352:
 516                gspca_dbg(gspca_dev, D_CONF, "Configuring camera for CIF mode\n");
 517
 518                data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
 519                                OV9650_RAW_RGB_SELECT;
 520                err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
 521                break;
 522
 523        case 320:
 524                gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QVGA mode\n");
 525
 526                data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
 527                                OV9650_RAW_RGB_SELECT;
 528                err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
 529                break;
 530
 531        case 176:
 532                gspca_dbg(gspca_dev, D_CONF, "Configuring camera for QCIF mode\n");
 533
 534                data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
 535                        OV9650_RAW_RGB_SELECT;
 536                err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
 537                break;
 538        }
 539        return err;
 540}
 541
 542int ov9650_stop(struct sd *sd)
 543{
 544        u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
 545        return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
 546}
 547
 548void ov9650_disconnect(struct sd *sd)
 549{
 550        ov9650_stop(sd);
 551
 552        sd->sensor = NULL;
 553}
 554
 555static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 556{
 557        struct sd *sd = (struct sd *) gspca_dev;
 558        u8 i2c_data;
 559        int err;
 560
 561        gspca_dbg(gspca_dev, D_CONF, "Set exposure to %d\n", val);
 562
 563        /* The 6 MSBs */
 564        i2c_data = (val >> 10) & 0x3f;
 565        err = m5602_write_sensor(sd, OV9650_AECHM,
 566                                  &i2c_data, 1);
 567        if (err < 0)
 568                return err;
 569
 570        /* The 8 middle bits */
 571        i2c_data = (val >> 2) & 0xff;
 572        err = m5602_write_sensor(sd, OV9650_AECH,
 573                                  &i2c_data, 1);
 574        if (err < 0)
 575                return err;
 576
 577        /* The 2 LSBs */
 578        i2c_data = val & 0x03;
 579        err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
 580        return err;
 581}
 582
 583static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 584{
 585        int err;
 586        u8 i2c_data;
 587        struct sd *sd = (struct sd *) gspca_dev;
 588
 589        gspca_dbg(gspca_dev, D_CONF, "Setting gain to %d\n", val);
 590
 591        /* The 2 MSB */
 592        /* Read the OV9650_VREF register first to avoid
 593           corrupting the VREF high and low bits */
 594        err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
 595        if (err < 0)
 596                return err;
 597
 598        /* Mask away all uninteresting bits */
 599        i2c_data = ((val & 0x0300) >> 2) |
 600                        (i2c_data & 0x3f);
 601        err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
 602        if (err < 0)
 603                return err;
 604
 605        /* The 8 LSBs */
 606        i2c_data = val & 0xff;
 607        err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
 608        return err;
 609}
 610
 611static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
 612{
 613        int err;
 614        u8 i2c_data;
 615        struct sd *sd = (struct sd *) gspca_dev;
 616
 617        gspca_dbg(gspca_dev, D_CONF, "Set red gain to %d\n", val);
 618
 619        i2c_data = val & 0xff;
 620        err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
 621        return err;
 622}
 623
 624static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 625{
 626        int err;
 627        u8 i2c_data;
 628        struct sd *sd = (struct sd *) gspca_dev;
 629
 630        gspca_dbg(gspca_dev, D_CONF, "Set blue gain to %d\n", val);
 631
 632        i2c_data = val & 0xff;
 633        err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
 634        return err;
 635}
 636
 637static int ov9650_set_hvflip(struct gspca_dev *gspca_dev)
 638{
 639        int err;
 640        u8 i2c_data;
 641        struct sd *sd = (struct sd *) gspca_dev;
 642        int hflip = sd->hflip->val;
 643        int vflip = sd->vflip->val;
 644
 645        gspca_dbg(gspca_dev, D_CONF, "Set hvflip to %d %d\n", hflip, vflip);
 646
 647        if (dmi_check_system(ov9650_flip_dmi_table))
 648                vflip = !vflip;
 649
 650        i2c_data = (hflip << 5) | (vflip << 4);
 651        err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
 652        if (err < 0)
 653                return err;
 654
 655        /* When vflip is toggled we need to readjust the bridge hsync/vsync */
 656        if (gspca_dev->streaming)
 657                err = ov9650_start(sd);
 658
 659        return err;
 660}
 661
 662static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
 663                                    __s32 val)
 664{
 665        int err;
 666        u8 i2c_data;
 667        struct sd *sd = (struct sd *) gspca_dev;
 668
 669        gspca_dbg(gspca_dev, D_CONF, "Set auto exposure control to %d\n", val);
 670
 671        err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 672        if (err < 0)
 673                return err;
 674
 675        val = (val == V4L2_EXPOSURE_AUTO);
 676        i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
 677
 678        return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 679}
 680
 681static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
 682                                         __s32 val)
 683{
 684        int err;
 685        u8 i2c_data;
 686        struct sd *sd = (struct sd *) gspca_dev;
 687
 688        gspca_dbg(gspca_dev, D_CONF, "Set auto white balance to %d\n", val);
 689
 690        err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 691        if (err < 0)
 692                return err;
 693
 694        i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
 695        err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 696
 697        return err;
 698}
 699
 700static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
 701{
 702        int err;
 703        u8 i2c_data;
 704        struct sd *sd = (struct sd *) gspca_dev;
 705
 706        gspca_dbg(gspca_dev, D_CONF, "Set auto gain control to %d\n", val);
 707
 708        err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 709        if (err < 0)
 710                return err;
 711
 712        i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
 713
 714        return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 715}
 716
 717static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl)
 718{
 719        struct gspca_dev *gspca_dev =
 720                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 721        struct sd *sd = (struct sd *) gspca_dev;
 722        int err;
 723
 724        if (!gspca_dev->streaming)
 725                return 0;
 726
 727        switch (ctrl->id) {
 728        case V4L2_CID_AUTO_WHITE_BALANCE:
 729                err = ov9650_set_auto_white_balance(gspca_dev, ctrl->val);
 730                if (err || ctrl->val)
 731                        return err;
 732                err = ov9650_set_red_balance(gspca_dev, sd->red_bal->val);
 733                if (err)
 734                        return err;
 735                err = ov9650_set_blue_balance(gspca_dev, sd->blue_bal->val);
 736                break;
 737        case V4L2_CID_EXPOSURE_AUTO:
 738                err = ov9650_set_auto_exposure(gspca_dev, ctrl->val);
 739                if (err || ctrl->val == V4L2_EXPOSURE_AUTO)
 740                        return err;
 741                err = ov9650_set_exposure(gspca_dev, sd->expo->val);
 742                break;
 743        case V4L2_CID_AUTOGAIN:
 744                err = ov9650_set_auto_gain(gspca_dev, ctrl->val);
 745                if (err || ctrl->val)
 746                        return err;
 747                err = ov9650_set_gain(gspca_dev, sd->gain->val);
 748                break;
 749        case V4L2_CID_HFLIP:
 750                err = ov9650_set_hvflip(gspca_dev);
 751                break;
 752        default:
 753                return -EINVAL;
 754        }
 755
 756        return err;
 757}
 758
 759static void ov9650_dump_registers(struct sd *sd)
 760{
 761        int address;
 762        pr_info("Dumping the ov9650 register state\n");
 763        for (address = 0; address < 0xa9; address++) {
 764                u8 value;
 765                m5602_read_sensor(sd, address, &value, 1);
 766                pr_info("register 0x%x contains 0x%x\n", address, value);
 767        }
 768
 769        pr_info("ov9650 register state dump complete\n");
 770
 771        pr_info("Probing for which registers that are read/write\n");
 772        for (address = 0; address < 0xff; address++) {
 773                u8 old_value, ctrl_value;
 774                u8 test_value[2] = {0xff, 0xff};
 775
 776                m5602_read_sensor(sd, address, &old_value, 1);
 777                m5602_write_sensor(sd, address, test_value, 1);
 778                m5602_read_sensor(sd, address, &ctrl_value, 1);
 779
 780                if (ctrl_value == test_value[0])
 781                        pr_info("register 0x%x is writeable\n", address);
 782                else
 783                        pr_info("register 0x%x is read only\n", address);
 784
 785                /* Restore original value */
 786                m5602_write_sensor(sd, address, &old_value, 1);
 787        }
 788}
 789