14763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén/* 24763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * Driver for the ov7660 sensor 34763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * 44763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * Copyright (C) 2009 Erik Andrén 54763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. 64763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> 74763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * 84763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * Portions of code to USB interface and ALi driver software, 94763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * Copyright (c) 2006 Willem Duinker 104763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * v4l2 interface modeled after the V4L2 driver 114763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * for SN9C10x PC Camera Controllers 124763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * 134763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * This program is free software; you can redistribute it and/or 144763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * modify it under the terms of the GNU General Public License as 154763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * published by the Free Software Foundation, version 2. 164763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén * 174763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén */ 184763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 19bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches 214763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén#include "m5602_ov7660.h" 224763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 23c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrénstatic int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 24c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrénstatic int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val); 25f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrénstatic int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev, 26f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén __s32 *val); 27f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrénstatic int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, 28f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén __s32 val); 29456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrénstatic int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); 30456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrénstatic int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); 317c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrénstatic int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); 327c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrénstatic int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val); 33a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrénstatic int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 34a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrénstatic int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 35a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrénstatic int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 36a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrénstatic int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 37c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 38f0ecba96e76295792a0b1ee2e03b505562e7b9f3Tobias Klauserstatic const struct ctrl ov7660_ctrls[] = { 39c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén#define GAIN_IDX 1 40c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén { 41c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén { 42c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .id = V4L2_CID_GAIN, 43c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .type = V4L2_CTRL_TYPE_INTEGER, 44c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .name = "gain", 45c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .minimum = 0x00, 46c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .maximum = 0xff, 47c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .step = 0x1, 4872b79747a88f1ffcb6689cedacc01235bb545cd6Erik Andrén .default_value = OV7660_DEFAULT_GAIN, 49c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .flags = V4L2_CTRL_FLAG_SLIDER 50c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén }, 51c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .set = ov7660_set_gain, 52c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén .get = ov7660_get_gain 53c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén }, 54cbd1f7fb7059c629cb9e5131a755febc906496a6Erik Andrén#define BLUE_BALANCE_IDX 2 5568fdb7a5b52cb060f7824f9d6e98e105af36a474Erik Andrén#define RED_BALANCE_IDX 3 56f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén#define AUTO_WHITE_BALANCE_IDX 4 57f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén { 58f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén { 59780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .id = V4L2_CID_AUTO_WHITE_BALANCE, 60780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .type = V4L2_CTRL_TYPE_BOOLEAN, 61780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .name = "auto white balance", 62780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .minimum = 0, 63780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .maximum = 1, 64780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .step = 1, 65780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .default_value = 1 66f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén }, 67f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén .set = ov7660_set_auto_white_balance, 68f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén .get = ov7660_get_auto_white_balance 69f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén }, 70456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén#define AUTO_GAIN_CTRL_IDX 5 71456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén { 72456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén { 73780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .id = V4L2_CID_AUTOGAIN, 74780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .type = V4L2_CTRL_TYPE_BOOLEAN, 75780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .name = "auto gain control", 76780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .minimum = 0, 77780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .maximum = 1, 78780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .step = 1, 79780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .default_value = 1 80456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén }, 81456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén .set = ov7660_set_auto_gain, 82456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén .get = ov7660_get_auto_gain 83456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén }, 847c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén#define AUTO_EXPOSURE_IDX 6 857c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén { 867c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén { 87780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .id = V4L2_CID_EXPOSURE_AUTO, 88780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .type = V4L2_CTRL_TYPE_BOOLEAN, 89780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .name = "auto exposure", 90780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .minimum = 0, 91780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .maximum = 1, 92780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .step = 1, 93780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .default_value = 1 947c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén }, 957c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén .set = ov7660_set_auto_exposure, 967c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén .get = ov7660_get_auto_exposure 97a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén }, 98a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén#define HFLIP_IDX 7 99a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén { 100a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén { 101780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .id = V4L2_CID_HFLIP, 102780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .type = V4L2_CTRL_TYPE_BOOLEAN, 103780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .name = "horizontal flip", 104780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .minimum = 0, 105780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .maximum = 1, 106780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .step = 1, 107780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .default_value = 0 108a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén }, 109a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén .set = ov7660_set_hflip, 110a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén .get = ov7660_get_hflip 111a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén }, 112a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén#define VFLIP_IDX 8 113a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén { 114a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén { 115780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .id = V4L2_CID_VFLIP, 116780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .type = V4L2_CTRL_TYPE_BOOLEAN, 117780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .name = "vertical flip", 118780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .minimum = 0, 119780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .maximum = 1, 120780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .step = 1, 121780e312175f688ab5ab6124c91d46fa2b9afe2d2Jean-François Moine .default_value = 0 122a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén }, 123a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén .set = ov7660_set_vflip, 124a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén .get = ov7660_get_vflip 125a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén }, 126a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 127c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén}; 1284763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 1294763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrénstatic struct v4l2_pix_format ov7660_modes[] = { 1304763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén { 1314763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 640, 1324763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 480, 1334763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén V4L2_PIX_FMT_SBGGR8, 1344763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén V4L2_FIELD_NONE, 1354763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén .sizeimage = 1364763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 640 * 480, 1374763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén .bytesperline = 640, 1384763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén .colorspace = V4L2_COLORSPACE_SRGB, 1394763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén .priv = 0 1404763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén } 1414763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén}; 1424763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 1434763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrénstatic void ov7660_dump_registers(struct sd *sd); 1444763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 1454763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrénint ov7660_probe(struct sd *sd) 1464763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén{ 147ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén int err = 0, i; 148ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén u8 prod_id = 0, ver_id = 0; 149ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 150ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén s32 *sensor_settings; 151ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 152ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén if (force_sensor) { 153ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén if (force_sensor == OV7660_SENSOR) { 154bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("Forcing an %s sensor\n", ov7660.name); 155ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén goto sensor_found; 156ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén } 157ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén /* If we want to force another sensor, 158ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén don't try to probe this one */ 159ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén return -ENODEV; 160ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén } 161ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 162ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén /* Do the preinit */ 163ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) { 164ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén u8 data[2]; 165ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 166ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén if (preinit_ov7660[i][0] == BRIDGE) { 167ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén err = m5602_write_bridge(sd, 168ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén preinit_ov7660[i][1], 169ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén preinit_ov7660[i][2]); 170ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén } else { 171ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén data[0] = preinit_ov7660[i][2]; 172ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén err = m5602_write_sensor(sd, 173ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén preinit_ov7660[i][1], data, 1); 174ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén } 175ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén } 176ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén if (err < 0) 177ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén return err; 178ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 179ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1)) 180ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén return -ENODEV; 181ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 182ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1)) 183ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén return -ENODEV; 184ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 185bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id); 186ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 187ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén if ((prod_id == 0x76) && (ver_id == 0x60)) { 188bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("Detected a ov7660 sensor\n"); 189ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén goto sensor_found; 190ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén } 1914763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén return -ENODEV; 192ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 193ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrénsensor_found: 194c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén sensor_settings = kmalloc( 195c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL); 196c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén if (!sensor_settings) 197c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén return -ENOMEM; 198c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 199ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén sd->gspca_dev.cam.cam_mode = ov7660_modes; 200ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); 201ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén sd->desc->ctrls = ov7660_ctrls; 202ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls); 203ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 204ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++) 205ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value; 206ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén sd->sensor_priv = sensor_settings; 207ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén 208ea8f74b168aa4d725c6d1ab98ef4eb4f6f3f3358Erik Andrén return 0; 2094763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén} 2104763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 2114763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrénint ov7660_init(struct sd *sd) 2124763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén{ 2130364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén int i, err = 0; 214c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén s32 *sensor_settings = sd->sensor_priv; 2150364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén 2160364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén /* Init the sensor */ 217eb3678fbe5d5be8315628885b7c93228c97a433dErik Andrén for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) { 2180364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén u8 data[2]; 2190364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén 220eb3678fbe5d5be8315628885b7c93228c97a433dErik Andrén if (init_ov7660[i][0] == BRIDGE) { 2210364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén err = m5602_write_bridge(sd, 222eb3678fbe5d5be8315628885b7c93228c97a433dErik Andrén init_ov7660[i][1], 223eb3678fbe5d5be8315628885b7c93228c97a433dErik Andrén init_ov7660[i][2]); 2240364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén } else { 225eb3678fbe5d5be8315628885b7c93228c97a433dErik Andrén data[0] = init_ov7660[i][2]; 2260364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén err = m5602_write_sensor(sd, 227eb3678fbe5d5be8315628885b7c93228c97a433dErik Andrén init_ov7660[i][1], data, 1); 2280364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén } 2290364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén } 2300364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén 2310364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén if (dump_sensor) 2320364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén ov7660_dump_registers(sd); 2330364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén 234c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 235c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén if (err < 0) 236c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén return err; 237c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 238f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén err = ov7660_set_auto_white_balance(&sd->gspca_dev, 239f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén sensor_settings[AUTO_WHITE_BALANCE_IDX]); 24036e64d5cec0a210d87e8e8c02566a1cbe24c00f3Erik Andrén if (err < 0) 24136e64d5cec0a210d87e8e8c02566a1cbe24c00f3Erik Andrén return err; 24236e64d5cec0a210d87e8e8c02566a1cbe24c00f3Erik Andrén 243456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén err = ov7660_set_auto_gain(&sd->gspca_dev, 244456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén sensor_settings[AUTO_GAIN_CTRL_IDX]); 245456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén if (err < 0) 246456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén return err; 247456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén 2487c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén err = ov7660_set_auto_exposure(&sd->gspca_dev, 2497c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén sensor_settings[AUTO_EXPOSURE_IDX]); 2507c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén if (err < 0) 2517c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén return err; 252a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén err = ov7660_set_hflip(&sd->gspca_dev, 253a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén sensor_settings[HFLIP_IDX]); 254a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén if (err < 0) 255a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén return err; 256a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 257a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén err = ov7660_set_vflip(&sd->gspca_dev, 258a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén sensor_settings[VFLIP_IDX]); 259f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén 2600364c4ca345175daa36c3c672fdecafd469e05a8Erik Andrén return err; 2614763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén} 2624763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 2634763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrénint ov7660_start(struct sd *sd) 2644763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén{ 2654763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén return 0; 2664763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén} 2674763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 2684763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrénint ov7660_stop(struct sd *sd) 2694763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén{ 2704763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén return 0; 2714763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén} 2724763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 273c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrénvoid ov7660_disconnect(struct sd *sd) 274c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén{ 275c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén ov7660_stop(sd); 276c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 277c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén sd->sensor = NULL; 278c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén kfree(sd->sensor_priv); 279c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén} 280c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 281c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrénstatic int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val) 282c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén{ 283c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén struct sd *sd = (struct sd *) gspca_dev; 284c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén s32 *sensor_settings = sd->sensor_priv; 285c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 286c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén *val = sensor_settings[GAIN_IDX]; 287c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén PDEBUG(D_V4L2, "Read gain %d", *val); 288c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén return 0; 289c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén} 290c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 291c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrénstatic int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val) 292c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén{ 293c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén int err; 294c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén u8 i2c_data; 295c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén struct sd *sd = (struct sd *) gspca_dev; 296c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén s32 *sensor_settings = sd->sensor_priv; 297c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 298c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén PDEBUG(D_V4L2, "Setting gain to %d", val); 299c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 300c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén sensor_settings[GAIN_IDX] = val; 301c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén 302c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1); 303c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén return err; 304c9304e43fb71ad790c5fc995de55e7c95abe5b4aErik Andrén} 3054763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 30668fdb7a5b52cb060f7824f9d6e98e105af36a474Erik Andrén 307f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrénstatic int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev, 308f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén __s32 *val) 309f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén{ 310f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén struct sd *sd = (struct sd *) gspca_dev; 311f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén s32 *sensor_settings = sd->sensor_priv; 312f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén 313f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; 314f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén return 0; 315f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén} 316f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén 317f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrénstatic int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, 318f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén __s32 val) 319f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén{ 320f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén int err; 321f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén u8 i2c_data; 322f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén struct sd *sd = (struct sd *) gspca_dev; 323f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén s32 *sensor_settings = sd->sensor_priv; 324f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén 325f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén PDEBUG(D_V4L2, "Set auto white balance to %d", val); 326f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén 327f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; 328f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 329f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén if (err < 0) 330f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén return err; 331f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén 332f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); 333f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 334f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén 335f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén return err; 336f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén} 337f1f59fe60e38c4c56b8acba9690cd08d86d2ac0eErik Andrén 338456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrénstatic int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) 339456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén{ 340456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén struct sd *sd = (struct sd *) gspca_dev; 341456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén s32 *sensor_settings = sd->sensor_priv; 342456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén 343456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén *val = sensor_settings[AUTO_GAIN_CTRL_IDX]; 344456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén PDEBUG(D_V4L2, "Read auto gain control %d", *val); 345456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén return 0; 346456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén} 347456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén 348456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrénstatic int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) 349456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén{ 350456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén int err; 351456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén u8 i2c_data; 352456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén struct sd *sd = (struct sd *) gspca_dev; 353456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén s32 *sensor_settings = sd->sensor_priv; 354456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén 355456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén PDEBUG(D_V4L2, "Set auto gain control to %d", val); 356456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén 357456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén sensor_settings[AUTO_GAIN_CTRL_IDX] = val; 358456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 359456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén if (err < 0) 360456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén return err; 361456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén 362456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); 363456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén 364456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 365456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén} 366456ebe4e92063b92d2672da272bfc7ac70bd8bddErik Andrén 3677c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrénstatic int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val) 3687c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén{ 3697c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén struct sd *sd = (struct sd *) gspca_dev; 3707c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén s32 *sensor_settings = sd->sensor_priv; 3717c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén 3727c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén *val = sensor_settings[AUTO_EXPOSURE_IDX]; 3737c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén PDEBUG(D_V4L2, "Read auto exposure control %d", *val); 3747c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén return 0; 3757c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén} 3767c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén 3777c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrénstatic int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, 3787c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén __s32 val) 3797c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén{ 3807c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén int err; 3817c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén u8 i2c_data; 3827c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén struct sd *sd = (struct sd *) gspca_dev; 3837c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén s32 *sensor_settings = sd->sensor_priv; 3847c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén 3857c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén PDEBUG(D_V4L2, "Set auto exposure control to %d", val); 3867c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén 3877c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén sensor_settings[AUTO_EXPOSURE_IDX] = val; 3887c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 3897c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén if (err < 0) 3907c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén return err; 3917c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén 3927c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0)); 3937c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén 3947c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 3957c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén} 3967c7ddf1638a45923ab053d1f7818c6d123148b4bErik Andrén 397a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrénstatic int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 398a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén{ 399a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén struct sd *sd = (struct sd *) gspca_dev; 400a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén s32 *sensor_settings = sd->sensor_priv; 401a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 402a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén *val = sensor_settings[HFLIP_IDX]; 403a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén PDEBUG(D_V4L2, "Read horizontal flip %d", *val); 404a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén return 0; 405a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén} 406a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 407a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrénstatic int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val) 408a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén{ 409a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén int err; 410a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén u8 i2c_data; 411a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén struct sd *sd = (struct sd *) gspca_dev; 412a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén s32 *sensor_settings = sd->sensor_priv; 413a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 414a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén PDEBUG(D_V4L2, "Set horizontal flip to %d", val); 415a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 416a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén sensor_settings[HFLIP_IDX] = val; 417a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 418a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén i2c_data = ((val & 0x01) << 5) | 419a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén (sensor_settings[VFLIP_IDX] << 4); 420a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 421a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); 422a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 423a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén return err; 424a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén} 425a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 426a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrénstatic int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) 427a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén{ 428a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén struct sd *sd = (struct sd *) gspca_dev; 429a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén s32 *sensor_settings = sd->sensor_priv; 430a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 431a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén *val = sensor_settings[VFLIP_IDX]; 432a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén PDEBUG(D_V4L2, "Read vertical flip %d", *val); 433a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 434a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén return 0; 435a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén} 436a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 437a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrénstatic int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val) 438a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén{ 439a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén int err; 440a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén u8 i2c_data; 441a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén struct sd *sd = (struct sd *) gspca_dev; 442a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén s32 *sensor_settings = sd->sensor_priv; 443a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 444a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén PDEBUG(D_V4L2, "Set vertical flip to %d", val); 445a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén sensor_settings[VFLIP_IDX] = val; 446a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 447a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); 448a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); 449a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén if (err < 0) 450a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén return err; 451a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 452a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén /* When vflip is toggled we need to readjust the bridge hsync/vsync */ 453a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén if (gspca_dev->streaming) 454a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén err = ov7660_start(sd); 455a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 456a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén return err; 457a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén} 458a66887d2ba2f829cbbc23a64e19a0b757b79c39eErik Andrén 4594763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrénstatic void ov7660_dump_registers(struct sd *sd) 4604763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén{ 4614763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén int address; 462bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("Dumping the ov7660 register state\n"); 4634763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén for (address = 0; address < 0xa9; address++) { 4644763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén u8 value; 4654763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén m5602_read_sensor(sd, address, &value, 1); 466bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("register 0x%x contains 0x%x\n", address, value); 4674763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén } 4684763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 469bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("ov7660 register state dump complete\n"); 4704763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 471bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("Probing for which registers that are read/write\n"); 4724763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén for (address = 0; address < 0xff; address++) { 4734763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén u8 old_value, ctrl_value; 4744763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén u8 test_value[2] = {0xff, 0xff}; 4754763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 4764763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén m5602_read_sensor(sd, address, &old_value, 1); 4774763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén m5602_write_sensor(sd, address, test_value, 1); 4784763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén m5602_read_sensor(sd, address, &ctrl_value, 1); 4794763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 4804763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén if (ctrl_value == test_value[0]) 481bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("register 0x%x is writeable\n", address); 4824763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén else 483bdfe91f411bd05392952efc1afdce8bda1923517Joe Perches pr_info("register 0x%x is read only\n", address); 4844763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén 4854763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén /* Restore original value */ 4864763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén m5602_write_sensor(sd, address, &old_value, 1); 4874763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén } 4884763fa84d9942137b011629be2e7547a23cdfbc6Erik Andrén} 489