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