162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * OV519 driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr> 662306a36Sopenharmony_ci * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This module is adapted from the ov51x-jpeg package, which itself 962306a36Sopenharmony_ci * was adapted from the ov511 driver. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Original copyright for the ov511 driver is: 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Copyright (c) 1999-2006 Mark W. McClelland 1462306a36Sopenharmony_ci * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach 1562306a36Sopenharmony_ci * Many improvements by Bret Wallach <bwallac1@san.rr.com> 1662306a36Sopenharmony_ci * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) 1762306a36Sopenharmony_ci * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> 1862306a36Sopenharmony_ci * Changes by Claudio Matsuoka <claudio@conectiva.com> 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * ov51x-jpeg original copyright is: 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Copyright (c) 2004-2007 Romain Beauxis <toots@rastageeks.org> 2362306a36Sopenharmony_ci * Support for OV7670 sensors was contributed by Sam Skipsey <aoanla@yahoo.com> 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define MODULE_NAME "ov519" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include <linux/input.h> 3162306a36Sopenharmony_ci#include "gspca.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* The jpeg_hdr is used by w996Xcf only */ 3462306a36Sopenharmony_ci/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */ 3562306a36Sopenharmony_ci#define CONEX_CAM 3662306a36Sopenharmony_ci#include "jpeg.h" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciMODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); 3962306a36Sopenharmony_ciMODULE_DESCRIPTION("OV519 USB Camera Driver"); 4062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* global parameters */ 4362306a36Sopenharmony_cistatic int frame_rate; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* Number of times to retry a failed I2C transaction. Increase this if you 4662306a36Sopenharmony_ci * are getting "Failed to read sensor ID..." */ 4762306a36Sopenharmony_cistatic int i2c_detect_tries = 10; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* ov519 device descriptor */ 5062306a36Sopenharmony_cistruct sd { 5162306a36Sopenharmony_ci struct gspca_dev gspca_dev; /* !! must be the first item */ 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci struct v4l2_ctrl *jpegqual; 5462306a36Sopenharmony_ci struct v4l2_ctrl *freq; 5562306a36Sopenharmony_ci struct { /* h/vflip control cluster */ 5662306a36Sopenharmony_ci struct v4l2_ctrl *hflip; 5762306a36Sopenharmony_ci struct v4l2_ctrl *vflip; 5862306a36Sopenharmony_ci }; 5962306a36Sopenharmony_ci struct { /* autobrightness/brightness control cluster */ 6062306a36Sopenharmony_ci struct v4l2_ctrl *autobright; 6162306a36Sopenharmony_ci struct v4l2_ctrl *brightness; 6262306a36Sopenharmony_ci }; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci u8 revision; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci u8 packet_nr; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci char bridge; 6962306a36Sopenharmony_ci#define BRIDGE_OV511 0 7062306a36Sopenharmony_ci#define BRIDGE_OV511PLUS 1 7162306a36Sopenharmony_ci#define BRIDGE_OV518 2 7262306a36Sopenharmony_ci#define BRIDGE_OV518PLUS 3 7362306a36Sopenharmony_ci#define BRIDGE_OV519 4 /* = ov530 */ 7462306a36Sopenharmony_ci#define BRIDGE_OVFX2 5 7562306a36Sopenharmony_ci#define BRIDGE_W9968CF 6 7662306a36Sopenharmony_ci#define BRIDGE_MASK 7 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci char invert_led; 7962306a36Sopenharmony_ci#define BRIDGE_INVERT_LED 8 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci char snapshot_pressed; 8262306a36Sopenharmony_ci char snapshot_needs_reset; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /* Determined by sensor type */ 8562306a36Sopenharmony_ci u8 sif; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define QUALITY_MIN 50 8862306a36Sopenharmony_ci#define QUALITY_MAX 70 8962306a36Sopenharmony_ci#define QUALITY_DEF 50 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci u8 stopped; /* Streaming is temporarily paused */ 9262306a36Sopenharmony_ci u8 first_frame; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci u8 frame_rate; /* current Framerate */ 9562306a36Sopenharmony_ci u8 clockdiv; /* clockdiv override */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci s8 sensor; /* Type of image sensor chip (SEN_*) */ 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci u8 sensor_addr; 10062306a36Sopenharmony_ci u16 sensor_width; 10162306a36Sopenharmony_ci u16 sensor_height; 10262306a36Sopenharmony_ci s16 sensor_reg_cache[256]; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci u8 jpeg_hdr[JPEG_HDR_SZ]; 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_cienum sensors { 10762306a36Sopenharmony_ci SEN_OV2610, 10862306a36Sopenharmony_ci SEN_OV2610AE, 10962306a36Sopenharmony_ci SEN_OV3610, 11062306a36Sopenharmony_ci SEN_OV6620, 11162306a36Sopenharmony_ci SEN_OV6630, 11262306a36Sopenharmony_ci SEN_OV66308AF, 11362306a36Sopenharmony_ci SEN_OV7610, 11462306a36Sopenharmony_ci SEN_OV7620, 11562306a36Sopenharmony_ci SEN_OV7620AE, 11662306a36Sopenharmony_ci SEN_OV7640, 11762306a36Sopenharmony_ci SEN_OV7648, 11862306a36Sopenharmony_ci SEN_OV7660, 11962306a36Sopenharmony_ci SEN_OV7670, 12062306a36Sopenharmony_ci SEN_OV76BE, 12162306a36Sopenharmony_ci SEN_OV8610, 12262306a36Sopenharmony_ci SEN_OV9600, 12362306a36Sopenharmony_ci}; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* Note this is a bit of a hack, but the w9968cf driver needs the code for all 12662306a36Sopenharmony_ci the ov sensors which is already present here. When we have the time we 12762306a36Sopenharmony_ci really should move the sensor drivers to v4l2 sub drivers. */ 12862306a36Sopenharmony_ci#include "w996Xcf.c" 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* table of the disabled controls */ 13162306a36Sopenharmony_cistruct ctrl_valid { 13262306a36Sopenharmony_ci unsigned int has_brightness:1; 13362306a36Sopenharmony_ci unsigned int has_contrast:1; 13462306a36Sopenharmony_ci unsigned int has_exposure:1; 13562306a36Sopenharmony_ci unsigned int has_autogain:1; 13662306a36Sopenharmony_ci unsigned int has_sat:1; 13762306a36Sopenharmony_ci unsigned int has_hvflip:1; 13862306a36Sopenharmony_ci unsigned int has_autobright:1; 13962306a36Sopenharmony_ci unsigned int has_freq:1; 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic const struct ctrl_valid valid_controls[] = { 14362306a36Sopenharmony_ci [SEN_OV2610] = { 14462306a36Sopenharmony_ci .has_exposure = 1, 14562306a36Sopenharmony_ci .has_autogain = 1, 14662306a36Sopenharmony_ci }, 14762306a36Sopenharmony_ci [SEN_OV2610AE] = { 14862306a36Sopenharmony_ci .has_exposure = 1, 14962306a36Sopenharmony_ci .has_autogain = 1, 15062306a36Sopenharmony_ci }, 15162306a36Sopenharmony_ci [SEN_OV3610] = { 15262306a36Sopenharmony_ci /* No controls */ 15362306a36Sopenharmony_ci }, 15462306a36Sopenharmony_ci [SEN_OV6620] = { 15562306a36Sopenharmony_ci .has_brightness = 1, 15662306a36Sopenharmony_ci .has_contrast = 1, 15762306a36Sopenharmony_ci .has_sat = 1, 15862306a36Sopenharmony_ci .has_autobright = 1, 15962306a36Sopenharmony_ci .has_freq = 1, 16062306a36Sopenharmony_ci }, 16162306a36Sopenharmony_ci [SEN_OV6630] = { 16262306a36Sopenharmony_ci .has_brightness = 1, 16362306a36Sopenharmony_ci .has_contrast = 1, 16462306a36Sopenharmony_ci .has_sat = 1, 16562306a36Sopenharmony_ci .has_autobright = 1, 16662306a36Sopenharmony_ci .has_freq = 1, 16762306a36Sopenharmony_ci }, 16862306a36Sopenharmony_ci [SEN_OV66308AF] = { 16962306a36Sopenharmony_ci .has_brightness = 1, 17062306a36Sopenharmony_ci .has_contrast = 1, 17162306a36Sopenharmony_ci .has_sat = 1, 17262306a36Sopenharmony_ci .has_autobright = 1, 17362306a36Sopenharmony_ci .has_freq = 1, 17462306a36Sopenharmony_ci }, 17562306a36Sopenharmony_ci [SEN_OV7610] = { 17662306a36Sopenharmony_ci .has_brightness = 1, 17762306a36Sopenharmony_ci .has_contrast = 1, 17862306a36Sopenharmony_ci .has_sat = 1, 17962306a36Sopenharmony_ci .has_autobright = 1, 18062306a36Sopenharmony_ci .has_freq = 1, 18162306a36Sopenharmony_ci }, 18262306a36Sopenharmony_ci [SEN_OV7620] = { 18362306a36Sopenharmony_ci .has_brightness = 1, 18462306a36Sopenharmony_ci .has_contrast = 1, 18562306a36Sopenharmony_ci .has_sat = 1, 18662306a36Sopenharmony_ci .has_autobright = 1, 18762306a36Sopenharmony_ci .has_freq = 1, 18862306a36Sopenharmony_ci }, 18962306a36Sopenharmony_ci [SEN_OV7620AE] = { 19062306a36Sopenharmony_ci .has_brightness = 1, 19162306a36Sopenharmony_ci .has_contrast = 1, 19262306a36Sopenharmony_ci .has_sat = 1, 19362306a36Sopenharmony_ci .has_autobright = 1, 19462306a36Sopenharmony_ci .has_freq = 1, 19562306a36Sopenharmony_ci }, 19662306a36Sopenharmony_ci [SEN_OV7640] = { 19762306a36Sopenharmony_ci .has_brightness = 1, 19862306a36Sopenharmony_ci .has_sat = 1, 19962306a36Sopenharmony_ci .has_freq = 1, 20062306a36Sopenharmony_ci }, 20162306a36Sopenharmony_ci [SEN_OV7648] = { 20262306a36Sopenharmony_ci .has_brightness = 1, 20362306a36Sopenharmony_ci .has_sat = 1, 20462306a36Sopenharmony_ci .has_freq = 1, 20562306a36Sopenharmony_ci }, 20662306a36Sopenharmony_ci [SEN_OV7660] = { 20762306a36Sopenharmony_ci .has_brightness = 1, 20862306a36Sopenharmony_ci .has_contrast = 1, 20962306a36Sopenharmony_ci .has_sat = 1, 21062306a36Sopenharmony_ci .has_hvflip = 1, 21162306a36Sopenharmony_ci .has_freq = 1, 21262306a36Sopenharmony_ci }, 21362306a36Sopenharmony_ci [SEN_OV7670] = { 21462306a36Sopenharmony_ci .has_brightness = 1, 21562306a36Sopenharmony_ci .has_contrast = 1, 21662306a36Sopenharmony_ci .has_hvflip = 1, 21762306a36Sopenharmony_ci .has_freq = 1, 21862306a36Sopenharmony_ci }, 21962306a36Sopenharmony_ci [SEN_OV76BE] = { 22062306a36Sopenharmony_ci .has_brightness = 1, 22162306a36Sopenharmony_ci .has_contrast = 1, 22262306a36Sopenharmony_ci .has_sat = 1, 22362306a36Sopenharmony_ci .has_autobright = 1, 22462306a36Sopenharmony_ci .has_freq = 1, 22562306a36Sopenharmony_ci }, 22662306a36Sopenharmony_ci [SEN_OV8610] = { 22762306a36Sopenharmony_ci .has_brightness = 1, 22862306a36Sopenharmony_ci .has_contrast = 1, 22962306a36Sopenharmony_ci .has_sat = 1, 23062306a36Sopenharmony_ci .has_autobright = 1, 23162306a36Sopenharmony_ci }, 23262306a36Sopenharmony_ci [SEN_OV9600] = { 23362306a36Sopenharmony_ci .has_exposure = 1, 23462306a36Sopenharmony_ci .has_autogain = 1, 23562306a36Sopenharmony_ci }, 23662306a36Sopenharmony_ci}; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic const struct v4l2_pix_format ov519_vga_mode[] = { 23962306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 24062306a36Sopenharmony_ci .bytesperline = 320, 24162306a36Sopenharmony_ci .sizeimage = 320 * 240 * 3 / 8 + 590, 24262306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 24362306a36Sopenharmony_ci .priv = 1}, 24462306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 24562306a36Sopenharmony_ci .bytesperline = 640, 24662306a36Sopenharmony_ci .sizeimage = 640 * 480 * 3 / 8 + 590, 24762306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 24862306a36Sopenharmony_ci .priv = 0}, 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_cistatic const struct v4l2_pix_format ov519_sif_mode[] = { 25162306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 25262306a36Sopenharmony_ci .bytesperline = 160, 25362306a36Sopenharmony_ci .sizeimage = 160 * 120 * 3 / 8 + 590, 25462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 25562306a36Sopenharmony_ci .priv = 3}, 25662306a36Sopenharmony_ci {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 25762306a36Sopenharmony_ci .bytesperline = 176, 25862306a36Sopenharmony_ci .sizeimage = 176 * 144 * 3 / 8 + 590, 25962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 26062306a36Sopenharmony_ci .priv = 1}, 26162306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 26262306a36Sopenharmony_ci .bytesperline = 320, 26362306a36Sopenharmony_ci .sizeimage = 320 * 240 * 3 / 8 + 590, 26462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 26562306a36Sopenharmony_ci .priv = 2}, 26662306a36Sopenharmony_ci {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 26762306a36Sopenharmony_ci .bytesperline = 352, 26862306a36Sopenharmony_ci .sizeimage = 352 * 288 * 3 / 8 + 590, 26962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 27062306a36Sopenharmony_ci .priv = 0}, 27162306a36Sopenharmony_ci}; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci/* Note some of the sizeimage values for the ov511 / ov518 may seem 27462306a36Sopenharmony_ci larger then necessary, however they need to be this big as the ov511 / 27562306a36Sopenharmony_ci ov518 always fills the entire isoc frame, using 0 padding bytes when 27662306a36Sopenharmony_ci it doesn't have any data. So with low framerates the amount of data 27762306a36Sopenharmony_ci transferred can become quite large (libv4l will remove all the 0 padding 27862306a36Sopenharmony_ci in userspace). */ 27962306a36Sopenharmony_cistatic const struct v4l2_pix_format ov518_vga_mode[] = { 28062306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 28162306a36Sopenharmony_ci .bytesperline = 320, 28262306a36Sopenharmony_ci .sizeimage = 320 * 240 * 3, 28362306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 28462306a36Sopenharmony_ci .priv = 1}, 28562306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 28662306a36Sopenharmony_ci .bytesperline = 640, 28762306a36Sopenharmony_ci .sizeimage = 640 * 480 * 2, 28862306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 28962306a36Sopenharmony_ci .priv = 0}, 29062306a36Sopenharmony_ci}; 29162306a36Sopenharmony_cistatic const struct v4l2_pix_format ov518_sif_mode[] = { 29262306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 29362306a36Sopenharmony_ci .bytesperline = 160, 29462306a36Sopenharmony_ci .sizeimage = 70000, 29562306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 29662306a36Sopenharmony_ci .priv = 3}, 29762306a36Sopenharmony_ci {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 29862306a36Sopenharmony_ci .bytesperline = 176, 29962306a36Sopenharmony_ci .sizeimage = 70000, 30062306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 30162306a36Sopenharmony_ci .priv = 1}, 30262306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 30362306a36Sopenharmony_ci .bytesperline = 320, 30462306a36Sopenharmony_ci .sizeimage = 320 * 240 * 3, 30562306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 30662306a36Sopenharmony_ci .priv = 2}, 30762306a36Sopenharmony_ci {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 30862306a36Sopenharmony_ci .bytesperline = 352, 30962306a36Sopenharmony_ci .sizeimage = 352 * 288 * 3, 31062306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 31162306a36Sopenharmony_ci .priv = 0}, 31262306a36Sopenharmony_ci}; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic const struct v4l2_pix_format ov511_vga_mode[] = { 31562306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 31662306a36Sopenharmony_ci .bytesperline = 320, 31762306a36Sopenharmony_ci .sizeimage = 320 * 240 * 3, 31862306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 31962306a36Sopenharmony_ci .priv = 1}, 32062306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 32162306a36Sopenharmony_ci .bytesperline = 640, 32262306a36Sopenharmony_ci .sizeimage = 640 * 480 * 2, 32362306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 32462306a36Sopenharmony_ci .priv = 0}, 32562306a36Sopenharmony_ci}; 32662306a36Sopenharmony_cistatic const struct v4l2_pix_format ov511_sif_mode[] = { 32762306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 32862306a36Sopenharmony_ci .bytesperline = 160, 32962306a36Sopenharmony_ci .sizeimage = 70000, 33062306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 33162306a36Sopenharmony_ci .priv = 3}, 33262306a36Sopenharmony_ci {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 33362306a36Sopenharmony_ci .bytesperline = 176, 33462306a36Sopenharmony_ci .sizeimage = 70000, 33562306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 33662306a36Sopenharmony_ci .priv = 1}, 33762306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 33862306a36Sopenharmony_ci .bytesperline = 320, 33962306a36Sopenharmony_ci .sizeimage = 320 * 240 * 3, 34062306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 34162306a36Sopenharmony_ci .priv = 2}, 34262306a36Sopenharmony_ci {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 34362306a36Sopenharmony_ci .bytesperline = 352, 34462306a36Sopenharmony_ci .sizeimage = 352 * 288 * 3, 34562306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 34662306a36Sopenharmony_ci .priv = 0}, 34762306a36Sopenharmony_ci}; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov2610_mode[] = { 35062306a36Sopenharmony_ci {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 35162306a36Sopenharmony_ci .bytesperline = 800, 35262306a36Sopenharmony_ci .sizeimage = 800 * 600, 35362306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 35462306a36Sopenharmony_ci .priv = 1}, 35562306a36Sopenharmony_ci {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 35662306a36Sopenharmony_ci .bytesperline = 1600, 35762306a36Sopenharmony_ci .sizeimage = 1600 * 1200, 35862306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB}, 35962306a36Sopenharmony_ci}; 36062306a36Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov3610_mode[] = { 36162306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 36262306a36Sopenharmony_ci .bytesperline = 640, 36362306a36Sopenharmony_ci .sizeimage = 640 * 480, 36462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 36562306a36Sopenharmony_ci .priv = 1}, 36662306a36Sopenharmony_ci {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 36762306a36Sopenharmony_ci .bytesperline = 800, 36862306a36Sopenharmony_ci .sizeimage = 800 * 600, 36962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 37062306a36Sopenharmony_ci .priv = 1}, 37162306a36Sopenharmony_ci {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 37262306a36Sopenharmony_ci .bytesperline = 1024, 37362306a36Sopenharmony_ci .sizeimage = 1024 * 768, 37462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 37562306a36Sopenharmony_ci .priv = 1}, 37662306a36Sopenharmony_ci {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 37762306a36Sopenharmony_ci .bytesperline = 1600, 37862306a36Sopenharmony_ci .sizeimage = 1600 * 1200, 37962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 38062306a36Sopenharmony_ci .priv = 0}, 38162306a36Sopenharmony_ci {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 38262306a36Sopenharmony_ci .bytesperline = 2048, 38362306a36Sopenharmony_ci .sizeimage = 2048 * 1536, 38462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 38562306a36Sopenharmony_ci .priv = 0}, 38662306a36Sopenharmony_ci}; 38762306a36Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov9600_mode[] = { 38862306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 38962306a36Sopenharmony_ci .bytesperline = 640, 39062306a36Sopenharmony_ci .sizeimage = 640 * 480, 39162306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 39262306a36Sopenharmony_ci .priv = 1}, 39362306a36Sopenharmony_ci {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 39462306a36Sopenharmony_ci .bytesperline = 1280, 39562306a36Sopenharmony_ci .sizeimage = 1280 * 1024, 39662306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB}, 39762306a36Sopenharmony_ci}; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci/* Registers common to OV511 / OV518 */ 40062306a36Sopenharmony_ci#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ 40162306a36Sopenharmony_ci#define R51x_SYS_RESET 0x50 40262306a36Sopenharmony_ci /* Reset type flags */ 40362306a36Sopenharmony_ci #define OV511_RESET_OMNICE 0x08 40462306a36Sopenharmony_ci#define R51x_SYS_INIT 0x53 40562306a36Sopenharmony_ci#define R51x_SYS_SNAP 0x52 40662306a36Sopenharmony_ci#define R51x_SYS_CUST_ID 0x5f 40762306a36Sopenharmony_ci#define R51x_COMP_LUT_BEGIN 0x80 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci/* OV511 Camera interface register numbers */ 41062306a36Sopenharmony_ci#define R511_CAM_DELAY 0x10 41162306a36Sopenharmony_ci#define R511_CAM_EDGE 0x11 41262306a36Sopenharmony_ci#define R511_CAM_PXCNT 0x12 41362306a36Sopenharmony_ci#define R511_CAM_LNCNT 0x13 41462306a36Sopenharmony_ci#define R511_CAM_PXDIV 0x14 41562306a36Sopenharmony_ci#define R511_CAM_LNDIV 0x15 41662306a36Sopenharmony_ci#define R511_CAM_UV_EN 0x16 41762306a36Sopenharmony_ci#define R511_CAM_LINE_MODE 0x17 41862306a36Sopenharmony_ci#define R511_CAM_OPTS 0x18 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci#define R511_SNAP_FRAME 0x19 42162306a36Sopenharmony_ci#define R511_SNAP_PXCNT 0x1a 42262306a36Sopenharmony_ci#define R511_SNAP_LNCNT 0x1b 42362306a36Sopenharmony_ci#define R511_SNAP_PXDIV 0x1c 42462306a36Sopenharmony_ci#define R511_SNAP_LNDIV 0x1d 42562306a36Sopenharmony_ci#define R511_SNAP_UV_EN 0x1e 42662306a36Sopenharmony_ci#define R511_SNAP_OPTS 0x1f 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci#define R511_DRAM_FLOW_CTL 0x20 42962306a36Sopenharmony_ci#define R511_FIFO_OPTS 0x31 43062306a36Sopenharmony_ci#define R511_I2C_CTL 0x40 43162306a36Sopenharmony_ci#define R511_SYS_LED_CTL 0x55 /* OV511+ only */ 43262306a36Sopenharmony_ci#define R511_COMP_EN 0x78 43362306a36Sopenharmony_ci#define R511_COMP_LUT_EN 0x79 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci/* OV518 Camera interface register numbers */ 43662306a36Sopenharmony_ci#define R518_GPIO_OUT 0x56 /* OV518(+) only */ 43762306a36Sopenharmony_ci#define R518_GPIO_CTL 0x57 /* OV518(+) only */ 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci/* OV519 Camera interface register numbers */ 44062306a36Sopenharmony_ci#define OV519_R10_H_SIZE 0x10 44162306a36Sopenharmony_ci#define OV519_R11_V_SIZE 0x11 44262306a36Sopenharmony_ci#define OV519_R12_X_OFFSETL 0x12 44362306a36Sopenharmony_ci#define OV519_R13_X_OFFSETH 0x13 44462306a36Sopenharmony_ci#define OV519_R14_Y_OFFSETL 0x14 44562306a36Sopenharmony_ci#define OV519_R15_Y_OFFSETH 0x15 44662306a36Sopenharmony_ci#define OV519_R16_DIVIDER 0x16 44762306a36Sopenharmony_ci#define OV519_R20_DFR 0x20 44862306a36Sopenharmony_ci#define OV519_R25_FORMAT 0x25 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci/* OV519 System Controller register numbers */ 45162306a36Sopenharmony_ci#define OV519_R51_RESET1 0x51 45262306a36Sopenharmony_ci#define OV519_R54_EN_CLK1 0x54 45362306a36Sopenharmony_ci#define OV519_R57_SNAPSHOT 0x57 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci#define OV519_GPIO_DATA_OUT0 0x71 45662306a36Sopenharmony_ci#define OV519_GPIO_IO_CTRL0 0x72 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci/*#define OV511_ENDPOINT_ADDRESS 1 * Isoc endpoint number */ 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci/* 46162306a36Sopenharmony_ci * The FX2 chip does not give us a zero length read at end of frame. 46262306a36Sopenharmony_ci * It does, however, give a short read at the end of a frame, if 46362306a36Sopenharmony_ci * necessary, rather than run two frames together. 46462306a36Sopenharmony_ci * 46562306a36Sopenharmony_ci * By choosing the right bulk transfer size, we are guaranteed to always 46662306a36Sopenharmony_ci * get a short read for the last read of each frame. Frame sizes are 46762306a36Sopenharmony_ci * always a composite number (width * height, or a multiple) so if we 46862306a36Sopenharmony_ci * choose a prime number, we are guaranteed that the last read of a 46962306a36Sopenharmony_ci * frame will be short. 47062306a36Sopenharmony_ci * 47162306a36Sopenharmony_ci * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB, 47262306a36Sopenharmony_ci * otherwise EOVERFLOW "babbling" errors occur. I have not been able 47362306a36Sopenharmony_ci * to figure out why. [PMiller] 47462306a36Sopenharmony_ci * 47562306a36Sopenharmony_ci * The constant (13 * 4096) is the largest "prime enough" number less than 64KB. 47662306a36Sopenharmony_ci * 47762306a36Sopenharmony_ci * It isn't enough to know the number of bytes per frame, in case we 47862306a36Sopenharmony_ci * have data dropouts or buffer overruns (even though the FX2 double 47962306a36Sopenharmony_ci * buffers, there are some pretty strict real time constraints for 48062306a36Sopenharmony_ci * isochronous transfer for larger frame sizes). 48162306a36Sopenharmony_ci */ 48262306a36Sopenharmony_ci/*jfm: this value does not work for 800x600 - see isoc_init */ 48362306a36Sopenharmony_ci#define OVFX2_BULK_SIZE (13 * 4096) 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci/* I2C registers */ 48662306a36Sopenharmony_ci#define R51x_I2C_W_SID 0x41 48762306a36Sopenharmony_ci#define R51x_I2C_SADDR_3 0x42 48862306a36Sopenharmony_ci#define R51x_I2C_SADDR_2 0x43 48962306a36Sopenharmony_ci#define R51x_I2C_R_SID 0x44 49062306a36Sopenharmony_ci#define R51x_I2C_DATA 0x45 49162306a36Sopenharmony_ci#define R518_I2C_CTL 0x47 /* OV518(+) only */ 49262306a36Sopenharmony_ci#define OVFX2_I2C_ADDR 0x00 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/* I2C ADDRESSES */ 49562306a36Sopenharmony_ci#define OV7xx0_SID 0x42 49662306a36Sopenharmony_ci#define OV_HIRES_SID 0x60 /* OV9xxx / OV2xxx / OV3xxx */ 49762306a36Sopenharmony_ci#define OV8xx0_SID 0xa0 49862306a36Sopenharmony_ci#define OV6xx0_SID 0xc0 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci/* OV7610 registers */ 50162306a36Sopenharmony_ci#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ 50262306a36Sopenharmony_ci#define OV7610_REG_BLUE 0x01 /* blue channel balance */ 50362306a36Sopenharmony_ci#define OV7610_REG_RED 0x02 /* red channel balance */ 50462306a36Sopenharmony_ci#define OV7610_REG_SAT 0x03 /* saturation */ 50562306a36Sopenharmony_ci#define OV8610_REG_HUE 0x04 /* 04 reserved */ 50662306a36Sopenharmony_ci#define OV7610_REG_CNT 0x05 /* Y contrast */ 50762306a36Sopenharmony_ci#define OV7610_REG_BRT 0x06 /* Y brightness */ 50862306a36Sopenharmony_ci#define OV7610_REG_COM_C 0x14 /* misc common regs */ 50962306a36Sopenharmony_ci#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */ 51062306a36Sopenharmony_ci#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */ 51162306a36Sopenharmony_ci#define OV7610_REG_COM_I 0x29 /* misc settings */ 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci/* OV7660 and OV7670 registers */ 51462306a36Sopenharmony_ci#define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ 51562306a36Sopenharmony_ci#define OV7670_R01_BLUE 0x01 /* blue gain */ 51662306a36Sopenharmony_ci#define OV7670_R02_RED 0x02 /* red gain */ 51762306a36Sopenharmony_ci#define OV7670_R03_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ 51862306a36Sopenharmony_ci#define OV7670_R04_COM1 0x04 /* Control 1 */ 51962306a36Sopenharmony_ci/*#define OV7670_R07_AECHH 0x07 * AEC MS 5 bits */ 52062306a36Sopenharmony_ci#define OV7670_R0C_COM3 0x0c /* Control 3 */ 52162306a36Sopenharmony_ci#define OV7670_R0D_COM4 0x0d /* Control 4 */ 52262306a36Sopenharmony_ci#define OV7670_R0E_COM5 0x0e /* All "reserved" */ 52362306a36Sopenharmony_ci#define OV7670_R0F_COM6 0x0f /* Control 6 */ 52462306a36Sopenharmony_ci#define OV7670_R10_AECH 0x10 /* More bits of AEC value */ 52562306a36Sopenharmony_ci#define OV7670_R11_CLKRC 0x11 /* Clock control */ 52662306a36Sopenharmony_ci#define OV7670_R12_COM7 0x12 /* Control 7 */ 52762306a36Sopenharmony_ci#define OV7670_COM7_FMT_VGA 0x00 52862306a36Sopenharmony_ci/*#define OV7670_COM7_YUV 0x00 * YUV */ 52962306a36Sopenharmony_ci#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ 53062306a36Sopenharmony_ci#define OV7670_COM7_FMT_MASK 0x38 53162306a36Sopenharmony_ci#define OV7670_COM7_RESET 0x80 /* Register reset */ 53262306a36Sopenharmony_ci#define OV7670_R13_COM8 0x13 /* Control 8 */ 53362306a36Sopenharmony_ci#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ 53462306a36Sopenharmony_ci#define OV7670_COM8_AWB 0x02 /* White balance enable */ 53562306a36Sopenharmony_ci#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ 53662306a36Sopenharmony_ci#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ 53762306a36Sopenharmony_ci#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ 53862306a36Sopenharmony_ci#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ 53962306a36Sopenharmony_ci#define OV7670_R14_COM9 0x14 /* Control 9 - gain ceiling */ 54062306a36Sopenharmony_ci#define OV7670_R15_COM10 0x15 /* Control 10 */ 54162306a36Sopenharmony_ci#define OV7670_R17_HSTART 0x17 /* Horiz start high bits */ 54262306a36Sopenharmony_ci#define OV7670_R18_HSTOP 0x18 /* Horiz stop high bits */ 54362306a36Sopenharmony_ci#define OV7670_R19_VSTART 0x19 /* Vert start high bits */ 54462306a36Sopenharmony_ci#define OV7670_R1A_VSTOP 0x1a /* Vert stop high bits */ 54562306a36Sopenharmony_ci#define OV7670_R1E_MVFP 0x1e /* Mirror / vflip */ 54662306a36Sopenharmony_ci#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ 54762306a36Sopenharmony_ci#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ 54862306a36Sopenharmony_ci#define OV7670_R24_AEW 0x24 /* AGC upper limit */ 54962306a36Sopenharmony_ci#define OV7670_R25_AEB 0x25 /* AGC lower limit */ 55062306a36Sopenharmony_ci#define OV7670_R26_VPT 0x26 /* AGC/AEC fast mode op region */ 55162306a36Sopenharmony_ci#define OV7670_R32_HREF 0x32 /* HREF pieces */ 55262306a36Sopenharmony_ci#define OV7670_R3A_TSLB 0x3a /* lots of stuff */ 55362306a36Sopenharmony_ci#define OV7670_R3B_COM11 0x3b /* Control 11 */ 55462306a36Sopenharmony_ci#define OV7670_COM11_EXP 0x02 55562306a36Sopenharmony_ci#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ 55662306a36Sopenharmony_ci#define OV7670_R3C_COM12 0x3c /* Control 12 */ 55762306a36Sopenharmony_ci#define OV7670_R3D_COM13 0x3d /* Control 13 */ 55862306a36Sopenharmony_ci#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ 55962306a36Sopenharmony_ci#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ 56062306a36Sopenharmony_ci#define OV7670_R3E_COM14 0x3e /* Control 14 */ 56162306a36Sopenharmony_ci#define OV7670_R3F_EDGE 0x3f /* Edge enhancement factor */ 56262306a36Sopenharmony_ci#define OV7670_R40_COM15 0x40 /* Control 15 */ 56362306a36Sopenharmony_ci/*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ 56462306a36Sopenharmony_ci#define OV7670_R41_COM16 0x41 /* Control 16 */ 56562306a36Sopenharmony_ci#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ 56662306a36Sopenharmony_ci/* end of ov7660 common registers */ 56762306a36Sopenharmony_ci#define OV7670_R55_BRIGHT 0x55 /* Brightness */ 56862306a36Sopenharmony_ci#define OV7670_R56_CONTRAS 0x56 /* Contrast control */ 56962306a36Sopenharmony_ci#define OV7670_R69_GFIX 0x69 /* Fix gain control */ 57062306a36Sopenharmony_ci/*#define OV7670_R8C_RGB444 0x8c * RGB 444 control */ 57162306a36Sopenharmony_ci#define OV7670_R9F_HAECC1 0x9f /* Hist AEC/AGC control 1 */ 57262306a36Sopenharmony_ci#define OV7670_RA0_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ 57362306a36Sopenharmony_ci#define OV7670_RA5_BD50MAX 0xa5 /* 50hz banding step limit */ 57462306a36Sopenharmony_ci#define OV7670_RA6_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ 57562306a36Sopenharmony_ci#define OV7670_RA7_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ 57662306a36Sopenharmony_ci#define OV7670_RA8_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ 57762306a36Sopenharmony_ci#define OV7670_RA9_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ 57862306a36Sopenharmony_ci#define OV7670_RAA_HAECC7 0xaa /* Hist AEC/AGC control 7 */ 57962306a36Sopenharmony_ci#define OV7670_RAB_BD60MAX 0xab /* 60hz banding step limit */ 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_cistruct ov_regvals { 58262306a36Sopenharmony_ci u8 reg; 58362306a36Sopenharmony_ci u8 val; 58462306a36Sopenharmony_ci}; 58562306a36Sopenharmony_cistruct ov_i2c_regvals { 58662306a36Sopenharmony_ci u8 reg; 58762306a36Sopenharmony_ci u8 val; 58862306a36Sopenharmony_ci}; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci/* Settings for OV2610 camera chip */ 59162306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_2610[] = { 59262306a36Sopenharmony_ci { 0x12, 0x80 }, /* reset */ 59362306a36Sopenharmony_ci}; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_2610ae[] = { 59662306a36Sopenharmony_ci {0x12, 0x80}, /* reset */ 59762306a36Sopenharmony_ci {0x13, 0xcd}, 59862306a36Sopenharmony_ci {0x09, 0x01}, 59962306a36Sopenharmony_ci {0x0d, 0x00}, 60062306a36Sopenharmony_ci {0x11, 0x80}, 60162306a36Sopenharmony_ci {0x12, 0x20}, /* 1600x1200 */ 60262306a36Sopenharmony_ci {0x33, 0x0c}, 60362306a36Sopenharmony_ci {0x35, 0x90}, 60462306a36Sopenharmony_ci {0x36, 0x37}, 60562306a36Sopenharmony_ci/* ms-win traces */ 60662306a36Sopenharmony_ci {0x11, 0x83}, /* clock / 3 ? */ 60762306a36Sopenharmony_ci {0x2d, 0x00}, /* 60 Hz filter */ 60862306a36Sopenharmony_ci {0x24, 0xb0}, /* normal colors */ 60962306a36Sopenharmony_ci {0x25, 0x90}, 61062306a36Sopenharmony_ci {0x10, 0x43}, 61162306a36Sopenharmony_ci}; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_3620b[] = { 61462306a36Sopenharmony_ci /* 61562306a36Sopenharmony_ci * From the datasheet: "Note that after writing to register COMH 61662306a36Sopenharmony_ci * (0x12) to change the sensor mode, registers related to the 61762306a36Sopenharmony_ci * sensor's cropping window will be reset back to their default 61862306a36Sopenharmony_ci * values." 61962306a36Sopenharmony_ci * 62062306a36Sopenharmony_ci * "wait 4096 external clock ... to make sure the sensor is 62162306a36Sopenharmony_ci * stable and ready to access registers" i.e. 160us at 24MHz 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_ci { 0x12, 0x80 }, /* COMH reset */ 62462306a36Sopenharmony_ci { 0x12, 0x00 }, /* QXGA, master */ 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci /* 62762306a36Sopenharmony_ci * 11 CLKRC "Clock Rate Control" 62862306a36Sopenharmony_ci * [7] internal frequency doublers: on 62962306a36Sopenharmony_ci * [6] video port mode: master 63062306a36Sopenharmony_ci * [5:0] clock divider: 1 63162306a36Sopenharmony_ci */ 63262306a36Sopenharmony_ci { 0x11, 0x80 }, 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* 63562306a36Sopenharmony_ci * 13 COMI "Common Control I" 63662306a36Sopenharmony_ci * = 192 (0xC0) 11000000 63762306a36Sopenharmony_ci * COMI[7] "AEC speed selection" 63862306a36Sopenharmony_ci * = 1 (0x01) 1....... "Faster AEC correction" 63962306a36Sopenharmony_ci * COMI[6] "AEC speed step selection" 64062306a36Sopenharmony_ci * = 1 (0x01) .1...... "Big steps, fast" 64162306a36Sopenharmony_ci * COMI[5] "Banding filter on off" 64262306a36Sopenharmony_ci * = 0 (0x00) ..0..... "Off" 64362306a36Sopenharmony_ci * COMI[4] "Banding filter option" 64462306a36Sopenharmony_ci * = 0 (0x00) ...0.... "Main clock is 48 MHz and 64562306a36Sopenharmony_ci * the PLL is ON" 64662306a36Sopenharmony_ci * COMI[3] "Reserved" 64762306a36Sopenharmony_ci * = 0 (0x00) ....0... 64862306a36Sopenharmony_ci * COMI[2] "AGC auto manual control selection" 64962306a36Sopenharmony_ci * = 0 (0x00) .....0.. "Manual" 65062306a36Sopenharmony_ci * COMI[1] "AWB auto manual control selection" 65162306a36Sopenharmony_ci * = 0 (0x00) ......0. "Manual" 65262306a36Sopenharmony_ci * COMI[0] "Exposure control" 65362306a36Sopenharmony_ci * = 0 (0x00) .......0 "Manual" 65462306a36Sopenharmony_ci */ 65562306a36Sopenharmony_ci { 0x13, 0xc0 }, 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* 65862306a36Sopenharmony_ci * 09 COMC "Common Control C" 65962306a36Sopenharmony_ci * = 8 (0x08) 00001000 66062306a36Sopenharmony_ci * COMC[7:5] "Reserved" 66162306a36Sopenharmony_ci * = 0 (0x00) 000..... 66262306a36Sopenharmony_ci * COMC[4] "Sleep Mode Enable" 66362306a36Sopenharmony_ci * = 0 (0x00) ...0.... "Normal mode" 66462306a36Sopenharmony_ci * COMC[3:2] "Sensor sampling reset timing selection" 66562306a36Sopenharmony_ci * = 2 (0x02) ....10.. "Longer reset time" 66662306a36Sopenharmony_ci * COMC[1:0] "Output drive current select" 66762306a36Sopenharmony_ci * = 0 (0x00) ......00 "Weakest" 66862306a36Sopenharmony_ci */ 66962306a36Sopenharmony_ci { 0x09, 0x08 }, 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci /* 67262306a36Sopenharmony_ci * 0C COMD "Common Control D" 67362306a36Sopenharmony_ci * = 8 (0x08) 00001000 67462306a36Sopenharmony_ci * COMD[7] "Reserved" 67562306a36Sopenharmony_ci * = 0 (0x00) 0....... 67662306a36Sopenharmony_ci * COMD[6] "Swap MSB and LSB at the output port" 67762306a36Sopenharmony_ci * = 0 (0x00) .0...... "False" 67862306a36Sopenharmony_ci * COMD[5:3] "Reserved" 67962306a36Sopenharmony_ci * = 1 (0x01) ..001... 68062306a36Sopenharmony_ci * COMD[2] "Output Average On Off" 68162306a36Sopenharmony_ci * = 0 (0x00) .....0.. "Output Normal" 68262306a36Sopenharmony_ci * COMD[1] "Sensor precharge voltage selection" 68362306a36Sopenharmony_ci * = 0 (0x00) ......0. "Selects internal 68462306a36Sopenharmony_ci * reference precharge 68562306a36Sopenharmony_ci * voltage" 68662306a36Sopenharmony_ci * COMD[0] "Snapshot option" 68762306a36Sopenharmony_ci * = 0 (0x00) .......0 "Enable live video output 68862306a36Sopenharmony_ci * after snapshot sequence" 68962306a36Sopenharmony_ci */ 69062306a36Sopenharmony_ci { 0x0c, 0x08 }, 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci /* 69362306a36Sopenharmony_ci * 0D COME "Common Control E" 69462306a36Sopenharmony_ci * = 161 (0xA1) 10100001 69562306a36Sopenharmony_ci * COME[7] "Output average option" 69662306a36Sopenharmony_ci * = 1 (0x01) 1....... "Output average of 4 pixels" 69762306a36Sopenharmony_ci * COME[6] "Anti-blooming control" 69862306a36Sopenharmony_ci * = 0 (0x00) .0...... "Off" 69962306a36Sopenharmony_ci * COME[5:3] "Reserved" 70062306a36Sopenharmony_ci * = 4 (0x04) ..100... 70162306a36Sopenharmony_ci * COME[2] "Clock output power down pin status" 70262306a36Sopenharmony_ci * = 0 (0x00) .....0.. "Tri-state data output pin 70362306a36Sopenharmony_ci * on power down" 70462306a36Sopenharmony_ci * COME[1] "Data output pin status selection at power down" 70562306a36Sopenharmony_ci * = 0 (0x00) ......0. "Tri-state VSYNC, PCLK, 70662306a36Sopenharmony_ci * HREF, and CHSYNC pins on 70762306a36Sopenharmony_ci * power down" 70862306a36Sopenharmony_ci * COME[0] "Auto zero circuit select" 70962306a36Sopenharmony_ci * = 1 (0x01) .......1 "On" 71062306a36Sopenharmony_ci */ 71162306a36Sopenharmony_ci { 0x0d, 0xa1 }, 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci /* 71462306a36Sopenharmony_ci * 0E COMF "Common Control F" 71562306a36Sopenharmony_ci * = 112 (0x70) 01110000 71662306a36Sopenharmony_ci * COMF[7] "System clock selection" 71762306a36Sopenharmony_ci * = 0 (0x00) 0....... "Use 24 MHz system clock" 71862306a36Sopenharmony_ci * COMF[6:4] "Reserved" 71962306a36Sopenharmony_ci * = 7 (0x07) .111.... 72062306a36Sopenharmony_ci * COMF[3] "Manual auto negative offset canceling selection" 72162306a36Sopenharmony_ci * = 0 (0x00) ....0... "Auto detect negative 72262306a36Sopenharmony_ci * offset and cancel it" 72362306a36Sopenharmony_ci * COMF[2:0] "Reserved" 72462306a36Sopenharmony_ci * = 0 (0x00) .....000 72562306a36Sopenharmony_ci */ 72662306a36Sopenharmony_ci { 0x0e, 0x70 }, 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci /* 72962306a36Sopenharmony_ci * 0F COMG "Common Control G" 73062306a36Sopenharmony_ci * = 66 (0x42) 01000010 73162306a36Sopenharmony_ci * COMG[7] "Optical black output selection" 73262306a36Sopenharmony_ci * = 0 (0x00) 0....... "Disable" 73362306a36Sopenharmony_ci * COMG[6] "Black level calibrate selection" 73462306a36Sopenharmony_ci * = 1 (0x01) .1...... "Use optical black pixels 73562306a36Sopenharmony_ci * to calibrate" 73662306a36Sopenharmony_ci * COMG[5:4] "Reserved" 73762306a36Sopenharmony_ci * = 0 (0x00) ..00.... 73862306a36Sopenharmony_ci * COMG[3] "Channel offset adjustment" 73962306a36Sopenharmony_ci * = 0 (0x00) ....0... "Disable offset adjustment" 74062306a36Sopenharmony_ci * COMG[2] "ADC black level calibration option" 74162306a36Sopenharmony_ci * = 0 (0x00) .....0.. "Use B/G line and G/R 74262306a36Sopenharmony_ci * line to calibrate each 74362306a36Sopenharmony_ci * channel's black level" 74462306a36Sopenharmony_ci * COMG[1] "Reserved" 74562306a36Sopenharmony_ci * = 1 (0x01) ......1. 74662306a36Sopenharmony_ci * COMG[0] "ADC black level calibration enable" 74762306a36Sopenharmony_ci * = 0 (0x00) .......0 "Disable" 74862306a36Sopenharmony_ci */ 74962306a36Sopenharmony_ci { 0x0f, 0x42 }, 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci /* 75262306a36Sopenharmony_ci * 14 COMJ "Common Control J" 75362306a36Sopenharmony_ci * = 198 (0xC6) 11000110 75462306a36Sopenharmony_ci * COMJ[7:6] "AGC gain ceiling" 75562306a36Sopenharmony_ci * = 3 (0x03) 11...... "8x" 75662306a36Sopenharmony_ci * COMJ[5:4] "Reserved" 75762306a36Sopenharmony_ci * = 0 (0x00) ..00.... 75862306a36Sopenharmony_ci * COMJ[3] "Auto banding filter" 75962306a36Sopenharmony_ci * = 0 (0x00) ....0... "Banding filter is always 76062306a36Sopenharmony_ci * on off depending on 76162306a36Sopenharmony_ci * COMI[5] setting" 76262306a36Sopenharmony_ci * COMJ[2] "VSYNC drop option" 76362306a36Sopenharmony_ci * = 1 (0x01) .....1.. "SYNC is dropped if frame 76462306a36Sopenharmony_ci * data is dropped" 76562306a36Sopenharmony_ci * COMJ[1] "Frame data drop" 76662306a36Sopenharmony_ci * = 1 (0x01) ......1. "Drop frame data if 76762306a36Sopenharmony_ci * exposure is not within 76862306a36Sopenharmony_ci * tolerance. In AEC mode, 76962306a36Sopenharmony_ci * data is normally dropped 77062306a36Sopenharmony_ci * when data is out of 77162306a36Sopenharmony_ci * range." 77262306a36Sopenharmony_ci * COMJ[0] "Reserved" 77362306a36Sopenharmony_ci * = 0 (0x00) .......0 77462306a36Sopenharmony_ci */ 77562306a36Sopenharmony_ci { 0x14, 0xc6 }, 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci /* 77862306a36Sopenharmony_ci * 15 COMK "Common Control K" 77962306a36Sopenharmony_ci * = 2 (0x02) 00000010 78062306a36Sopenharmony_ci * COMK[7] "CHSYNC pin output swap" 78162306a36Sopenharmony_ci * = 0 (0x00) 0....... "CHSYNC" 78262306a36Sopenharmony_ci * COMK[6] "HREF pin output swap" 78362306a36Sopenharmony_ci * = 0 (0x00) .0...... "HREF" 78462306a36Sopenharmony_ci * COMK[5] "PCLK output selection" 78562306a36Sopenharmony_ci * = 0 (0x00) ..0..... "PCLK always output" 78662306a36Sopenharmony_ci * COMK[4] "PCLK edge selection" 78762306a36Sopenharmony_ci * = 0 (0x00) ...0.... "Data valid on falling edge" 78862306a36Sopenharmony_ci * COMK[3] "HREF output polarity" 78962306a36Sopenharmony_ci * = 0 (0x00) ....0... "positive" 79062306a36Sopenharmony_ci * COMK[2] "Reserved" 79162306a36Sopenharmony_ci * = 0 (0x00) .....0.. 79262306a36Sopenharmony_ci * COMK[1] "VSYNC polarity" 79362306a36Sopenharmony_ci * = 1 (0x01) ......1. "negative" 79462306a36Sopenharmony_ci * COMK[0] "HSYNC polarity" 79562306a36Sopenharmony_ci * = 0 (0x00) .......0 "positive" 79662306a36Sopenharmony_ci */ 79762306a36Sopenharmony_ci { 0x15, 0x02 }, 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci /* 80062306a36Sopenharmony_ci * 33 CHLF "Current Control" 80162306a36Sopenharmony_ci * = 9 (0x09) 00001001 80262306a36Sopenharmony_ci * CHLF[7:6] "Sensor current control" 80362306a36Sopenharmony_ci * = 0 (0x00) 00...... 80462306a36Sopenharmony_ci * CHLF[5] "Sensor current range control" 80562306a36Sopenharmony_ci * = 0 (0x00) ..0..... "normal range" 80662306a36Sopenharmony_ci * CHLF[4] "Sensor current" 80762306a36Sopenharmony_ci * = 0 (0x00) ...0.... "normal current" 80862306a36Sopenharmony_ci * CHLF[3] "Sensor buffer current control" 80962306a36Sopenharmony_ci * = 1 (0x01) ....1... "half current" 81062306a36Sopenharmony_ci * CHLF[2] "Column buffer current control" 81162306a36Sopenharmony_ci * = 0 (0x00) .....0.. "normal current" 81262306a36Sopenharmony_ci * CHLF[1] "Analog DSP current control" 81362306a36Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 81462306a36Sopenharmony_ci * CHLF[1] "ADC current control" 81562306a36Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 81662306a36Sopenharmony_ci */ 81762306a36Sopenharmony_ci { 0x33, 0x09 }, 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci /* 82062306a36Sopenharmony_ci * 34 VBLM "Blooming Control" 82162306a36Sopenharmony_ci * = 80 (0x50) 01010000 82262306a36Sopenharmony_ci * VBLM[7] "Hard soft reset switch" 82362306a36Sopenharmony_ci * = 0 (0x00) 0....... "Hard reset" 82462306a36Sopenharmony_ci * VBLM[6:4] "Blooming voltage selection" 82562306a36Sopenharmony_ci * = 5 (0x05) .101.... 82662306a36Sopenharmony_ci * VBLM[3:0] "Sensor current control" 82762306a36Sopenharmony_ci * = 0 (0x00) ....0000 82862306a36Sopenharmony_ci */ 82962306a36Sopenharmony_ci { 0x34, 0x50 }, 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* 83262306a36Sopenharmony_ci * 36 VCHG "Sensor Precharge Voltage Control" 83362306a36Sopenharmony_ci * = 0 (0x00) 00000000 83462306a36Sopenharmony_ci * VCHG[7] "Reserved" 83562306a36Sopenharmony_ci * = 0 (0x00) 0....... 83662306a36Sopenharmony_ci * VCHG[6:4] "Sensor precharge voltage control" 83762306a36Sopenharmony_ci * = 0 (0x00) .000.... 83862306a36Sopenharmony_ci * VCHG[3:0] "Sensor array common reference" 83962306a36Sopenharmony_ci * = 0 (0x00) ....0000 84062306a36Sopenharmony_ci */ 84162306a36Sopenharmony_ci { 0x36, 0x00 }, 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci /* 84462306a36Sopenharmony_ci * 37 ADC "ADC Reference Control" 84562306a36Sopenharmony_ci * = 4 (0x04) 00000100 84662306a36Sopenharmony_ci * ADC[7:4] "Reserved" 84762306a36Sopenharmony_ci * = 0 (0x00) 0000.... 84862306a36Sopenharmony_ci * ADC[3] "ADC input signal range" 84962306a36Sopenharmony_ci * = 0 (0x00) ....0... "Input signal 1.0x" 85062306a36Sopenharmony_ci * ADC[2:0] "ADC range control" 85162306a36Sopenharmony_ci * = 4 (0x04) .....100 85262306a36Sopenharmony_ci */ 85362306a36Sopenharmony_ci { 0x37, 0x04 }, 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci /* 85662306a36Sopenharmony_ci * 38 ACOM "Analog Common Ground" 85762306a36Sopenharmony_ci * = 82 (0x52) 01010010 85862306a36Sopenharmony_ci * ACOM[7] "Analog gain control" 85962306a36Sopenharmony_ci * = 0 (0x00) 0....... "Gain 1x" 86062306a36Sopenharmony_ci * ACOM[6] "Analog black level calibration" 86162306a36Sopenharmony_ci * = 1 (0x01) .1...... "On" 86262306a36Sopenharmony_ci * ACOM[5:0] "Reserved" 86362306a36Sopenharmony_ci * = 18 (0x12) ..010010 86462306a36Sopenharmony_ci */ 86562306a36Sopenharmony_ci { 0x38, 0x52 }, 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci /* 86862306a36Sopenharmony_ci * 3A FREFA "Internal Reference Adjustment" 86962306a36Sopenharmony_ci * = 0 (0x00) 00000000 87062306a36Sopenharmony_ci * FREFA[7:0] "Range" 87162306a36Sopenharmony_ci * = 0 (0x00) 00000000 87262306a36Sopenharmony_ci */ 87362306a36Sopenharmony_ci { 0x3a, 0x00 }, 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci /* 87662306a36Sopenharmony_ci * 3C FVOPT "Internal Reference Adjustment" 87762306a36Sopenharmony_ci * = 31 (0x1F) 00011111 87862306a36Sopenharmony_ci * FVOPT[7:0] "Range" 87962306a36Sopenharmony_ci * = 31 (0x1F) 00011111 88062306a36Sopenharmony_ci */ 88162306a36Sopenharmony_ci { 0x3c, 0x1f }, 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci /* 88462306a36Sopenharmony_ci * 44 Undocumented = 0 (0x00) 00000000 88562306a36Sopenharmony_ci * 44[7:0] "It's a secret" 88662306a36Sopenharmony_ci * = 0 (0x00) 00000000 88762306a36Sopenharmony_ci */ 88862306a36Sopenharmony_ci { 0x44, 0x00 }, 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci /* 89162306a36Sopenharmony_ci * 40 Undocumented = 0 (0x00) 00000000 89262306a36Sopenharmony_ci * 40[7:0] "It's a secret" 89362306a36Sopenharmony_ci * = 0 (0x00) 00000000 89462306a36Sopenharmony_ci */ 89562306a36Sopenharmony_ci { 0x40, 0x00 }, 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci /* 89862306a36Sopenharmony_ci * 41 Undocumented = 0 (0x00) 00000000 89962306a36Sopenharmony_ci * 41[7:0] "It's a secret" 90062306a36Sopenharmony_ci * = 0 (0x00) 00000000 90162306a36Sopenharmony_ci */ 90262306a36Sopenharmony_ci { 0x41, 0x00 }, 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci /* 90562306a36Sopenharmony_ci * 42 Undocumented = 0 (0x00) 00000000 90662306a36Sopenharmony_ci * 42[7:0] "It's a secret" 90762306a36Sopenharmony_ci * = 0 (0x00) 00000000 90862306a36Sopenharmony_ci */ 90962306a36Sopenharmony_ci { 0x42, 0x00 }, 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci /* 91262306a36Sopenharmony_ci * 43 Undocumented = 0 (0x00) 00000000 91362306a36Sopenharmony_ci * 43[7:0] "It's a secret" 91462306a36Sopenharmony_ci * = 0 (0x00) 00000000 91562306a36Sopenharmony_ci */ 91662306a36Sopenharmony_ci { 0x43, 0x00 }, 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci /* 91962306a36Sopenharmony_ci * 45 Undocumented = 128 (0x80) 10000000 92062306a36Sopenharmony_ci * 45[7:0] "It's a secret" 92162306a36Sopenharmony_ci * = 128 (0x80) 10000000 92262306a36Sopenharmony_ci */ 92362306a36Sopenharmony_ci { 0x45, 0x80 }, 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci /* 92662306a36Sopenharmony_ci * 48 Undocumented = 192 (0xC0) 11000000 92762306a36Sopenharmony_ci * 48[7:0] "It's a secret" 92862306a36Sopenharmony_ci * = 192 (0xC0) 11000000 92962306a36Sopenharmony_ci */ 93062306a36Sopenharmony_ci { 0x48, 0xc0 }, 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci /* 93362306a36Sopenharmony_ci * 49 Undocumented = 25 (0x19) 00011001 93462306a36Sopenharmony_ci * 49[7:0] "It's a secret" 93562306a36Sopenharmony_ci * = 25 (0x19) 00011001 93662306a36Sopenharmony_ci */ 93762306a36Sopenharmony_ci { 0x49, 0x19 }, 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci /* 94062306a36Sopenharmony_ci * 4B Undocumented = 128 (0x80) 10000000 94162306a36Sopenharmony_ci * 4B[7:0] "It's a secret" 94262306a36Sopenharmony_ci * = 128 (0x80) 10000000 94362306a36Sopenharmony_ci */ 94462306a36Sopenharmony_ci { 0x4b, 0x80 }, 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci /* 94762306a36Sopenharmony_ci * 4D Undocumented = 196 (0xC4) 11000100 94862306a36Sopenharmony_ci * 4D[7:0] "It's a secret" 94962306a36Sopenharmony_ci * = 196 (0xC4) 11000100 95062306a36Sopenharmony_ci */ 95162306a36Sopenharmony_ci { 0x4d, 0xc4 }, 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci /* 95462306a36Sopenharmony_ci * 35 VREF "Reference Voltage Control" 95562306a36Sopenharmony_ci * = 76 (0x4c) 01001100 95662306a36Sopenharmony_ci * VREF[7:5] "Column high reference control" 95762306a36Sopenharmony_ci * = 2 (0x02) 010..... "higher voltage" 95862306a36Sopenharmony_ci * VREF[4:2] "Column low reference control" 95962306a36Sopenharmony_ci * = 3 (0x03) ...011.. "Highest voltage" 96062306a36Sopenharmony_ci * VREF[1:0] "Reserved" 96162306a36Sopenharmony_ci * = 0 (0x00) ......00 96262306a36Sopenharmony_ci */ 96362306a36Sopenharmony_ci { 0x35, 0x4c }, 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci /* 96662306a36Sopenharmony_ci * 3D Undocumented = 0 (0x00) 00000000 96762306a36Sopenharmony_ci * 3D[7:0] "It's a secret" 96862306a36Sopenharmony_ci * = 0 (0x00) 00000000 96962306a36Sopenharmony_ci */ 97062306a36Sopenharmony_ci { 0x3d, 0x00 }, 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci /* 97362306a36Sopenharmony_ci * 3E Undocumented = 0 (0x00) 00000000 97462306a36Sopenharmony_ci * 3E[7:0] "It's a secret" 97562306a36Sopenharmony_ci * = 0 (0x00) 00000000 97662306a36Sopenharmony_ci */ 97762306a36Sopenharmony_ci { 0x3e, 0x00 }, 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci /* 98062306a36Sopenharmony_ci * 3B FREFB "Internal Reference Adjustment" 98162306a36Sopenharmony_ci * = 24 (0x18) 00011000 98262306a36Sopenharmony_ci * FREFB[7:0] "Range" 98362306a36Sopenharmony_ci * = 24 (0x18) 00011000 98462306a36Sopenharmony_ci */ 98562306a36Sopenharmony_ci { 0x3b, 0x18 }, 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci /* 98862306a36Sopenharmony_ci * 33 CHLF "Current Control" 98962306a36Sopenharmony_ci * = 25 (0x19) 00011001 99062306a36Sopenharmony_ci * CHLF[7:6] "Sensor current control" 99162306a36Sopenharmony_ci * = 0 (0x00) 00...... 99262306a36Sopenharmony_ci * CHLF[5] "Sensor current range control" 99362306a36Sopenharmony_ci * = 0 (0x00) ..0..... "normal range" 99462306a36Sopenharmony_ci * CHLF[4] "Sensor current" 99562306a36Sopenharmony_ci * = 1 (0x01) ...1.... "double current" 99662306a36Sopenharmony_ci * CHLF[3] "Sensor buffer current control" 99762306a36Sopenharmony_ci * = 1 (0x01) ....1... "half current" 99862306a36Sopenharmony_ci * CHLF[2] "Column buffer current control" 99962306a36Sopenharmony_ci * = 0 (0x00) .....0.. "normal current" 100062306a36Sopenharmony_ci * CHLF[1] "Analog DSP current control" 100162306a36Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 100262306a36Sopenharmony_ci * CHLF[1] "ADC current control" 100362306a36Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 100462306a36Sopenharmony_ci */ 100562306a36Sopenharmony_ci { 0x33, 0x19 }, 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci /* 100862306a36Sopenharmony_ci * 34 VBLM "Blooming Control" 100962306a36Sopenharmony_ci * = 90 (0x5A) 01011010 101062306a36Sopenharmony_ci * VBLM[7] "Hard soft reset switch" 101162306a36Sopenharmony_ci * = 0 (0x00) 0....... "Hard reset" 101262306a36Sopenharmony_ci * VBLM[6:4] "Blooming voltage selection" 101362306a36Sopenharmony_ci * = 5 (0x05) .101.... 101462306a36Sopenharmony_ci * VBLM[3:0] "Sensor current control" 101562306a36Sopenharmony_ci * = 10 (0x0A) ....1010 101662306a36Sopenharmony_ci */ 101762306a36Sopenharmony_ci { 0x34, 0x5a }, 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci /* 102062306a36Sopenharmony_ci * 3B FREFB "Internal Reference Adjustment" 102162306a36Sopenharmony_ci * = 0 (0x00) 00000000 102262306a36Sopenharmony_ci * FREFB[7:0] "Range" 102362306a36Sopenharmony_ci * = 0 (0x00) 00000000 102462306a36Sopenharmony_ci */ 102562306a36Sopenharmony_ci { 0x3b, 0x00 }, 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci /* 102862306a36Sopenharmony_ci * 33 CHLF "Current Control" 102962306a36Sopenharmony_ci * = 9 (0x09) 00001001 103062306a36Sopenharmony_ci * CHLF[7:6] "Sensor current control" 103162306a36Sopenharmony_ci * = 0 (0x00) 00...... 103262306a36Sopenharmony_ci * CHLF[5] "Sensor current range control" 103362306a36Sopenharmony_ci * = 0 (0x00) ..0..... "normal range" 103462306a36Sopenharmony_ci * CHLF[4] "Sensor current" 103562306a36Sopenharmony_ci * = 0 (0x00) ...0.... "normal current" 103662306a36Sopenharmony_ci * CHLF[3] "Sensor buffer current control" 103762306a36Sopenharmony_ci * = 1 (0x01) ....1... "half current" 103862306a36Sopenharmony_ci * CHLF[2] "Column buffer current control" 103962306a36Sopenharmony_ci * = 0 (0x00) .....0.. "normal current" 104062306a36Sopenharmony_ci * CHLF[1] "Analog DSP current control" 104162306a36Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 104262306a36Sopenharmony_ci * CHLF[1] "ADC current control" 104362306a36Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 104462306a36Sopenharmony_ci */ 104562306a36Sopenharmony_ci { 0x33, 0x09 }, 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci /* 104862306a36Sopenharmony_ci * 34 VBLM "Blooming Control" 104962306a36Sopenharmony_ci * = 80 (0x50) 01010000 105062306a36Sopenharmony_ci * VBLM[7] "Hard soft reset switch" 105162306a36Sopenharmony_ci * = 0 (0x00) 0....... "Hard reset" 105262306a36Sopenharmony_ci * VBLM[6:4] "Blooming voltage selection" 105362306a36Sopenharmony_ci * = 5 (0x05) .101.... 105462306a36Sopenharmony_ci * VBLM[3:0] "Sensor current control" 105562306a36Sopenharmony_ci * = 0 (0x00) ....0000 105662306a36Sopenharmony_ci */ 105762306a36Sopenharmony_ci { 0x34, 0x50 }, 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci /* 106062306a36Sopenharmony_ci * 12 COMH "Common Control H" 106162306a36Sopenharmony_ci * = 64 (0x40) 01000000 106262306a36Sopenharmony_ci * COMH[7] "SRST" 106362306a36Sopenharmony_ci * = 0 (0x00) 0....... "No-op" 106462306a36Sopenharmony_ci * COMH[6:4] "Resolution selection" 106562306a36Sopenharmony_ci * = 4 (0x04) .100.... "XGA" 106662306a36Sopenharmony_ci * COMH[3] "Master slave selection" 106762306a36Sopenharmony_ci * = 0 (0x00) ....0... "Master mode" 106862306a36Sopenharmony_ci * COMH[2] "Internal B/R channel option" 106962306a36Sopenharmony_ci * = 0 (0x00) .....0.. "B/R use same channel" 107062306a36Sopenharmony_ci * COMH[1] "Color bar test pattern" 107162306a36Sopenharmony_ci * = 0 (0x00) ......0. "Off" 107262306a36Sopenharmony_ci * COMH[0] "Reserved" 107362306a36Sopenharmony_ci * = 0 (0x00) .......0 107462306a36Sopenharmony_ci */ 107562306a36Sopenharmony_ci { 0x12, 0x40 }, 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci /* 107862306a36Sopenharmony_ci * 17 HREFST "Horizontal window start" 107962306a36Sopenharmony_ci * = 31 (0x1F) 00011111 108062306a36Sopenharmony_ci * HREFST[7:0] "Horizontal window start, 8 MSBs" 108162306a36Sopenharmony_ci * = 31 (0x1F) 00011111 108262306a36Sopenharmony_ci */ 108362306a36Sopenharmony_ci { 0x17, 0x1f }, 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci /* 108662306a36Sopenharmony_ci * 18 HREFEND "Horizontal window end" 108762306a36Sopenharmony_ci * = 95 (0x5F) 01011111 108862306a36Sopenharmony_ci * HREFEND[7:0] "Horizontal Window End, 8 MSBs" 108962306a36Sopenharmony_ci * = 95 (0x5F) 01011111 109062306a36Sopenharmony_ci */ 109162306a36Sopenharmony_ci { 0x18, 0x5f }, 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci /* 109462306a36Sopenharmony_ci * 19 VSTRT "Vertical window start" 109562306a36Sopenharmony_ci * = 0 (0x00) 00000000 109662306a36Sopenharmony_ci * VSTRT[7:0] "Vertical Window Start, 8 MSBs" 109762306a36Sopenharmony_ci * = 0 (0x00) 00000000 109862306a36Sopenharmony_ci */ 109962306a36Sopenharmony_ci { 0x19, 0x00 }, 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* 110262306a36Sopenharmony_ci * 1A VEND "Vertical window end" 110362306a36Sopenharmony_ci * = 96 (0x60) 01100000 110462306a36Sopenharmony_ci * VEND[7:0] "Vertical Window End, 8 MSBs" 110562306a36Sopenharmony_ci * = 96 (0x60) 01100000 110662306a36Sopenharmony_ci */ 110762306a36Sopenharmony_ci { 0x1a, 0x60 }, 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci /* 111062306a36Sopenharmony_ci * 32 COMM "Common Control M" 111162306a36Sopenharmony_ci * = 18 (0x12) 00010010 111262306a36Sopenharmony_ci * COMM[7:6] "Pixel clock divide option" 111362306a36Sopenharmony_ci * = 0 (0x00) 00...... "/1" 111462306a36Sopenharmony_ci * COMM[5:3] "Horizontal window end position, 3 LSBs" 111562306a36Sopenharmony_ci * = 2 (0x02) ..010... 111662306a36Sopenharmony_ci * COMM[2:0] "Horizontal window start position, 3 LSBs" 111762306a36Sopenharmony_ci * = 2 (0x02) .....010 111862306a36Sopenharmony_ci */ 111962306a36Sopenharmony_ci { 0x32, 0x12 }, 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci /* 112262306a36Sopenharmony_ci * 03 COMA "Common Control A" 112362306a36Sopenharmony_ci * = 74 (0x4A) 01001010 112462306a36Sopenharmony_ci * COMA[7:4] "AWB Update Threshold" 112562306a36Sopenharmony_ci * = 4 (0x04) 0100.... 112662306a36Sopenharmony_ci * COMA[3:2] "Vertical window end line control 2 LSBs" 112762306a36Sopenharmony_ci * = 2 (0x02) ....10.. 112862306a36Sopenharmony_ci * COMA[1:0] "Vertical window start line control 2 LSBs" 112962306a36Sopenharmony_ci * = 2 (0x02) ......10 113062306a36Sopenharmony_ci */ 113162306a36Sopenharmony_ci { 0x03, 0x4a }, 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci /* 113462306a36Sopenharmony_ci * 11 CLKRC "Clock Rate Control" 113562306a36Sopenharmony_ci * = 128 (0x80) 10000000 113662306a36Sopenharmony_ci * CLKRC[7] "Internal frequency doublers on off seclection" 113762306a36Sopenharmony_ci * = 1 (0x01) 1....... "On" 113862306a36Sopenharmony_ci * CLKRC[6] "Digital video master slave selection" 113962306a36Sopenharmony_ci * = 0 (0x00) .0...... "Master mode, sensor 114062306a36Sopenharmony_ci * provides PCLK" 114162306a36Sopenharmony_ci * CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }" 114262306a36Sopenharmony_ci * = 0 (0x00) ..000000 114362306a36Sopenharmony_ci */ 114462306a36Sopenharmony_ci { 0x11, 0x80 }, 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci /* 114762306a36Sopenharmony_ci * 12 COMH "Common Control H" 114862306a36Sopenharmony_ci * = 0 (0x00) 00000000 114962306a36Sopenharmony_ci * COMH[7] "SRST" 115062306a36Sopenharmony_ci * = 0 (0x00) 0....... "No-op" 115162306a36Sopenharmony_ci * COMH[6:4] "Resolution selection" 115262306a36Sopenharmony_ci * = 0 (0x00) .000.... "QXGA" 115362306a36Sopenharmony_ci * COMH[3] "Master slave selection" 115462306a36Sopenharmony_ci * = 0 (0x00) ....0... "Master mode" 115562306a36Sopenharmony_ci * COMH[2] "Internal B/R channel option" 115662306a36Sopenharmony_ci * = 0 (0x00) .....0.. "B/R use same channel" 115762306a36Sopenharmony_ci * COMH[1] "Color bar test pattern" 115862306a36Sopenharmony_ci * = 0 (0x00) ......0. "Off" 115962306a36Sopenharmony_ci * COMH[0] "Reserved" 116062306a36Sopenharmony_ci * = 0 (0x00) .......0 116162306a36Sopenharmony_ci */ 116262306a36Sopenharmony_ci { 0x12, 0x00 }, 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci /* 116562306a36Sopenharmony_ci * 12 COMH "Common Control H" 116662306a36Sopenharmony_ci * = 64 (0x40) 01000000 116762306a36Sopenharmony_ci * COMH[7] "SRST" 116862306a36Sopenharmony_ci * = 0 (0x00) 0....... "No-op" 116962306a36Sopenharmony_ci * COMH[6:4] "Resolution selection" 117062306a36Sopenharmony_ci * = 4 (0x04) .100.... "XGA" 117162306a36Sopenharmony_ci * COMH[3] "Master slave selection" 117262306a36Sopenharmony_ci * = 0 (0x00) ....0... "Master mode" 117362306a36Sopenharmony_ci * COMH[2] "Internal B/R channel option" 117462306a36Sopenharmony_ci * = 0 (0x00) .....0.. "B/R use same channel" 117562306a36Sopenharmony_ci * COMH[1] "Color bar test pattern" 117662306a36Sopenharmony_ci * = 0 (0x00) ......0. "Off" 117762306a36Sopenharmony_ci * COMH[0] "Reserved" 117862306a36Sopenharmony_ci * = 0 (0x00) .......0 117962306a36Sopenharmony_ci */ 118062306a36Sopenharmony_ci { 0x12, 0x40 }, 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci /* 118362306a36Sopenharmony_ci * 17 HREFST "Horizontal window start" 118462306a36Sopenharmony_ci * = 31 (0x1F) 00011111 118562306a36Sopenharmony_ci * HREFST[7:0] "Horizontal window start, 8 MSBs" 118662306a36Sopenharmony_ci * = 31 (0x1F) 00011111 118762306a36Sopenharmony_ci */ 118862306a36Sopenharmony_ci { 0x17, 0x1f }, 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci /* 119162306a36Sopenharmony_ci * 18 HREFEND "Horizontal window end" 119262306a36Sopenharmony_ci * = 95 (0x5F) 01011111 119362306a36Sopenharmony_ci * HREFEND[7:0] "Horizontal Window End, 8 MSBs" 119462306a36Sopenharmony_ci * = 95 (0x5F) 01011111 119562306a36Sopenharmony_ci */ 119662306a36Sopenharmony_ci { 0x18, 0x5f }, 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci /* 119962306a36Sopenharmony_ci * 19 VSTRT "Vertical window start" 120062306a36Sopenharmony_ci * = 0 (0x00) 00000000 120162306a36Sopenharmony_ci * VSTRT[7:0] "Vertical Window Start, 8 MSBs" 120262306a36Sopenharmony_ci * = 0 (0x00) 00000000 120362306a36Sopenharmony_ci */ 120462306a36Sopenharmony_ci { 0x19, 0x00 }, 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci /* 120762306a36Sopenharmony_ci * 1A VEND "Vertical window end" 120862306a36Sopenharmony_ci * = 96 (0x60) 01100000 120962306a36Sopenharmony_ci * VEND[7:0] "Vertical Window End, 8 MSBs" 121062306a36Sopenharmony_ci * = 96 (0x60) 01100000 121162306a36Sopenharmony_ci */ 121262306a36Sopenharmony_ci { 0x1a, 0x60 }, 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci /* 121562306a36Sopenharmony_ci * 32 COMM "Common Control M" 121662306a36Sopenharmony_ci * = 18 (0x12) 00010010 121762306a36Sopenharmony_ci * COMM[7:6] "Pixel clock divide option" 121862306a36Sopenharmony_ci * = 0 (0x00) 00...... "/1" 121962306a36Sopenharmony_ci * COMM[5:3] "Horizontal window end position, 3 LSBs" 122062306a36Sopenharmony_ci * = 2 (0x02) ..010... 122162306a36Sopenharmony_ci * COMM[2:0] "Horizontal window start position, 3 LSBs" 122262306a36Sopenharmony_ci * = 2 (0x02) .....010 122362306a36Sopenharmony_ci */ 122462306a36Sopenharmony_ci { 0x32, 0x12 }, 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci /* 122762306a36Sopenharmony_ci * 03 COMA "Common Control A" 122862306a36Sopenharmony_ci * = 74 (0x4A) 01001010 122962306a36Sopenharmony_ci * COMA[7:4] "AWB Update Threshold" 123062306a36Sopenharmony_ci * = 4 (0x04) 0100.... 123162306a36Sopenharmony_ci * COMA[3:2] "Vertical window end line control 2 LSBs" 123262306a36Sopenharmony_ci * = 2 (0x02) ....10.. 123362306a36Sopenharmony_ci * COMA[1:0] "Vertical window start line control 2 LSBs" 123462306a36Sopenharmony_ci * = 2 (0x02) ......10 123562306a36Sopenharmony_ci */ 123662306a36Sopenharmony_ci { 0x03, 0x4a }, 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci /* 123962306a36Sopenharmony_ci * 02 RED "Red Gain Control" 124062306a36Sopenharmony_ci * = 175 (0xAF) 10101111 124162306a36Sopenharmony_ci * RED[7] "Action" 124262306a36Sopenharmony_ci * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" 124362306a36Sopenharmony_ci * RED[6:0] "Value" 124462306a36Sopenharmony_ci * = 47 (0x2F) .0101111 124562306a36Sopenharmony_ci */ 124662306a36Sopenharmony_ci { 0x02, 0xaf }, 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci /* 124962306a36Sopenharmony_ci * 2D ADDVSL "VSYNC Pulse Width" 125062306a36Sopenharmony_ci * = 210 (0xD2) 11010010 125162306a36Sopenharmony_ci * ADDVSL[7:0] "VSYNC pulse width, LSB" 125262306a36Sopenharmony_ci * = 210 (0xD2) 11010010 125362306a36Sopenharmony_ci */ 125462306a36Sopenharmony_ci { 0x2d, 0xd2 }, 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci /* 125762306a36Sopenharmony_ci * 00 GAIN = 24 (0x18) 00011000 125862306a36Sopenharmony_ci * GAIN[7:6] "Reserved" 125962306a36Sopenharmony_ci * = 0 (0x00) 00...... 126062306a36Sopenharmony_ci * GAIN[5] "Double" 126162306a36Sopenharmony_ci * = 0 (0x00) ..0..... "False" 126262306a36Sopenharmony_ci * GAIN[4] "Double" 126362306a36Sopenharmony_ci * = 1 (0x01) ...1.... "True" 126462306a36Sopenharmony_ci * GAIN[3:0] "Range" 126562306a36Sopenharmony_ci * = 8 (0x08) ....1000 126662306a36Sopenharmony_ci */ 126762306a36Sopenharmony_ci { 0x00, 0x18 }, 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci /* 127062306a36Sopenharmony_ci * 01 BLUE "Blue Gain Control" 127162306a36Sopenharmony_ci * = 240 (0xF0) 11110000 127262306a36Sopenharmony_ci * BLUE[7] "Action" 127362306a36Sopenharmony_ci * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" 127462306a36Sopenharmony_ci * BLUE[6:0] "Value" 127562306a36Sopenharmony_ci * = 112 (0x70) .1110000 127662306a36Sopenharmony_ci */ 127762306a36Sopenharmony_ci { 0x01, 0xf0 }, 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci /* 128062306a36Sopenharmony_ci * 10 AEC "Automatic Exposure Control" 128162306a36Sopenharmony_ci * = 10 (0x0A) 00001010 128262306a36Sopenharmony_ci * AEC[7:0] "Automatic Exposure Control, 8 MSBs" 128362306a36Sopenharmony_ci * = 10 (0x0A) 00001010 128462306a36Sopenharmony_ci */ 128562306a36Sopenharmony_ci { 0x10, 0x0a }, 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci { 0xe1, 0x67 }, 128862306a36Sopenharmony_ci { 0xe3, 0x03 }, 128962306a36Sopenharmony_ci { 0xe4, 0x26 }, 129062306a36Sopenharmony_ci { 0xe5, 0x3e }, 129162306a36Sopenharmony_ci { 0xf8, 0x01 }, 129262306a36Sopenharmony_ci { 0xff, 0x01 }, 129362306a36Sopenharmony_ci}; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_6x20[] = { 129662306a36Sopenharmony_ci { 0x12, 0x80 }, /* reset */ 129762306a36Sopenharmony_ci { 0x11, 0x01 }, 129862306a36Sopenharmony_ci { 0x03, 0x60 }, 129962306a36Sopenharmony_ci { 0x05, 0x7f }, /* For when autoadjust is off */ 130062306a36Sopenharmony_ci { 0x07, 0xa8 }, 130162306a36Sopenharmony_ci /* The ratio of 0x0c and 0x0d controls the white point */ 130262306a36Sopenharmony_ci { 0x0c, 0x24 }, 130362306a36Sopenharmony_ci { 0x0d, 0x24 }, 130462306a36Sopenharmony_ci { 0x0f, 0x15 }, /* COMS */ 130562306a36Sopenharmony_ci { 0x10, 0x75 }, /* AEC Exposure time */ 130662306a36Sopenharmony_ci { 0x12, 0x24 }, /* Enable AGC */ 130762306a36Sopenharmony_ci { 0x14, 0x04 }, 130862306a36Sopenharmony_ci /* 0x16: 0x06 helps frame stability with moving objects */ 130962306a36Sopenharmony_ci { 0x16, 0x06 }, 131062306a36Sopenharmony_ci/* { 0x20, 0x30 }, * Aperture correction enable */ 131162306a36Sopenharmony_ci { 0x26, 0xb2 }, /* BLC enable */ 131262306a36Sopenharmony_ci /* 0x28: 0x05 Selects RGB format if RGB on */ 131362306a36Sopenharmony_ci { 0x28, 0x05 }, 131462306a36Sopenharmony_ci { 0x2a, 0x04 }, /* Disable framerate adjust */ 131562306a36Sopenharmony_ci/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */ 131662306a36Sopenharmony_ci { 0x2d, 0x85 }, 131762306a36Sopenharmony_ci { 0x33, 0xa0 }, /* Color Processing Parameter */ 131862306a36Sopenharmony_ci { 0x34, 0xd2 }, /* Max A/D range */ 131962306a36Sopenharmony_ci { 0x38, 0x8b }, 132062306a36Sopenharmony_ci { 0x39, 0x40 }, 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci { 0x3c, 0x39 }, /* Enable AEC mode changing */ 132362306a36Sopenharmony_ci { 0x3c, 0x3c }, /* Change AEC mode */ 132462306a36Sopenharmony_ci { 0x3c, 0x24 }, /* Disable AEC mode changing */ 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci { 0x3d, 0x80 }, 132762306a36Sopenharmony_ci /* These next two registers (0x4a, 0x4b) are undocumented. 132862306a36Sopenharmony_ci * They control the color balance */ 132962306a36Sopenharmony_ci { 0x4a, 0x80 }, 133062306a36Sopenharmony_ci { 0x4b, 0x80 }, 133162306a36Sopenharmony_ci { 0x4d, 0xd2 }, /* This reduces noise a bit */ 133262306a36Sopenharmony_ci { 0x4e, 0xc1 }, 133362306a36Sopenharmony_ci { 0x4f, 0x04 }, 133462306a36Sopenharmony_ci/* Do 50-53 have any effect? */ 133562306a36Sopenharmony_ci/* Toggle 0x12[2] off and on here? */ 133662306a36Sopenharmony_ci}; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_6x30[] = { 133962306a36Sopenharmony_ci { 0x12, 0x80 }, /* Reset */ 134062306a36Sopenharmony_ci { 0x00, 0x1f }, /* Gain */ 134162306a36Sopenharmony_ci { 0x01, 0x99 }, /* Blue gain */ 134262306a36Sopenharmony_ci { 0x02, 0x7c }, /* Red gain */ 134362306a36Sopenharmony_ci { 0x03, 0xc0 }, /* Saturation */ 134462306a36Sopenharmony_ci { 0x05, 0x0a }, /* Contrast */ 134562306a36Sopenharmony_ci { 0x06, 0x95 }, /* Brightness */ 134662306a36Sopenharmony_ci { 0x07, 0x2d }, /* Sharpness */ 134762306a36Sopenharmony_ci { 0x0c, 0x20 }, 134862306a36Sopenharmony_ci { 0x0d, 0x20 }, 134962306a36Sopenharmony_ci { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */ 135062306a36Sopenharmony_ci { 0x0f, 0x05 }, 135162306a36Sopenharmony_ci { 0x10, 0x9a }, 135262306a36Sopenharmony_ci { 0x11, 0x00 }, /* Pixel clock = fastest */ 135362306a36Sopenharmony_ci { 0x12, 0x24 }, /* Enable AGC and AWB */ 135462306a36Sopenharmony_ci { 0x13, 0x21 }, 135562306a36Sopenharmony_ci { 0x14, 0x80 }, 135662306a36Sopenharmony_ci { 0x15, 0x01 }, 135762306a36Sopenharmony_ci { 0x16, 0x03 }, 135862306a36Sopenharmony_ci { 0x17, 0x38 }, 135962306a36Sopenharmony_ci { 0x18, 0xea }, 136062306a36Sopenharmony_ci { 0x19, 0x04 }, 136162306a36Sopenharmony_ci { 0x1a, 0x93 }, 136262306a36Sopenharmony_ci { 0x1b, 0x00 }, 136362306a36Sopenharmony_ci { 0x1e, 0xc4 }, 136462306a36Sopenharmony_ci { 0x1f, 0x04 }, 136562306a36Sopenharmony_ci { 0x20, 0x20 }, 136662306a36Sopenharmony_ci { 0x21, 0x10 }, 136762306a36Sopenharmony_ci { 0x22, 0x88 }, 136862306a36Sopenharmony_ci { 0x23, 0xc0 }, /* Crystal circuit power level */ 136962306a36Sopenharmony_ci { 0x25, 0x9a }, /* Increase AEC black ratio */ 137062306a36Sopenharmony_ci { 0x26, 0xb2 }, /* BLC enable */ 137162306a36Sopenharmony_ci { 0x27, 0xa2 }, 137262306a36Sopenharmony_ci { 0x28, 0x00 }, 137362306a36Sopenharmony_ci { 0x29, 0x00 }, 137462306a36Sopenharmony_ci { 0x2a, 0x84 }, /* 60 Hz power */ 137562306a36Sopenharmony_ci { 0x2b, 0xa8 }, /* 60 Hz power */ 137662306a36Sopenharmony_ci { 0x2c, 0xa0 }, 137762306a36Sopenharmony_ci { 0x2d, 0x95 }, /* Enable auto-brightness */ 137862306a36Sopenharmony_ci { 0x2e, 0x88 }, 137962306a36Sopenharmony_ci { 0x33, 0x26 }, 138062306a36Sopenharmony_ci { 0x34, 0x03 }, 138162306a36Sopenharmony_ci { 0x36, 0x8f }, 138262306a36Sopenharmony_ci { 0x37, 0x80 }, 138362306a36Sopenharmony_ci { 0x38, 0x83 }, 138462306a36Sopenharmony_ci { 0x39, 0x80 }, 138562306a36Sopenharmony_ci { 0x3a, 0x0f }, 138662306a36Sopenharmony_ci { 0x3b, 0x3c }, 138762306a36Sopenharmony_ci { 0x3c, 0x1a }, 138862306a36Sopenharmony_ci { 0x3d, 0x80 }, 138962306a36Sopenharmony_ci { 0x3e, 0x80 }, 139062306a36Sopenharmony_ci { 0x3f, 0x0e }, 139162306a36Sopenharmony_ci { 0x40, 0x00 }, /* White bal */ 139262306a36Sopenharmony_ci { 0x41, 0x00 }, /* White bal */ 139362306a36Sopenharmony_ci { 0x42, 0x80 }, 139462306a36Sopenharmony_ci { 0x43, 0x3f }, /* White bal */ 139562306a36Sopenharmony_ci { 0x44, 0x80 }, 139662306a36Sopenharmony_ci { 0x45, 0x20 }, 139762306a36Sopenharmony_ci { 0x46, 0x20 }, 139862306a36Sopenharmony_ci { 0x47, 0x80 }, 139962306a36Sopenharmony_ci { 0x48, 0x7f }, 140062306a36Sopenharmony_ci { 0x49, 0x00 }, 140162306a36Sopenharmony_ci { 0x4a, 0x00 }, 140262306a36Sopenharmony_ci { 0x4b, 0x80 }, 140362306a36Sopenharmony_ci { 0x4c, 0xd0 }, 140462306a36Sopenharmony_ci { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ 140562306a36Sopenharmony_ci { 0x4e, 0x40 }, 140662306a36Sopenharmony_ci { 0x4f, 0x07 }, /* UV avg., col. killer: max */ 140762306a36Sopenharmony_ci { 0x50, 0xff }, 140862306a36Sopenharmony_ci { 0x54, 0x23 }, /* Max AGC gain: 18dB */ 140962306a36Sopenharmony_ci { 0x55, 0xff }, 141062306a36Sopenharmony_ci { 0x56, 0x12 }, 141162306a36Sopenharmony_ci { 0x57, 0x81 }, 141262306a36Sopenharmony_ci { 0x58, 0x75 }, 141362306a36Sopenharmony_ci { 0x59, 0x01 }, /* AGC dark current comp.: +1 */ 141462306a36Sopenharmony_ci { 0x5a, 0x2c }, 141562306a36Sopenharmony_ci { 0x5b, 0x0f }, /* AWB chrominance levels */ 141662306a36Sopenharmony_ci { 0x5c, 0x10 }, 141762306a36Sopenharmony_ci { 0x3d, 0x80 }, 141862306a36Sopenharmony_ci { 0x27, 0xa6 }, 141962306a36Sopenharmony_ci { 0x12, 0x20 }, /* Toggle AWB */ 142062306a36Sopenharmony_ci { 0x12, 0x24 }, 142162306a36Sopenharmony_ci}; 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci/* Lawrence Glaister <lg@jfm.bc.ca> reports: 142462306a36Sopenharmony_ci * 142562306a36Sopenharmony_ci * Register 0x0f in the 7610 has the following effects: 142662306a36Sopenharmony_ci * 142762306a36Sopenharmony_ci * 0x85 (AEC method 1): Best overall, good contrast range 142862306a36Sopenharmony_ci * 0x45 (AEC method 2): Very overexposed 142962306a36Sopenharmony_ci * 0xa5 (spec sheet default): Ok, but the black level is 143062306a36Sopenharmony_ci * shifted resulting in loss of contrast 143162306a36Sopenharmony_ci * 0x05 (old driver setting): very overexposed, too much 143262306a36Sopenharmony_ci * contrast 143362306a36Sopenharmony_ci */ 143462306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7610[] = { 143562306a36Sopenharmony_ci { 0x10, 0xff }, 143662306a36Sopenharmony_ci { 0x16, 0x06 }, 143762306a36Sopenharmony_ci { 0x28, 0x24 }, 143862306a36Sopenharmony_ci { 0x2b, 0xac }, 143962306a36Sopenharmony_ci { 0x12, 0x00 }, 144062306a36Sopenharmony_ci { 0x38, 0x81 }, 144162306a36Sopenharmony_ci { 0x28, 0x24 }, /* 0c */ 144262306a36Sopenharmony_ci { 0x0f, 0x85 }, /* lg's setting */ 144362306a36Sopenharmony_ci { 0x15, 0x01 }, 144462306a36Sopenharmony_ci { 0x20, 0x1c }, 144562306a36Sopenharmony_ci { 0x23, 0x2a }, 144662306a36Sopenharmony_ci { 0x24, 0x10 }, 144762306a36Sopenharmony_ci { 0x25, 0x8a }, 144862306a36Sopenharmony_ci { 0x26, 0xa2 }, 144962306a36Sopenharmony_ci { 0x27, 0xc2 }, 145062306a36Sopenharmony_ci { 0x2a, 0x04 }, 145162306a36Sopenharmony_ci { 0x2c, 0xfe }, 145262306a36Sopenharmony_ci { 0x2d, 0x93 }, 145362306a36Sopenharmony_ci { 0x30, 0x71 }, 145462306a36Sopenharmony_ci { 0x31, 0x60 }, 145562306a36Sopenharmony_ci { 0x32, 0x26 }, 145662306a36Sopenharmony_ci { 0x33, 0x20 }, 145762306a36Sopenharmony_ci { 0x34, 0x48 }, 145862306a36Sopenharmony_ci { 0x12, 0x24 }, 145962306a36Sopenharmony_ci { 0x11, 0x01 }, 146062306a36Sopenharmony_ci { 0x0c, 0x24 }, 146162306a36Sopenharmony_ci { 0x0d, 0x24 }, 146262306a36Sopenharmony_ci}; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7620[] = { 146562306a36Sopenharmony_ci { 0x12, 0x80 }, /* reset */ 146662306a36Sopenharmony_ci { 0x00, 0x00 }, /* gain */ 146762306a36Sopenharmony_ci { 0x01, 0x80 }, /* blue gain */ 146862306a36Sopenharmony_ci { 0x02, 0x80 }, /* red gain */ 146962306a36Sopenharmony_ci { 0x03, 0xc0 }, /* OV7670_R03_VREF */ 147062306a36Sopenharmony_ci { 0x06, 0x60 }, 147162306a36Sopenharmony_ci { 0x07, 0x00 }, 147262306a36Sopenharmony_ci { 0x0c, 0x24 }, 147362306a36Sopenharmony_ci { 0x0c, 0x24 }, 147462306a36Sopenharmony_ci { 0x0d, 0x24 }, 147562306a36Sopenharmony_ci { 0x11, 0x01 }, 147662306a36Sopenharmony_ci { 0x12, 0x24 }, 147762306a36Sopenharmony_ci { 0x13, 0x01 }, 147862306a36Sopenharmony_ci { 0x14, 0x84 }, 147962306a36Sopenharmony_ci { 0x15, 0x01 }, 148062306a36Sopenharmony_ci { 0x16, 0x03 }, 148162306a36Sopenharmony_ci { 0x17, 0x2f }, 148262306a36Sopenharmony_ci { 0x18, 0xcf }, 148362306a36Sopenharmony_ci { 0x19, 0x06 }, 148462306a36Sopenharmony_ci { 0x1a, 0xf5 }, 148562306a36Sopenharmony_ci { 0x1b, 0x00 }, 148662306a36Sopenharmony_ci { 0x20, 0x18 }, 148762306a36Sopenharmony_ci { 0x21, 0x80 }, 148862306a36Sopenharmony_ci { 0x22, 0x80 }, 148962306a36Sopenharmony_ci { 0x23, 0x00 }, 149062306a36Sopenharmony_ci { 0x26, 0xa2 }, 149162306a36Sopenharmony_ci { 0x27, 0xea }, 149262306a36Sopenharmony_ci { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */ 149362306a36Sopenharmony_ci { 0x29, 0x00 }, 149462306a36Sopenharmony_ci { 0x2a, 0x10 }, 149562306a36Sopenharmony_ci { 0x2b, 0x00 }, 149662306a36Sopenharmony_ci { 0x2c, 0x88 }, 149762306a36Sopenharmony_ci { 0x2d, 0x91 }, 149862306a36Sopenharmony_ci { 0x2e, 0x80 }, 149962306a36Sopenharmony_ci { 0x2f, 0x44 }, 150062306a36Sopenharmony_ci { 0x60, 0x27 }, 150162306a36Sopenharmony_ci { 0x61, 0x02 }, 150262306a36Sopenharmony_ci { 0x62, 0x5f }, 150362306a36Sopenharmony_ci { 0x63, 0xd5 }, 150462306a36Sopenharmony_ci { 0x64, 0x57 }, 150562306a36Sopenharmony_ci { 0x65, 0x83 }, 150662306a36Sopenharmony_ci { 0x66, 0x55 }, 150762306a36Sopenharmony_ci { 0x67, 0x92 }, 150862306a36Sopenharmony_ci { 0x68, 0xcf }, 150962306a36Sopenharmony_ci { 0x69, 0x76 }, 151062306a36Sopenharmony_ci { 0x6a, 0x22 }, 151162306a36Sopenharmony_ci { 0x6b, 0x00 }, 151262306a36Sopenharmony_ci { 0x6c, 0x02 }, 151362306a36Sopenharmony_ci { 0x6d, 0x44 }, 151462306a36Sopenharmony_ci { 0x6e, 0x80 }, 151562306a36Sopenharmony_ci { 0x6f, 0x1d }, 151662306a36Sopenharmony_ci { 0x70, 0x8b }, 151762306a36Sopenharmony_ci { 0x71, 0x00 }, 151862306a36Sopenharmony_ci { 0x72, 0x14 }, 151962306a36Sopenharmony_ci { 0x73, 0x54 }, 152062306a36Sopenharmony_ci { 0x74, 0x00 }, 152162306a36Sopenharmony_ci { 0x75, 0x8e }, 152262306a36Sopenharmony_ci { 0x76, 0x00 }, 152362306a36Sopenharmony_ci { 0x77, 0xff }, 152462306a36Sopenharmony_ci { 0x78, 0x80 }, 152562306a36Sopenharmony_ci { 0x79, 0x80 }, 152662306a36Sopenharmony_ci { 0x7a, 0x80 }, 152762306a36Sopenharmony_ci { 0x7b, 0xe2 }, 152862306a36Sopenharmony_ci { 0x7c, 0x00 }, 152962306a36Sopenharmony_ci}; 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci/* 7640 and 7648. The defaults should be OK for most registers. */ 153262306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7640[] = { 153362306a36Sopenharmony_ci { 0x12, 0x80 }, 153462306a36Sopenharmony_ci { 0x12, 0x14 }, 153562306a36Sopenharmony_ci}; 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_cistatic const struct ov_regvals init_519_ov7660[] = { 153862306a36Sopenharmony_ci { 0x5d, 0x03 }, /* Turn off suspend mode */ 153962306a36Sopenharmony_ci { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */ 154062306a36Sopenharmony_ci { 0x54, 0x0f }, /* bit2 (jpeg enable) */ 154162306a36Sopenharmony_ci { 0xa2, 0x20 }, /* a2-a5 are undocumented */ 154262306a36Sopenharmony_ci { 0xa3, 0x18 }, 154362306a36Sopenharmony_ci { 0xa4, 0x04 }, 154462306a36Sopenharmony_ci { 0xa5, 0x28 }, 154562306a36Sopenharmony_ci { 0x37, 0x00 }, /* SetUsbInit */ 154662306a36Sopenharmony_ci { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ 154762306a36Sopenharmony_ci /* Enable both fields, YUV Input, disable defect comp (why?) */ 154862306a36Sopenharmony_ci { 0x20, 0x0c }, /* 0x0d does U <-> V swap */ 154962306a36Sopenharmony_ci { 0x21, 0x38 }, 155062306a36Sopenharmony_ci { 0x22, 0x1d }, 155162306a36Sopenharmony_ci { 0x17, 0x50 }, /* undocumented */ 155262306a36Sopenharmony_ci { 0x37, 0x00 }, /* undocumented */ 155362306a36Sopenharmony_ci { 0x40, 0xff }, /* I2C timeout counter */ 155462306a36Sopenharmony_ci { 0x46, 0x00 }, /* I2C clock prescaler */ 155562306a36Sopenharmony_ci}; 155662306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7660[] = { 155762306a36Sopenharmony_ci {OV7670_R12_COM7, OV7670_COM7_RESET}, 155862306a36Sopenharmony_ci {OV7670_R11_CLKRC, 0x81}, 155962306a36Sopenharmony_ci {0x92, 0x00}, /* DM_LNL */ 156062306a36Sopenharmony_ci {0x93, 0x00}, /* DM_LNH */ 156162306a36Sopenharmony_ci {0x9d, 0x4c}, /* BD50ST */ 156262306a36Sopenharmony_ci {0x9e, 0x3f}, /* BD60ST */ 156362306a36Sopenharmony_ci {OV7670_R3B_COM11, 0x02}, 156462306a36Sopenharmony_ci {OV7670_R13_COM8, 0xf5}, 156562306a36Sopenharmony_ci {OV7670_R10_AECH, 0x00}, 156662306a36Sopenharmony_ci {OV7670_R00_GAIN, 0x00}, 156762306a36Sopenharmony_ci {OV7670_R01_BLUE, 0x7c}, 156862306a36Sopenharmony_ci {OV7670_R02_RED, 0x9d}, 156962306a36Sopenharmony_ci {OV7670_R12_COM7, 0x00}, 157062306a36Sopenharmony_ci {OV7670_R04_COM1, 00}, 157162306a36Sopenharmony_ci {OV7670_R18_HSTOP, 0x01}, 157262306a36Sopenharmony_ci {OV7670_R17_HSTART, 0x13}, 157362306a36Sopenharmony_ci {OV7670_R32_HREF, 0x92}, 157462306a36Sopenharmony_ci {OV7670_R19_VSTART, 0x02}, 157562306a36Sopenharmony_ci {OV7670_R1A_VSTOP, 0x7a}, 157662306a36Sopenharmony_ci {OV7670_R03_VREF, 0x00}, 157762306a36Sopenharmony_ci {OV7670_R0E_COM5, 0x04}, 157862306a36Sopenharmony_ci {OV7670_R0F_COM6, 0x62}, 157962306a36Sopenharmony_ci {OV7670_R15_COM10, 0x00}, 158062306a36Sopenharmony_ci {0x16, 0x02}, /* RSVD */ 158162306a36Sopenharmony_ci {0x1b, 0x00}, /* PSHFT */ 158262306a36Sopenharmony_ci {OV7670_R1E_MVFP, 0x01}, 158362306a36Sopenharmony_ci {0x29, 0x3c}, /* RSVD */ 158462306a36Sopenharmony_ci {0x33, 0x00}, /* CHLF */ 158562306a36Sopenharmony_ci {0x34, 0x07}, /* ARBLM */ 158662306a36Sopenharmony_ci {0x35, 0x84}, /* RSVD */ 158762306a36Sopenharmony_ci {0x36, 0x00}, /* RSVD */ 158862306a36Sopenharmony_ci {0x37, 0x04}, /* ADC */ 158962306a36Sopenharmony_ci {0x39, 0x43}, /* OFON */ 159062306a36Sopenharmony_ci {OV7670_R3A_TSLB, 0x00}, 159162306a36Sopenharmony_ci {OV7670_R3C_COM12, 0x6c}, 159262306a36Sopenharmony_ci {OV7670_R3D_COM13, 0x98}, 159362306a36Sopenharmony_ci {OV7670_R3F_EDGE, 0x23}, 159462306a36Sopenharmony_ci {OV7670_R40_COM15, 0xc1}, 159562306a36Sopenharmony_ci {OV7670_R41_COM16, 0x22}, 159662306a36Sopenharmony_ci {0x6b, 0x0a}, /* DBLV */ 159762306a36Sopenharmony_ci {0xa1, 0x08}, /* RSVD */ 159862306a36Sopenharmony_ci {0x69, 0x80}, /* HV */ 159962306a36Sopenharmony_ci {0x43, 0xf0}, /* RSVD.. */ 160062306a36Sopenharmony_ci {0x44, 0x10}, 160162306a36Sopenharmony_ci {0x45, 0x78}, 160262306a36Sopenharmony_ci {0x46, 0xa8}, 160362306a36Sopenharmony_ci {0x47, 0x60}, 160462306a36Sopenharmony_ci {0x48, 0x80}, 160562306a36Sopenharmony_ci {0x59, 0xba}, 160662306a36Sopenharmony_ci {0x5a, 0x9a}, 160762306a36Sopenharmony_ci {0x5b, 0x22}, 160862306a36Sopenharmony_ci {0x5c, 0xb9}, 160962306a36Sopenharmony_ci {0x5d, 0x9b}, 161062306a36Sopenharmony_ci {0x5e, 0x10}, 161162306a36Sopenharmony_ci {0x5f, 0xe0}, 161262306a36Sopenharmony_ci {0x60, 0x85}, 161362306a36Sopenharmony_ci {0x61, 0x60}, 161462306a36Sopenharmony_ci {0x9f, 0x9d}, /* RSVD */ 161562306a36Sopenharmony_ci {0xa0, 0xa0}, /* DSPC2 */ 161662306a36Sopenharmony_ci {0x4f, 0x60}, /* matrix */ 161762306a36Sopenharmony_ci {0x50, 0x64}, 161862306a36Sopenharmony_ci {0x51, 0x04}, 161962306a36Sopenharmony_ci {0x52, 0x18}, 162062306a36Sopenharmony_ci {0x53, 0x3c}, 162162306a36Sopenharmony_ci {0x54, 0x54}, 162262306a36Sopenharmony_ci {0x55, 0x40}, 162362306a36Sopenharmony_ci {0x56, 0x40}, 162462306a36Sopenharmony_ci {0x57, 0x40}, 162562306a36Sopenharmony_ci {0x58, 0x0d}, /* matrix sign */ 162662306a36Sopenharmony_ci {0x8b, 0xcc}, /* RSVD */ 162762306a36Sopenharmony_ci {0x8c, 0xcc}, 162862306a36Sopenharmony_ci {0x8d, 0xcf}, 162962306a36Sopenharmony_ci {0x6c, 0x40}, /* gamma curve */ 163062306a36Sopenharmony_ci {0x6d, 0xe0}, 163162306a36Sopenharmony_ci {0x6e, 0xa0}, 163262306a36Sopenharmony_ci {0x6f, 0x80}, 163362306a36Sopenharmony_ci {0x70, 0x70}, 163462306a36Sopenharmony_ci {0x71, 0x80}, 163562306a36Sopenharmony_ci {0x72, 0x60}, 163662306a36Sopenharmony_ci {0x73, 0x60}, 163762306a36Sopenharmony_ci {0x74, 0x50}, 163862306a36Sopenharmony_ci {0x75, 0x40}, 163962306a36Sopenharmony_ci {0x76, 0x38}, 164062306a36Sopenharmony_ci {0x77, 0x3c}, 164162306a36Sopenharmony_ci {0x78, 0x32}, 164262306a36Sopenharmony_ci {0x79, 0x1a}, 164362306a36Sopenharmony_ci {0x7a, 0x28}, 164462306a36Sopenharmony_ci {0x7b, 0x24}, 164562306a36Sopenharmony_ci {0x7c, 0x04}, /* gamma curve */ 164662306a36Sopenharmony_ci {0x7d, 0x12}, 164762306a36Sopenharmony_ci {0x7e, 0x26}, 164862306a36Sopenharmony_ci {0x7f, 0x46}, 164962306a36Sopenharmony_ci {0x80, 0x54}, 165062306a36Sopenharmony_ci {0x81, 0x64}, 165162306a36Sopenharmony_ci {0x82, 0x70}, 165262306a36Sopenharmony_ci {0x83, 0x7c}, 165362306a36Sopenharmony_ci {0x84, 0x86}, 165462306a36Sopenharmony_ci {0x85, 0x8e}, 165562306a36Sopenharmony_ci {0x86, 0x9c}, 165662306a36Sopenharmony_ci {0x87, 0xab}, 165762306a36Sopenharmony_ci {0x88, 0xc4}, 165862306a36Sopenharmony_ci {0x89, 0xd1}, 165962306a36Sopenharmony_ci {0x8a, 0xe5}, 166062306a36Sopenharmony_ci {OV7670_R14_COM9, 0x1e}, 166162306a36Sopenharmony_ci {OV7670_R24_AEW, 0x80}, 166262306a36Sopenharmony_ci {OV7670_R25_AEB, 0x72}, 166362306a36Sopenharmony_ci {OV7670_R26_VPT, 0xb3}, 166462306a36Sopenharmony_ci {0x62, 0x80}, /* LCC1 */ 166562306a36Sopenharmony_ci {0x63, 0x80}, /* LCC2 */ 166662306a36Sopenharmony_ci {0x64, 0x06}, /* LCC3 */ 166762306a36Sopenharmony_ci {0x65, 0x00}, /* LCC4 */ 166862306a36Sopenharmony_ci {0x66, 0x01}, /* LCC5 */ 166962306a36Sopenharmony_ci {0x94, 0x0e}, /* RSVD.. */ 167062306a36Sopenharmony_ci {0x95, 0x14}, 167162306a36Sopenharmony_ci {OV7670_R13_COM8, OV7670_COM8_FASTAEC 167262306a36Sopenharmony_ci | OV7670_COM8_AECSTEP 167362306a36Sopenharmony_ci | OV7670_COM8_BFILT 167462306a36Sopenharmony_ci | 0x10 167562306a36Sopenharmony_ci | OV7670_COM8_AGC 167662306a36Sopenharmony_ci | OV7670_COM8_AWB 167762306a36Sopenharmony_ci | OV7670_COM8_AEC}, 167862306a36Sopenharmony_ci {0xa1, 0xc8} 167962306a36Sopenharmony_ci}; 168062306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_9600[] = { 168162306a36Sopenharmony_ci {0x12, 0x80}, 168262306a36Sopenharmony_ci {0x0c, 0x28}, 168362306a36Sopenharmony_ci {0x11, 0x80}, 168462306a36Sopenharmony_ci {0x13, 0xb5}, 168562306a36Sopenharmony_ci {0x14, 0x3e}, 168662306a36Sopenharmony_ci {0x1b, 0x04}, 168762306a36Sopenharmony_ci {0x24, 0xb0}, 168862306a36Sopenharmony_ci {0x25, 0x90}, 168962306a36Sopenharmony_ci {0x26, 0x94}, 169062306a36Sopenharmony_ci {0x35, 0x90}, 169162306a36Sopenharmony_ci {0x37, 0x07}, 169262306a36Sopenharmony_ci {0x38, 0x08}, 169362306a36Sopenharmony_ci {0x01, 0x8e}, 169462306a36Sopenharmony_ci {0x02, 0x85} 169562306a36Sopenharmony_ci}; 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci/* 7670. Defaults taken from OmniVision provided data, 169862306a36Sopenharmony_ci* as provided by Jonathan Corbet of OLPC */ 169962306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7670[] = { 170062306a36Sopenharmony_ci { OV7670_R12_COM7, OV7670_COM7_RESET }, 170162306a36Sopenharmony_ci { OV7670_R3A_TSLB, 0x04 }, /* OV */ 170262306a36Sopenharmony_ci { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ 170362306a36Sopenharmony_ci { OV7670_R11_CLKRC, 0x01 }, 170462306a36Sopenharmony_ci/* 170562306a36Sopenharmony_ci * Set the hardware window. These values from OV don't entirely 170662306a36Sopenharmony_ci * make sense - hstop is less than hstart. But they work... 170762306a36Sopenharmony_ci */ 170862306a36Sopenharmony_ci { OV7670_R17_HSTART, 0x13 }, 170962306a36Sopenharmony_ci { OV7670_R18_HSTOP, 0x01 }, 171062306a36Sopenharmony_ci { OV7670_R32_HREF, 0xb6 }, 171162306a36Sopenharmony_ci { OV7670_R19_VSTART, 0x02 }, 171262306a36Sopenharmony_ci { OV7670_R1A_VSTOP, 0x7a }, 171362306a36Sopenharmony_ci { OV7670_R03_VREF, 0x0a }, 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci { OV7670_R0C_COM3, 0x00 }, 171662306a36Sopenharmony_ci { OV7670_R3E_COM14, 0x00 }, 171762306a36Sopenharmony_ci/* Mystery scaling numbers */ 171862306a36Sopenharmony_ci { 0x70, 0x3a }, 171962306a36Sopenharmony_ci { 0x71, 0x35 }, 172062306a36Sopenharmony_ci { 0x72, 0x11 }, 172162306a36Sopenharmony_ci { 0x73, 0xf0 }, 172262306a36Sopenharmony_ci { 0xa2, 0x02 }, 172362306a36Sopenharmony_ci/* { OV7670_R15_COM10, 0x0 }, */ 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci/* Gamma curve values */ 172662306a36Sopenharmony_ci { 0x7a, 0x20 }, 172762306a36Sopenharmony_ci { 0x7b, 0x10 }, 172862306a36Sopenharmony_ci { 0x7c, 0x1e }, 172962306a36Sopenharmony_ci { 0x7d, 0x35 }, 173062306a36Sopenharmony_ci { 0x7e, 0x5a }, 173162306a36Sopenharmony_ci { 0x7f, 0x69 }, 173262306a36Sopenharmony_ci { 0x80, 0x76 }, 173362306a36Sopenharmony_ci { 0x81, 0x80 }, 173462306a36Sopenharmony_ci { 0x82, 0x88 }, 173562306a36Sopenharmony_ci { 0x83, 0x8f }, 173662306a36Sopenharmony_ci { 0x84, 0x96 }, 173762306a36Sopenharmony_ci { 0x85, 0xa3 }, 173862306a36Sopenharmony_ci { 0x86, 0xaf }, 173962306a36Sopenharmony_ci { 0x87, 0xc4 }, 174062306a36Sopenharmony_ci { 0x88, 0xd7 }, 174162306a36Sopenharmony_ci { 0x89, 0xe8 }, 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci/* AGC and AEC parameters. Note we start by disabling those features, 174462306a36Sopenharmony_ci then turn them only after tweaking the values. */ 174562306a36Sopenharmony_ci { OV7670_R13_COM8, OV7670_COM8_FASTAEC 174662306a36Sopenharmony_ci | OV7670_COM8_AECSTEP 174762306a36Sopenharmony_ci | OV7670_COM8_BFILT }, 174862306a36Sopenharmony_ci { OV7670_R00_GAIN, 0x00 }, 174962306a36Sopenharmony_ci { OV7670_R10_AECH, 0x00 }, 175062306a36Sopenharmony_ci { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */ 175162306a36Sopenharmony_ci { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ 175262306a36Sopenharmony_ci { OV7670_RA5_BD50MAX, 0x05 }, 175362306a36Sopenharmony_ci { OV7670_RAB_BD60MAX, 0x07 }, 175462306a36Sopenharmony_ci { OV7670_R24_AEW, 0x95 }, 175562306a36Sopenharmony_ci { OV7670_R25_AEB, 0x33 }, 175662306a36Sopenharmony_ci { OV7670_R26_VPT, 0xe3 }, 175762306a36Sopenharmony_ci { OV7670_R9F_HAECC1, 0x78 }, 175862306a36Sopenharmony_ci { OV7670_RA0_HAECC2, 0x68 }, 175962306a36Sopenharmony_ci { 0xa1, 0x03 }, /* magic */ 176062306a36Sopenharmony_ci { OV7670_RA6_HAECC3, 0xd8 }, 176162306a36Sopenharmony_ci { OV7670_RA7_HAECC4, 0xd8 }, 176262306a36Sopenharmony_ci { OV7670_RA8_HAECC5, 0xf0 }, 176362306a36Sopenharmony_ci { OV7670_RA9_HAECC6, 0x90 }, 176462306a36Sopenharmony_ci { OV7670_RAA_HAECC7, 0x94 }, 176562306a36Sopenharmony_ci { OV7670_R13_COM8, OV7670_COM8_FASTAEC 176662306a36Sopenharmony_ci | OV7670_COM8_AECSTEP 176762306a36Sopenharmony_ci | OV7670_COM8_BFILT 176862306a36Sopenharmony_ci | OV7670_COM8_AGC 176962306a36Sopenharmony_ci | OV7670_COM8_AEC }, 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci/* Almost all of these are magic "reserved" values. */ 177262306a36Sopenharmony_ci { OV7670_R0E_COM5, 0x61 }, 177362306a36Sopenharmony_ci { OV7670_R0F_COM6, 0x4b }, 177462306a36Sopenharmony_ci { 0x16, 0x02 }, 177562306a36Sopenharmony_ci { OV7670_R1E_MVFP, 0x07 }, 177662306a36Sopenharmony_ci { 0x21, 0x02 }, 177762306a36Sopenharmony_ci { 0x22, 0x91 }, 177862306a36Sopenharmony_ci { 0x29, 0x07 }, 177962306a36Sopenharmony_ci { 0x33, 0x0b }, 178062306a36Sopenharmony_ci { 0x35, 0x0b }, 178162306a36Sopenharmony_ci { 0x37, 0x1d }, 178262306a36Sopenharmony_ci { 0x38, 0x71 }, 178362306a36Sopenharmony_ci { 0x39, 0x2a }, 178462306a36Sopenharmony_ci { OV7670_R3C_COM12, 0x78 }, 178562306a36Sopenharmony_ci { 0x4d, 0x40 }, 178662306a36Sopenharmony_ci { 0x4e, 0x20 }, 178762306a36Sopenharmony_ci { OV7670_R69_GFIX, 0x00 }, 178862306a36Sopenharmony_ci { 0x6b, 0x4a }, 178962306a36Sopenharmony_ci { 0x74, 0x10 }, 179062306a36Sopenharmony_ci { 0x8d, 0x4f }, 179162306a36Sopenharmony_ci { 0x8e, 0x00 }, 179262306a36Sopenharmony_ci { 0x8f, 0x00 }, 179362306a36Sopenharmony_ci { 0x90, 0x00 }, 179462306a36Sopenharmony_ci { 0x91, 0x00 }, 179562306a36Sopenharmony_ci { 0x96, 0x00 }, 179662306a36Sopenharmony_ci { 0x9a, 0x00 }, 179762306a36Sopenharmony_ci { 0xb0, 0x84 }, 179862306a36Sopenharmony_ci { 0xb1, 0x0c }, 179962306a36Sopenharmony_ci { 0xb2, 0x0e }, 180062306a36Sopenharmony_ci { 0xb3, 0x82 }, 180162306a36Sopenharmony_ci { 0xb8, 0x0a }, 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci/* More reserved magic, some of which tweaks white balance */ 180462306a36Sopenharmony_ci { 0x43, 0x0a }, 180562306a36Sopenharmony_ci { 0x44, 0xf0 }, 180662306a36Sopenharmony_ci { 0x45, 0x34 }, 180762306a36Sopenharmony_ci { 0x46, 0x58 }, 180862306a36Sopenharmony_ci { 0x47, 0x28 }, 180962306a36Sopenharmony_ci { 0x48, 0x3a }, 181062306a36Sopenharmony_ci { 0x59, 0x88 }, 181162306a36Sopenharmony_ci { 0x5a, 0x88 }, 181262306a36Sopenharmony_ci { 0x5b, 0x44 }, 181362306a36Sopenharmony_ci { 0x5c, 0x67 }, 181462306a36Sopenharmony_ci { 0x5d, 0x49 }, 181562306a36Sopenharmony_ci { 0x5e, 0x0e }, 181662306a36Sopenharmony_ci { 0x6c, 0x0a }, 181762306a36Sopenharmony_ci { 0x6d, 0x55 }, 181862306a36Sopenharmony_ci { 0x6e, 0x11 }, 181962306a36Sopenharmony_ci { 0x6f, 0x9f }, /* "9e for advance AWB" */ 182062306a36Sopenharmony_ci { 0x6a, 0x40 }, 182162306a36Sopenharmony_ci { OV7670_R01_BLUE, 0x40 }, 182262306a36Sopenharmony_ci { OV7670_R02_RED, 0x60 }, 182362306a36Sopenharmony_ci { OV7670_R13_COM8, OV7670_COM8_FASTAEC 182462306a36Sopenharmony_ci | OV7670_COM8_AECSTEP 182562306a36Sopenharmony_ci | OV7670_COM8_BFILT 182662306a36Sopenharmony_ci | OV7670_COM8_AGC 182762306a36Sopenharmony_ci | OV7670_COM8_AEC 182862306a36Sopenharmony_ci | OV7670_COM8_AWB }, 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci/* Matrix coefficients */ 183162306a36Sopenharmony_ci { 0x4f, 0x80 }, 183262306a36Sopenharmony_ci { 0x50, 0x80 }, 183362306a36Sopenharmony_ci { 0x51, 0x00 }, 183462306a36Sopenharmony_ci { 0x52, 0x22 }, 183562306a36Sopenharmony_ci { 0x53, 0x5e }, 183662306a36Sopenharmony_ci { 0x54, 0x80 }, 183762306a36Sopenharmony_ci { 0x58, 0x9e }, 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci { OV7670_R41_COM16, OV7670_COM16_AWBGAIN }, 184062306a36Sopenharmony_ci { OV7670_R3F_EDGE, 0x00 }, 184162306a36Sopenharmony_ci { 0x75, 0x05 }, 184262306a36Sopenharmony_ci { 0x76, 0xe1 }, 184362306a36Sopenharmony_ci { 0x4c, 0x00 }, 184462306a36Sopenharmony_ci { 0x77, 0x01 }, 184562306a36Sopenharmony_ci { OV7670_R3D_COM13, OV7670_COM13_GAMMA 184662306a36Sopenharmony_ci | OV7670_COM13_UVSAT 184762306a36Sopenharmony_ci | 2}, /* was 3 */ 184862306a36Sopenharmony_ci { 0x4b, 0x09 }, 184962306a36Sopenharmony_ci { 0xc9, 0x60 }, 185062306a36Sopenharmony_ci { OV7670_R41_COM16, 0x38 }, 185162306a36Sopenharmony_ci { 0x56, 0x40 }, 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci { 0x34, 0x11 }, 185462306a36Sopenharmony_ci { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, 185562306a36Sopenharmony_ci { 0xa4, 0x88 }, 185662306a36Sopenharmony_ci { 0x96, 0x00 }, 185762306a36Sopenharmony_ci { 0x97, 0x30 }, 185862306a36Sopenharmony_ci { 0x98, 0x20 }, 185962306a36Sopenharmony_ci { 0x99, 0x30 }, 186062306a36Sopenharmony_ci { 0x9a, 0x84 }, 186162306a36Sopenharmony_ci { 0x9b, 0x29 }, 186262306a36Sopenharmony_ci { 0x9c, 0x03 }, 186362306a36Sopenharmony_ci { 0x9d, 0x4c }, 186462306a36Sopenharmony_ci { 0x9e, 0x3f }, 186562306a36Sopenharmony_ci { 0x78, 0x04 }, 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci/* Extra-weird stuff. Some sort of multiplexor register */ 186862306a36Sopenharmony_ci { 0x79, 0x01 }, 186962306a36Sopenharmony_ci { 0xc8, 0xf0 }, 187062306a36Sopenharmony_ci { 0x79, 0x0f }, 187162306a36Sopenharmony_ci { 0xc8, 0x00 }, 187262306a36Sopenharmony_ci { 0x79, 0x10 }, 187362306a36Sopenharmony_ci { 0xc8, 0x7e }, 187462306a36Sopenharmony_ci { 0x79, 0x0a }, 187562306a36Sopenharmony_ci { 0xc8, 0x80 }, 187662306a36Sopenharmony_ci { 0x79, 0x0b }, 187762306a36Sopenharmony_ci { 0xc8, 0x01 }, 187862306a36Sopenharmony_ci { 0x79, 0x0c }, 187962306a36Sopenharmony_ci { 0xc8, 0x0f }, 188062306a36Sopenharmony_ci { 0x79, 0x0d }, 188162306a36Sopenharmony_ci { 0xc8, 0x20 }, 188262306a36Sopenharmony_ci { 0x79, 0x09 }, 188362306a36Sopenharmony_ci { 0xc8, 0x80 }, 188462306a36Sopenharmony_ci { 0x79, 0x02 }, 188562306a36Sopenharmony_ci { 0xc8, 0xc0 }, 188662306a36Sopenharmony_ci { 0x79, 0x03 }, 188762306a36Sopenharmony_ci { 0xc8, 0x40 }, 188862306a36Sopenharmony_ci { 0x79, 0x05 }, 188962306a36Sopenharmony_ci { 0xc8, 0x30 }, 189062306a36Sopenharmony_ci { 0x79, 0x26 }, 189162306a36Sopenharmony_ci}; 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_8610[] = { 189462306a36Sopenharmony_ci { 0x12, 0x80 }, 189562306a36Sopenharmony_ci { 0x00, 0x00 }, 189662306a36Sopenharmony_ci { 0x01, 0x80 }, 189762306a36Sopenharmony_ci { 0x02, 0x80 }, 189862306a36Sopenharmony_ci { 0x03, 0xc0 }, 189962306a36Sopenharmony_ci { 0x04, 0x30 }, 190062306a36Sopenharmony_ci { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */ 190162306a36Sopenharmony_ci { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */ 190262306a36Sopenharmony_ci { 0x0a, 0x86 }, 190362306a36Sopenharmony_ci { 0x0b, 0xb0 }, 190462306a36Sopenharmony_ci { 0x0c, 0x20 }, 190562306a36Sopenharmony_ci { 0x0d, 0x20 }, 190662306a36Sopenharmony_ci { 0x11, 0x01 }, 190762306a36Sopenharmony_ci { 0x12, 0x25 }, 190862306a36Sopenharmony_ci { 0x13, 0x01 }, 190962306a36Sopenharmony_ci { 0x14, 0x04 }, 191062306a36Sopenharmony_ci { 0x15, 0x01 }, /* Lin and Win think different about UV order */ 191162306a36Sopenharmony_ci { 0x16, 0x03 }, 191262306a36Sopenharmony_ci { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */ 191362306a36Sopenharmony_ci { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */ 191462306a36Sopenharmony_ci { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */ 191562306a36Sopenharmony_ci { 0x1a, 0xf5 }, 191662306a36Sopenharmony_ci { 0x1b, 0x00 }, 191762306a36Sopenharmony_ci { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */ 191862306a36Sopenharmony_ci { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */ 191962306a36Sopenharmony_ci { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */ 192062306a36Sopenharmony_ci { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */ 192162306a36Sopenharmony_ci { 0x26, 0xa2 }, 192262306a36Sopenharmony_ci { 0x27, 0xea }, 192362306a36Sopenharmony_ci { 0x28, 0x00 }, 192462306a36Sopenharmony_ci { 0x29, 0x00 }, 192562306a36Sopenharmony_ci { 0x2a, 0x80 }, 192662306a36Sopenharmony_ci { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */ 192762306a36Sopenharmony_ci { 0x2c, 0xac }, 192862306a36Sopenharmony_ci { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */ 192962306a36Sopenharmony_ci { 0x2e, 0x80 }, 193062306a36Sopenharmony_ci { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */ 193162306a36Sopenharmony_ci { 0x4c, 0x00 }, 193262306a36Sopenharmony_ci { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */ 193362306a36Sopenharmony_ci { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */ 193462306a36Sopenharmony_ci { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */ 193562306a36Sopenharmony_ci { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */ 193662306a36Sopenharmony_ci { 0x63, 0xff }, 193762306a36Sopenharmony_ci { 0x64, 0x53 }, /* new windrv 090403 says 0x57, 193862306a36Sopenharmony_ci * maybe that's wrong */ 193962306a36Sopenharmony_ci { 0x65, 0x00 }, 194062306a36Sopenharmony_ci { 0x66, 0x55 }, 194162306a36Sopenharmony_ci { 0x67, 0xb0 }, 194262306a36Sopenharmony_ci { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */ 194362306a36Sopenharmony_ci { 0x69, 0x02 }, 194462306a36Sopenharmony_ci { 0x6a, 0x22 }, 194562306a36Sopenharmony_ci { 0x6b, 0x00 }, 194662306a36Sopenharmony_ci { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but 194762306a36Sopenharmony_ci * deleting bit7 colors the first images red */ 194862306a36Sopenharmony_ci { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */ 194962306a36Sopenharmony_ci { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */ 195062306a36Sopenharmony_ci { 0x6f, 0x01 }, 195162306a36Sopenharmony_ci { 0x70, 0x8b }, 195262306a36Sopenharmony_ci { 0x71, 0x00 }, 195362306a36Sopenharmony_ci { 0x72, 0x14 }, 195462306a36Sopenharmony_ci { 0x73, 0x54 }, 195562306a36Sopenharmony_ci { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */ 195662306a36Sopenharmony_ci { 0x75, 0x0e }, 195762306a36Sopenharmony_ci { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */ 195862306a36Sopenharmony_ci { 0x77, 0xff }, 195962306a36Sopenharmony_ci { 0x78, 0x80 }, 196062306a36Sopenharmony_ci { 0x79, 0x80 }, 196162306a36Sopenharmony_ci { 0x7a, 0x80 }, 196262306a36Sopenharmony_ci { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */ 196362306a36Sopenharmony_ci { 0x7c, 0x00 }, 196462306a36Sopenharmony_ci { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */ 196562306a36Sopenharmony_ci { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */ 196662306a36Sopenharmony_ci { 0x7f, 0xfb }, 196762306a36Sopenharmony_ci { 0x80, 0x28 }, 196862306a36Sopenharmony_ci { 0x81, 0x00 }, 196962306a36Sopenharmony_ci { 0x82, 0x23 }, 197062306a36Sopenharmony_ci { 0x83, 0x0b }, 197162306a36Sopenharmony_ci { 0x84, 0x00 }, 197262306a36Sopenharmony_ci { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */ 197362306a36Sopenharmony_ci { 0x86, 0xc9 }, 197462306a36Sopenharmony_ci { 0x87, 0x00 }, 197562306a36Sopenharmony_ci { 0x88, 0x00 }, 197662306a36Sopenharmony_ci { 0x89, 0x01 }, 197762306a36Sopenharmony_ci { 0x12, 0x20 }, 197862306a36Sopenharmony_ci { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */ 197962306a36Sopenharmony_ci}; 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_cistatic unsigned char ov7670_abs_to_sm(unsigned char v) 198262306a36Sopenharmony_ci{ 198362306a36Sopenharmony_ci if (v > 127) 198462306a36Sopenharmony_ci return v & 0x7f; 198562306a36Sopenharmony_ci return (128 - v) | 0x80; 198662306a36Sopenharmony_ci} 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci/* Write a OV519 register */ 198962306a36Sopenharmony_cistatic void reg_w(struct sd *sd, u16 index, u16 value) 199062306a36Sopenharmony_ci{ 199162306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 199262306a36Sopenharmony_ci int ret, req = 0; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 199562306a36Sopenharmony_ci return; 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 199862306a36Sopenharmony_ci udelay(150); 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci switch (sd->bridge) { 200162306a36Sopenharmony_ci case BRIDGE_OV511: 200262306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 200362306a36Sopenharmony_ci req = 2; 200462306a36Sopenharmony_ci break; 200562306a36Sopenharmony_ci case BRIDGE_OVFX2: 200662306a36Sopenharmony_ci req = 0x0a; 200762306a36Sopenharmony_ci fallthrough; 200862306a36Sopenharmony_ci case BRIDGE_W9968CF: 200962306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "SET %02x %04x %04x\n", 201062306a36Sopenharmony_ci req, value, index); 201162306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 201262306a36Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 201362306a36Sopenharmony_ci req, 201462306a36Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 201562306a36Sopenharmony_ci value, index, NULL, 0, 500); 201662306a36Sopenharmony_ci goto leave; 201762306a36Sopenharmony_ci default: 201862306a36Sopenharmony_ci req = 1; 201962306a36Sopenharmony_ci } 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "SET %02x 0000 %04x %02x\n", 202262306a36Sopenharmony_ci req, index, value); 202362306a36Sopenharmony_ci sd->gspca_dev.usb_buf[0] = value; 202462306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 202562306a36Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 202662306a36Sopenharmony_ci req, 202762306a36Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 202862306a36Sopenharmony_ci 0, index, 202962306a36Sopenharmony_ci sd->gspca_dev.usb_buf, 1, 500); 203062306a36Sopenharmony_cileave: 203162306a36Sopenharmony_ci if (ret < 0) { 203262306a36Sopenharmony_ci gspca_err(gspca_dev, "reg_w %02x failed %d\n", index, ret); 203362306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 203462306a36Sopenharmony_ci return; 203562306a36Sopenharmony_ci } 203662306a36Sopenharmony_ci} 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci/* Read from a OV519 register, note not valid for the w9968cf!! */ 203962306a36Sopenharmony_ci/* returns: negative is error, pos or zero is data */ 204062306a36Sopenharmony_cistatic int reg_r(struct sd *sd, u16 index) 204162306a36Sopenharmony_ci{ 204262306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 204362306a36Sopenharmony_ci int ret; 204462306a36Sopenharmony_ci int req; 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 204762306a36Sopenharmony_ci return -1; 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci switch (sd->bridge) { 205062306a36Sopenharmony_ci case BRIDGE_OV511: 205162306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 205262306a36Sopenharmony_ci req = 3; 205362306a36Sopenharmony_ci break; 205462306a36Sopenharmony_ci case BRIDGE_OVFX2: 205562306a36Sopenharmony_ci req = 0x0b; 205662306a36Sopenharmony_ci break; 205762306a36Sopenharmony_ci default: 205862306a36Sopenharmony_ci req = 1; 205962306a36Sopenharmony_ci } 206062306a36Sopenharmony_ci 206162306a36Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 206262306a36Sopenharmony_ci udelay(150); 206362306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 206462306a36Sopenharmony_ci usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 206562306a36Sopenharmony_ci req, 206662306a36Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 206762306a36Sopenharmony_ci 0, index, sd->gspca_dev.usb_buf, 1, 500); 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci if (ret >= 0) { 207062306a36Sopenharmony_ci ret = sd->gspca_dev.usb_buf[0]; 207162306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "GET %02x 0000 %04x %02x\n", 207262306a36Sopenharmony_ci req, index, ret); 207362306a36Sopenharmony_ci } else { 207462306a36Sopenharmony_ci gspca_err(gspca_dev, "reg_r %02x failed %d\n", index, ret); 207562306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 207662306a36Sopenharmony_ci /* 207762306a36Sopenharmony_ci * Make sure the result is zeroed to avoid uninitialized 207862306a36Sopenharmony_ci * values. 207962306a36Sopenharmony_ci */ 208062306a36Sopenharmony_ci gspca_dev->usb_buf[0] = 0; 208162306a36Sopenharmony_ci } 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_ci return ret; 208462306a36Sopenharmony_ci} 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_ci/* Read 8 values from a OV519 register */ 208762306a36Sopenharmony_cistatic int reg_r8(struct sd *sd, 208862306a36Sopenharmony_ci u16 index) 208962306a36Sopenharmony_ci{ 209062306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 209162306a36Sopenharmony_ci int ret; 209262306a36Sopenharmony_ci 209362306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 209462306a36Sopenharmony_ci return -1; 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 209762306a36Sopenharmony_ci udelay(150); 209862306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 209962306a36Sopenharmony_ci usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 210062306a36Sopenharmony_ci 1, /* REQ_IO */ 210162306a36Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 210262306a36Sopenharmony_ci 0, index, sd->gspca_dev.usb_buf, 8, 500); 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci if (ret >= 0) { 210562306a36Sopenharmony_ci ret = sd->gspca_dev.usb_buf[0]; 210662306a36Sopenharmony_ci } else { 210762306a36Sopenharmony_ci gspca_err(gspca_dev, "reg_r8 %02x failed %d\n", index, ret); 210862306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 210962306a36Sopenharmony_ci /* 211062306a36Sopenharmony_ci * Make sure the buffer is zeroed to avoid uninitialized 211162306a36Sopenharmony_ci * values. 211262306a36Sopenharmony_ci */ 211362306a36Sopenharmony_ci memset(gspca_dev->usb_buf, 0, 8); 211462306a36Sopenharmony_ci } 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci return ret; 211762306a36Sopenharmony_ci} 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci/* 212062306a36Sopenharmony_ci * Writes bits at positions specified by mask to an OV51x reg. Bits that are in 212162306a36Sopenharmony_ci * the same position as 1's in "mask" are cleared and set to "value". Bits 212262306a36Sopenharmony_ci * that are in the same position as 0's in "mask" are preserved, regardless 212362306a36Sopenharmony_ci * of their respective state in "value". 212462306a36Sopenharmony_ci */ 212562306a36Sopenharmony_cistatic void reg_w_mask(struct sd *sd, 212662306a36Sopenharmony_ci u16 index, 212762306a36Sopenharmony_ci u8 value, 212862306a36Sopenharmony_ci u8 mask) 212962306a36Sopenharmony_ci{ 213062306a36Sopenharmony_ci int ret; 213162306a36Sopenharmony_ci u8 oldval; 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci if (mask != 0xff) { 213462306a36Sopenharmony_ci value &= mask; /* Enforce mask on value */ 213562306a36Sopenharmony_ci ret = reg_r(sd, index); 213662306a36Sopenharmony_ci if (ret < 0) 213762306a36Sopenharmony_ci return; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci oldval = ret & ~mask; /* Clear the masked bits */ 214062306a36Sopenharmony_ci value |= oldval; /* Set the desired bits */ 214162306a36Sopenharmony_ci } 214262306a36Sopenharmony_ci reg_w(sd, index, value); 214362306a36Sopenharmony_ci} 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_ci/* 214662306a36Sopenharmony_ci * Writes multiple (n) byte value to a single register. Only valid with certain 214762306a36Sopenharmony_ci * registers (0x30 and 0xc4 - 0xce). 214862306a36Sopenharmony_ci */ 214962306a36Sopenharmony_cistatic void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) 215062306a36Sopenharmony_ci{ 215162306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 215262306a36Sopenharmony_ci int ret; 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 215562306a36Sopenharmony_ci return; 215662306a36Sopenharmony_ci 215762306a36Sopenharmony_ci *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 216062306a36Sopenharmony_ci udelay(150); 216162306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 216262306a36Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 216362306a36Sopenharmony_ci 1 /* REG_IO */, 216462306a36Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 216562306a36Sopenharmony_ci 0, index, 216662306a36Sopenharmony_ci sd->gspca_dev.usb_buf, n, 500); 216762306a36Sopenharmony_ci if (ret < 0) { 216862306a36Sopenharmony_ci gspca_err(gspca_dev, "reg_w32 %02x failed %d\n", index, ret); 216962306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 217062306a36Sopenharmony_ci } 217162306a36Sopenharmony_ci} 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_cistatic void ov511_i2c_w(struct sd *sd, u8 reg, u8 value) 217462306a36Sopenharmony_ci{ 217562306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 217662306a36Sopenharmony_ci int rc, retries; 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "ov511_i2c_w %02x %02x\n", reg, value); 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_ci /* Three byte write cycle */ 218162306a36Sopenharmony_ci for (retries = 6; ; ) { 218262306a36Sopenharmony_ci /* Select camera register */ 218362306a36Sopenharmony_ci reg_w(sd, R51x_I2C_SADDR_3, reg); 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci /* Write "value" to I2C data port of OV511 */ 218662306a36Sopenharmony_ci reg_w(sd, R51x_I2C_DATA, value); 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci /* Initiate 3-byte write cycle */ 218962306a36Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x01); 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci do { 219262306a36Sopenharmony_ci rc = reg_r(sd, R511_I2C_CTL); 219362306a36Sopenharmony_ci } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci if (rc < 0) 219662306a36Sopenharmony_ci return; 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci if ((rc & 2) == 0) /* Ack? */ 219962306a36Sopenharmony_ci break; 220062306a36Sopenharmony_ci if (--retries < 0) { 220162306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "i2c write retries exhausted\n"); 220262306a36Sopenharmony_ci return; 220362306a36Sopenharmony_ci } 220462306a36Sopenharmony_ci } 220562306a36Sopenharmony_ci} 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_cistatic int ov511_i2c_r(struct sd *sd, u8 reg) 220862306a36Sopenharmony_ci{ 220962306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 221062306a36Sopenharmony_ci int rc, value, retries; 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_ci /* Two byte write cycle */ 221362306a36Sopenharmony_ci for (retries = 6; ; ) { 221462306a36Sopenharmony_ci /* Select camera register */ 221562306a36Sopenharmony_ci reg_w(sd, R51x_I2C_SADDR_2, reg); 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ci /* Initiate 2-byte write cycle */ 221862306a36Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x03); 221962306a36Sopenharmony_ci 222062306a36Sopenharmony_ci do { 222162306a36Sopenharmony_ci rc = reg_r(sd, R511_I2C_CTL); 222262306a36Sopenharmony_ci } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_ci if (rc < 0) 222562306a36Sopenharmony_ci return rc; 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_ci if ((rc & 2) == 0) /* Ack? */ 222862306a36Sopenharmony_ci break; 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci /* I2C abort */ 223162306a36Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x10); 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci if (--retries < 0) { 223462306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "i2c write retries exhausted\n"); 223562306a36Sopenharmony_ci return -1; 223662306a36Sopenharmony_ci } 223762306a36Sopenharmony_ci } 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci /* Two byte read cycle */ 224062306a36Sopenharmony_ci for (retries = 6; ; ) { 224162306a36Sopenharmony_ci /* Initiate 2-byte read cycle */ 224262306a36Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x05); 224362306a36Sopenharmony_ci 224462306a36Sopenharmony_ci do { 224562306a36Sopenharmony_ci rc = reg_r(sd, R511_I2C_CTL); 224662306a36Sopenharmony_ci } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci if (rc < 0) 224962306a36Sopenharmony_ci return rc; 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ci if ((rc & 2) == 0) /* Ack? */ 225262306a36Sopenharmony_ci break; 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci /* I2C abort */ 225562306a36Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x10); 225662306a36Sopenharmony_ci 225762306a36Sopenharmony_ci if (--retries < 0) { 225862306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "i2c read retries exhausted\n"); 225962306a36Sopenharmony_ci return -1; 226062306a36Sopenharmony_ci } 226162306a36Sopenharmony_ci } 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_ci value = reg_r(sd, R51x_I2C_DATA); 226462306a36Sopenharmony_ci 226562306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "ov511_i2c_r %02x %02x\n", reg, value); 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_ci /* This is needed to make i2c_w() work */ 226862306a36Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x05); 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci return value; 227162306a36Sopenharmony_ci} 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ci/* 227462306a36Sopenharmony_ci * The OV518 I2C I/O procedure is different, hence, this function. 227562306a36Sopenharmony_ci * This is normally only called from i2c_w(). Note that this function 227662306a36Sopenharmony_ci * always succeeds regardless of whether the sensor is present and working. 227762306a36Sopenharmony_ci */ 227862306a36Sopenharmony_cistatic void ov518_i2c_w(struct sd *sd, 227962306a36Sopenharmony_ci u8 reg, 228062306a36Sopenharmony_ci u8 value) 228162306a36Sopenharmony_ci{ 228262306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "ov518_i2c_w %02x %02x\n", reg, value); 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci /* Select camera register */ 228762306a36Sopenharmony_ci reg_w(sd, R51x_I2C_SADDR_3, reg); 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci /* Write "value" to I2C data port of OV511 */ 229062306a36Sopenharmony_ci reg_w(sd, R51x_I2C_DATA, value); 229162306a36Sopenharmony_ci 229262306a36Sopenharmony_ci /* Initiate 3-byte write cycle */ 229362306a36Sopenharmony_ci reg_w(sd, R518_I2C_CTL, 0x01); 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci /* wait for write complete */ 229662306a36Sopenharmony_ci msleep(4); 229762306a36Sopenharmony_ci reg_r8(sd, R518_I2C_CTL); 229862306a36Sopenharmony_ci} 229962306a36Sopenharmony_ci 230062306a36Sopenharmony_ci/* 230162306a36Sopenharmony_ci * returns: negative is error, pos or zero is data 230262306a36Sopenharmony_ci * 230362306a36Sopenharmony_ci * The OV518 I2C I/O procedure is different, hence, this function. 230462306a36Sopenharmony_ci * This is normally only called from i2c_r(). Note that this function 230562306a36Sopenharmony_ci * always succeeds regardless of whether the sensor is present and working. 230662306a36Sopenharmony_ci */ 230762306a36Sopenharmony_cistatic int ov518_i2c_r(struct sd *sd, u8 reg) 230862306a36Sopenharmony_ci{ 230962306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 231062306a36Sopenharmony_ci int value; 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci /* Select camera register */ 231362306a36Sopenharmony_ci reg_w(sd, R51x_I2C_SADDR_2, reg); 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_ci /* Initiate 2-byte write cycle */ 231662306a36Sopenharmony_ci reg_w(sd, R518_I2C_CTL, 0x03); 231762306a36Sopenharmony_ci reg_r8(sd, R518_I2C_CTL); 231862306a36Sopenharmony_ci 231962306a36Sopenharmony_ci /* Initiate 2-byte read cycle */ 232062306a36Sopenharmony_ci reg_w(sd, R518_I2C_CTL, 0x05); 232162306a36Sopenharmony_ci reg_r8(sd, R518_I2C_CTL); 232262306a36Sopenharmony_ci 232362306a36Sopenharmony_ci value = reg_r(sd, R51x_I2C_DATA); 232462306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "ov518_i2c_r %02x %02x\n", reg, value); 232562306a36Sopenharmony_ci return value; 232662306a36Sopenharmony_ci} 232762306a36Sopenharmony_ci 232862306a36Sopenharmony_cistatic void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) 232962306a36Sopenharmony_ci{ 233062306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 233162306a36Sopenharmony_ci int ret; 233262306a36Sopenharmony_ci 233362306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 233462306a36Sopenharmony_ci return; 233562306a36Sopenharmony_ci 233662306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 233762306a36Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 233862306a36Sopenharmony_ci 0x02, 233962306a36Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 234062306a36Sopenharmony_ci (u16) value, (u16) reg, NULL, 0, 500); 234162306a36Sopenharmony_ci 234262306a36Sopenharmony_ci if (ret < 0) { 234362306a36Sopenharmony_ci gspca_err(gspca_dev, "ovfx2_i2c_w %02x failed %d\n", reg, ret); 234462306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 234562306a36Sopenharmony_ci } 234662306a36Sopenharmony_ci 234762306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "ovfx2_i2c_w %02x %02x\n", reg, value); 234862306a36Sopenharmony_ci} 234962306a36Sopenharmony_ci 235062306a36Sopenharmony_cistatic int ovfx2_i2c_r(struct sd *sd, u8 reg) 235162306a36Sopenharmony_ci{ 235262306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 235362306a36Sopenharmony_ci int ret; 235462306a36Sopenharmony_ci 235562306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 235662306a36Sopenharmony_ci return -1; 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 235962306a36Sopenharmony_ci usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 236062306a36Sopenharmony_ci 0x03, 236162306a36Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 236262306a36Sopenharmony_ci 0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500); 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci if (ret >= 0) { 236562306a36Sopenharmony_ci ret = sd->gspca_dev.usb_buf[0]; 236662306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "ovfx2_i2c_r %02x %02x\n", 236762306a36Sopenharmony_ci reg, ret); 236862306a36Sopenharmony_ci } else { 236962306a36Sopenharmony_ci gspca_err(gspca_dev, "ovfx2_i2c_r %02x failed %d\n", reg, ret); 237062306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 237162306a36Sopenharmony_ci } 237262306a36Sopenharmony_ci 237362306a36Sopenharmony_ci return ret; 237462306a36Sopenharmony_ci} 237562306a36Sopenharmony_ci 237662306a36Sopenharmony_cistatic void i2c_w(struct sd *sd, u8 reg, u8 value) 237762306a36Sopenharmony_ci{ 237862306a36Sopenharmony_ci if (sd->sensor_reg_cache[reg] == value) 237962306a36Sopenharmony_ci return; 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci switch (sd->bridge) { 238262306a36Sopenharmony_ci case BRIDGE_OV511: 238362306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 238462306a36Sopenharmony_ci ov511_i2c_w(sd, reg, value); 238562306a36Sopenharmony_ci break; 238662306a36Sopenharmony_ci case BRIDGE_OV518: 238762306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 238862306a36Sopenharmony_ci case BRIDGE_OV519: 238962306a36Sopenharmony_ci ov518_i2c_w(sd, reg, value); 239062306a36Sopenharmony_ci break; 239162306a36Sopenharmony_ci case BRIDGE_OVFX2: 239262306a36Sopenharmony_ci ovfx2_i2c_w(sd, reg, value); 239362306a36Sopenharmony_ci break; 239462306a36Sopenharmony_ci case BRIDGE_W9968CF: 239562306a36Sopenharmony_ci w9968cf_i2c_w(sd, reg, value); 239662306a36Sopenharmony_ci break; 239762306a36Sopenharmony_ci } 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci if (sd->gspca_dev.usb_err >= 0) { 240062306a36Sopenharmony_ci /* Up on sensor reset empty the register cache */ 240162306a36Sopenharmony_ci if (reg == 0x12 && (value & 0x80)) 240262306a36Sopenharmony_ci memset(sd->sensor_reg_cache, -1, 240362306a36Sopenharmony_ci sizeof(sd->sensor_reg_cache)); 240462306a36Sopenharmony_ci else 240562306a36Sopenharmony_ci sd->sensor_reg_cache[reg] = value; 240662306a36Sopenharmony_ci } 240762306a36Sopenharmony_ci} 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_cistatic int i2c_r(struct sd *sd, u8 reg) 241062306a36Sopenharmony_ci{ 241162306a36Sopenharmony_ci int ret = -1; 241262306a36Sopenharmony_ci 241362306a36Sopenharmony_ci if (sd->sensor_reg_cache[reg] != -1) 241462306a36Sopenharmony_ci return sd->sensor_reg_cache[reg]; 241562306a36Sopenharmony_ci 241662306a36Sopenharmony_ci switch (sd->bridge) { 241762306a36Sopenharmony_ci case BRIDGE_OV511: 241862306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 241962306a36Sopenharmony_ci ret = ov511_i2c_r(sd, reg); 242062306a36Sopenharmony_ci break; 242162306a36Sopenharmony_ci case BRIDGE_OV518: 242262306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 242362306a36Sopenharmony_ci case BRIDGE_OV519: 242462306a36Sopenharmony_ci ret = ov518_i2c_r(sd, reg); 242562306a36Sopenharmony_ci break; 242662306a36Sopenharmony_ci case BRIDGE_OVFX2: 242762306a36Sopenharmony_ci ret = ovfx2_i2c_r(sd, reg); 242862306a36Sopenharmony_ci break; 242962306a36Sopenharmony_ci case BRIDGE_W9968CF: 243062306a36Sopenharmony_ci ret = w9968cf_i2c_r(sd, reg); 243162306a36Sopenharmony_ci break; 243262306a36Sopenharmony_ci } 243362306a36Sopenharmony_ci 243462306a36Sopenharmony_ci if (ret >= 0) 243562306a36Sopenharmony_ci sd->sensor_reg_cache[reg] = ret; 243662306a36Sopenharmony_ci 243762306a36Sopenharmony_ci return ret; 243862306a36Sopenharmony_ci} 243962306a36Sopenharmony_ci 244062306a36Sopenharmony_ci/* Writes bits at positions specified by mask to an I2C reg. Bits that are in 244162306a36Sopenharmony_ci * the same position as 1's in "mask" are cleared and set to "value". Bits 244262306a36Sopenharmony_ci * that are in the same position as 0's in "mask" are preserved, regardless 244362306a36Sopenharmony_ci * of their respective state in "value". 244462306a36Sopenharmony_ci */ 244562306a36Sopenharmony_cistatic void i2c_w_mask(struct sd *sd, 244662306a36Sopenharmony_ci u8 reg, 244762306a36Sopenharmony_ci u8 value, 244862306a36Sopenharmony_ci u8 mask) 244962306a36Sopenharmony_ci{ 245062306a36Sopenharmony_ci int rc; 245162306a36Sopenharmony_ci u8 oldval; 245262306a36Sopenharmony_ci 245362306a36Sopenharmony_ci value &= mask; /* Enforce mask on value */ 245462306a36Sopenharmony_ci rc = i2c_r(sd, reg); 245562306a36Sopenharmony_ci if (rc < 0) 245662306a36Sopenharmony_ci return; 245762306a36Sopenharmony_ci oldval = rc & ~mask; /* Clear the masked bits */ 245862306a36Sopenharmony_ci value |= oldval; /* Set the desired bits */ 245962306a36Sopenharmony_ci i2c_w(sd, reg, value); 246062306a36Sopenharmony_ci} 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ci/* Temporarily stops OV511 from functioning. Must do this before changing 246362306a36Sopenharmony_ci * registers while the camera is streaming */ 246462306a36Sopenharmony_cistatic inline void ov51x_stop(struct sd *sd) 246562306a36Sopenharmony_ci{ 246662306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 246762306a36Sopenharmony_ci 246862306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "stopping\n"); 246962306a36Sopenharmony_ci sd->stopped = 1; 247062306a36Sopenharmony_ci switch (sd->bridge) { 247162306a36Sopenharmony_ci case BRIDGE_OV511: 247262306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 247362306a36Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x3d); 247462306a36Sopenharmony_ci break; 247562306a36Sopenharmony_ci case BRIDGE_OV518: 247662306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 247762306a36Sopenharmony_ci reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); 247862306a36Sopenharmony_ci break; 247962306a36Sopenharmony_ci case BRIDGE_OV519: 248062306a36Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x0f); 248162306a36Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x00); 248262306a36Sopenharmony_ci reg_w(sd, 0x22, 0x00); /* FRAR */ 248362306a36Sopenharmony_ci break; 248462306a36Sopenharmony_ci case BRIDGE_OVFX2: 248562306a36Sopenharmony_ci reg_w_mask(sd, 0x0f, 0x00, 0x02); 248662306a36Sopenharmony_ci break; 248762306a36Sopenharmony_ci case BRIDGE_W9968CF: 248862306a36Sopenharmony_ci reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ 248962306a36Sopenharmony_ci break; 249062306a36Sopenharmony_ci } 249162306a36Sopenharmony_ci} 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_ci/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not 249462306a36Sopenharmony_ci * actually stopped (for performance). */ 249562306a36Sopenharmony_cistatic inline void ov51x_restart(struct sd *sd) 249662306a36Sopenharmony_ci{ 249762306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 249862306a36Sopenharmony_ci 249962306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "restarting\n"); 250062306a36Sopenharmony_ci if (!sd->stopped) 250162306a36Sopenharmony_ci return; 250262306a36Sopenharmony_ci sd->stopped = 0; 250362306a36Sopenharmony_ci 250462306a36Sopenharmony_ci /* Reinitialize the stream */ 250562306a36Sopenharmony_ci switch (sd->bridge) { 250662306a36Sopenharmony_ci case BRIDGE_OV511: 250762306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 250862306a36Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x00); 250962306a36Sopenharmony_ci break; 251062306a36Sopenharmony_ci case BRIDGE_OV518: 251162306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 251262306a36Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 251362306a36Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x00); 251462306a36Sopenharmony_ci break; 251562306a36Sopenharmony_ci case BRIDGE_OV519: 251662306a36Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x0f); 251762306a36Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x00); 251862306a36Sopenharmony_ci reg_w(sd, 0x22, 0x1d); /* FRAR */ 251962306a36Sopenharmony_ci break; 252062306a36Sopenharmony_ci case BRIDGE_OVFX2: 252162306a36Sopenharmony_ci reg_w_mask(sd, 0x0f, 0x02, 0x02); 252262306a36Sopenharmony_ci break; 252362306a36Sopenharmony_ci case BRIDGE_W9968CF: 252462306a36Sopenharmony_ci reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ 252562306a36Sopenharmony_ci break; 252662306a36Sopenharmony_ci } 252762306a36Sopenharmony_ci} 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_cistatic void ov51x_set_slave_ids(struct sd *sd, u8 slave); 253062306a36Sopenharmony_ci 253162306a36Sopenharmony_ci/* This does an initial reset of an OmniVision sensor and ensures that I2C 253262306a36Sopenharmony_ci * is synchronized. Returns <0 on failure. 253362306a36Sopenharmony_ci */ 253462306a36Sopenharmony_cistatic int init_ov_sensor(struct sd *sd, u8 slave) 253562306a36Sopenharmony_ci{ 253662306a36Sopenharmony_ci int i; 253762306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci ov51x_set_slave_ids(sd, slave); 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci /* Reset the sensor */ 254262306a36Sopenharmony_ci i2c_w(sd, 0x12, 0x80); 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_ci /* Wait for it to initialize */ 254562306a36Sopenharmony_ci msleep(150); 254662306a36Sopenharmony_ci 254762306a36Sopenharmony_ci for (i = 0; i < i2c_detect_tries; i++) { 254862306a36Sopenharmony_ci if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f && 254962306a36Sopenharmony_ci i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) { 255062306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "I2C synced in %d attempt(s)\n", 255162306a36Sopenharmony_ci i); 255262306a36Sopenharmony_ci return 0; 255362306a36Sopenharmony_ci } 255462306a36Sopenharmony_ci 255562306a36Sopenharmony_ci /* Reset the sensor */ 255662306a36Sopenharmony_ci i2c_w(sd, 0x12, 0x80); 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci /* Wait for it to initialize */ 255962306a36Sopenharmony_ci msleep(150); 256062306a36Sopenharmony_ci 256162306a36Sopenharmony_ci /* Dummy read to sync I2C */ 256262306a36Sopenharmony_ci if (i2c_r(sd, 0x00) < 0) 256362306a36Sopenharmony_ci return -1; 256462306a36Sopenharmony_ci } 256562306a36Sopenharmony_ci return -1; 256662306a36Sopenharmony_ci} 256762306a36Sopenharmony_ci 256862306a36Sopenharmony_ci/* Set the read and write slave IDs. The "slave" argument is the write slave, 256962306a36Sopenharmony_ci * and the read slave will be set to (slave + 1). 257062306a36Sopenharmony_ci * This should not be called from outside the i2c I/O functions. 257162306a36Sopenharmony_ci * Sets I2C read and write slave IDs. Returns <0 for error 257262306a36Sopenharmony_ci */ 257362306a36Sopenharmony_cistatic void ov51x_set_slave_ids(struct sd *sd, 257462306a36Sopenharmony_ci u8 slave) 257562306a36Sopenharmony_ci{ 257662306a36Sopenharmony_ci switch (sd->bridge) { 257762306a36Sopenharmony_ci case BRIDGE_OVFX2: 257862306a36Sopenharmony_ci reg_w(sd, OVFX2_I2C_ADDR, slave); 257962306a36Sopenharmony_ci return; 258062306a36Sopenharmony_ci case BRIDGE_W9968CF: 258162306a36Sopenharmony_ci sd->sensor_addr = slave; 258262306a36Sopenharmony_ci return; 258362306a36Sopenharmony_ci } 258462306a36Sopenharmony_ci 258562306a36Sopenharmony_ci reg_w(sd, R51x_I2C_W_SID, slave); 258662306a36Sopenharmony_ci reg_w(sd, R51x_I2C_R_SID, slave + 1); 258762306a36Sopenharmony_ci} 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_cistatic void write_regvals(struct sd *sd, 259062306a36Sopenharmony_ci const struct ov_regvals *regvals, 259162306a36Sopenharmony_ci int n) 259262306a36Sopenharmony_ci{ 259362306a36Sopenharmony_ci while (--n >= 0) { 259462306a36Sopenharmony_ci reg_w(sd, regvals->reg, regvals->val); 259562306a36Sopenharmony_ci regvals++; 259662306a36Sopenharmony_ci } 259762306a36Sopenharmony_ci} 259862306a36Sopenharmony_ci 259962306a36Sopenharmony_cistatic void write_i2c_regvals(struct sd *sd, 260062306a36Sopenharmony_ci const struct ov_i2c_regvals *regvals, 260162306a36Sopenharmony_ci int n) 260262306a36Sopenharmony_ci{ 260362306a36Sopenharmony_ci while (--n >= 0) { 260462306a36Sopenharmony_ci i2c_w(sd, regvals->reg, regvals->val); 260562306a36Sopenharmony_ci regvals++; 260662306a36Sopenharmony_ci } 260762306a36Sopenharmony_ci} 260862306a36Sopenharmony_ci 260962306a36Sopenharmony_ci/**************************************************************************** 261062306a36Sopenharmony_ci * 261162306a36Sopenharmony_ci * OV511 and sensor configuration 261262306a36Sopenharmony_ci * 261362306a36Sopenharmony_ci ***************************************************************************/ 261462306a36Sopenharmony_ci 261562306a36Sopenharmony_ci/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */ 261662306a36Sopenharmony_cistatic void ov_hires_configure(struct sd *sd) 261762306a36Sopenharmony_ci{ 261862306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 261962306a36Sopenharmony_ci int high, low; 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci if (sd->bridge != BRIDGE_OVFX2) { 262262306a36Sopenharmony_ci gspca_err(gspca_dev, "error hires sensors only supported with ovfx2\n"); 262362306a36Sopenharmony_ci return; 262462306a36Sopenharmony_ci } 262562306a36Sopenharmony_ci 262662306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "starting ov hires configuration\n"); 262762306a36Sopenharmony_ci 262862306a36Sopenharmony_ci /* Detect sensor (sub)type */ 262962306a36Sopenharmony_ci high = i2c_r(sd, 0x0a); 263062306a36Sopenharmony_ci low = i2c_r(sd, 0x0b); 263162306a36Sopenharmony_ci /* info("%x, %x", high, low); */ 263262306a36Sopenharmony_ci switch (high) { 263362306a36Sopenharmony_ci case 0x96: 263462306a36Sopenharmony_ci switch (low) { 263562306a36Sopenharmony_ci case 0x40: 263662306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV2610\n"); 263762306a36Sopenharmony_ci sd->sensor = SEN_OV2610; 263862306a36Sopenharmony_ci return; 263962306a36Sopenharmony_ci case 0x41: 264062306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV2610AE\n"); 264162306a36Sopenharmony_ci sd->sensor = SEN_OV2610AE; 264262306a36Sopenharmony_ci return; 264362306a36Sopenharmony_ci case 0xb1: 264462306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV9600\n"); 264562306a36Sopenharmony_ci sd->sensor = SEN_OV9600; 264662306a36Sopenharmony_ci return; 264762306a36Sopenharmony_ci } 264862306a36Sopenharmony_ci break; 264962306a36Sopenharmony_ci case 0x36: 265062306a36Sopenharmony_ci if ((low & 0x0f) == 0x00) { 265162306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV3610\n"); 265262306a36Sopenharmony_ci sd->sensor = SEN_OV3610; 265362306a36Sopenharmony_ci return; 265462306a36Sopenharmony_ci } 265562306a36Sopenharmony_ci break; 265662306a36Sopenharmony_ci } 265762306a36Sopenharmony_ci gspca_err(gspca_dev, "Error unknown sensor type: %02x%02x\n", 265862306a36Sopenharmony_ci high, low); 265962306a36Sopenharmony_ci} 266062306a36Sopenharmony_ci 266162306a36Sopenharmony_ci/* This initializes the OV8110, OV8610 sensor. The OV8110 uses 266262306a36Sopenharmony_ci * the same register settings as the OV8610, since they are very similar. 266362306a36Sopenharmony_ci */ 266462306a36Sopenharmony_cistatic void ov8xx0_configure(struct sd *sd) 266562306a36Sopenharmony_ci{ 266662306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 266762306a36Sopenharmony_ci int rc; 266862306a36Sopenharmony_ci 266962306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "starting ov8xx0 configuration\n"); 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci /* Detect sensor (sub)type */ 267262306a36Sopenharmony_ci rc = i2c_r(sd, OV7610_REG_COM_I); 267362306a36Sopenharmony_ci if (rc < 0) { 267462306a36Sopenharmony_ci gspca_err(gspca_dev, "Error detecting sensor type\n"); 267562306a36Sopenharmony_ci return; 267662306a36Sopenharmony_ci } 267762306a36Sopenharmony_ci if ((rc & 3) == 1) 267862306a36Sopenharmony_ci sd->sensor = SEN_OV8610; 267962306a36Sopenharmony_ci else 268062306a36Sopenharmony_ci gspca_err(gspca_dev, "Unknown image sensor version: %d\n", 268162306a36Sopenharmony_ci rc & 3); 268262306a36Sopenharmony_ci} 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses 268562306a36Sopenharmony_ci * the same register settings as the OV7610, since they are very similar. 268662306a36Sopenharmony_ci */ 268762306a36Sopenharmony_cistatic void ov7xx0_configure(struct sd *sd) 268862306a36Sopenharmony_ci{ 268962306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 269062306a36Sopenharmony_ci int rc, high, low; 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "starting OV7xx0 configuration\n"); 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci /* Detect sensor (sub)type */ 269562306a36Sopenharmony_ci rc = i2c_r(sd, OV7610_REG_COM_I); 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ci /* add OV7670 here 269862306a36Sopenharmony_ci * it appears to be wrongly detected as a 7610 by default */ 269962306a36Sopenharmony_ci if (rc < 0) { 270062306a36Sopenharmony_ci gspca_err(gspca_dev, "Error detecting sensor type\n"); 270162306a36Sopenharmony_ci return; 270262306a36Sopenharmony_ci } 270362306a36Sopenharmony_ci if ((rc & 3) == 3) { 270462306a36Sopenharmony_ci /* quick hack to make OV7670s work */ 270562306a36Sopenharmony_ci high = i2c_r(sd, 0x0a); 270662306a36Sopenharmony_ci low = i2c_r(sd, 0x0b); 270762306a36Sopenharmony_ci /* info("%x, %x", high, low); */ 270862306a36Sopenharmony_ci if (high == 0x76 && (low & 0xf0) == 0x70) { 270962306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV76%02x\n", 271062306a36Sopenharmony_ci low); 271162306a36Sopenharmony_ci sd->sensor = SEN_OV7670; 271262306a36Sopenharmony_ci } else { 271362306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7610\n"); 271462306a36Sopenharmony_ci sd->sensor = SEN_OV7610; 271562306a36Sopenharmony_ci } 271662306a36Sopenharmony_ci } else if ((rc & 3) == 1) { 271762306a36Sopenharmony_ci /* I don't know what's different about the 76BE yet. */ 271862306a36Sopenharmony_ci if (i2c_r(sd, 0x15) & 1) { 271962306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7620AE\n"); 272062306a36Sopenharmony_ci sd->sensor = SEN_OV7620AE; 272162306a36Sopenharmony_ci } else { 272262306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV76BE\n"); 272362306a36Sopenharmony_ci sd->sensor = SEN_OV76BE; 272462306a36Sopenharmony_ci } 272562306a36Sopenharmony_ci } else if ((rc & 3) == 0) { 272662306a36Sopenharmony_ci /* try to read product id registers */ 272762306a36Sopenharmony_ci high = i2c_r(sd, 0x0a); 272862306a36Sopenharmony_ci if (high < 0) { 272962306a36Sopenharmony_ci gspca_err(gspca_dev, "Error detecting camera chip PID\n"); 273062306a36Sopenharmony_ci return; 273162306a36Sopenharmony_ci } 273262306a36Sopenharmony_ci low = i2c_r(sd, 0x0b); 273362306a36Sopenharmony_ci if (low < 0) { 273462306a36Sopenharmony_ci gspca_err(gspca_dev, "Error detecting camera chip VER\n"); 273562306a36Sopenharmony_ci return; 273662306a36Sopenharmony_ci } 273762306a36Sopenharmony_ci if (high == 0x76) { 273862306a36Sopenharmony_ci switch (low) { 273962306a36Sopenharmony_ci case 0x30: 274062306a36Sopenharmony_ci gspca_err(gspca_dev, "Sensor is an OV7630/OV7635\n"); 274162306a36Sopenharmony_ci gspca_err(gspca_dev, "7630 is not supported by this driver\n"); 274262306a36Sopenharmony_ci return; 274362306a36Sopenharmony_ci case 0x40: 274462306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7645\n"); 274562306a36Sopenharmony_ci sd->sensor = SEN_OV7640; /* FIXME */ 274662306a36Sopenharmony_ci break; 274762306a36Sopenharmony_ci case 0x45: 274862306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7645B\n"); 274962306a36Sopenharmony_ci sd->sensor = SEN_OV7640; /* FIXME */ 275062306a36Sopenharmony_ci break; 275162306a36Sopenharmony_ci case 0x48: 275262306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7648\n"); 275362306a36Sopenharmony_ci sd->sensor = SEN_OV7648; 275462306a36Sopenharmony_ci break; 275562306a36Sopenharmony_ci case 0x60: 275662306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV7660\n"); 275762306a36Sopenharmony_ci sd->sensor = SEN_OV7660; 275862306a36Sopenharmony_ci break; 275962306a36Sopenharmony_ci default: 276062306a36Sopenharmony_ci gspca_err(gspca_dev, "Unknown sensor: 0x76%02x\n", 276162306a36Sopenharmony_ci low); 276262306a36Sopenharmony_ci return; 276362306a36Sopenharmony_ci } 276462306a36Sopenharmony_ci } else { 276562306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7620\n"); 276662306a36Sopenharmony_ci sd->sensor = SEN_OV7620; 276762306a36Sopenharmony_ci } 276862306a36Sopenharmony_ci } else { 276962306a36Sopenharmony_ci gspca_err(gspca_dev, "Unknown image sensor version: %d\n", 277062306a36Sopenharmony_ci rc & 3); 277162306a36Sopenharmony_ci } 277262306a36Sopenharmony_ci} 277362306a36Sopenharmony_ci 277462306a36Sopenharmony_ci/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ 277562306a36Sopenharmony_cistatic void ov6xx0_configure(struct sd *sd) 277662306a36Sopenharmony_ci{ 277762306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 277862306a36Sopenharmony_ci int rc; 277962306a36Sopenharmony_ci 278062306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "starting OV6xx0 configuration\n"); 278162306a36Sopenharmony_ci 278262306a36Sopenharmony_ci /* Detect sensor (sub)type */ 278362306a36Sopenharmony_ci rc = i2c_r(sd, OV7610_REG_COM_I); 278462306a36Sopenharmony_ci if (rc < 0) { 278562306a36Sopenharmony_ci gspca_err(gspca_dev, "Error detecting sensor type\n"); 278662306a36Sopenharmony_ci return; 278762306a36Sopenharmony_ci } 278862306a36Sopenharmony_ci 278962306a36Sopenharmony_ci /* Ugh. The first two bits are the version bits, but 279062306a36Sopenharmony_ci * the entire register value must be used. I guess OVT 279162306a36Sopenharmony_ci * underestimated how many variants they would make. */ 279262306a36Sopenharmony_ci switch (rc) { 279362306a36Sopenharmony_ci case 0x00: 279462306a36Sopenharmony_ci sd->sensor = SEN_OV6630; 279562306a36Sopenharmony_ci pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n"); 279662306a36Sopenharmony_ci break; 279762306a36Sopenharmony_ci case 0x01: 279862306a36Sopenharmony_ci sd->sensor = SEN_OV6620; 279962306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV6620\n"); 280062306a36Sopenharmony_ci break; 280162306a36Sopenharmony_ci case 0x02: 280262306a36Sopenharmony_ci sd->sensor = SEN_OV6630; 280362306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV66308AE\n"); 280462306a36Sopenharmony_ci break; 280562306a36Sopenharmony_ci case 0x03: 280662306a36Sopenharmony_ci sd->sensor = SEN_OV66308AF; 280762306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV66308AF\n"); 280862306a36Sopenharmony_ci break; 280962306a36Sopenharmony_ci case 0x90: 281062306a36Sopenharmony_ci sd->sensor = SEN_OV6630; 281162306a36Sopenharmony_ci pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n"); 281262306a36Sopenharmony_ci break; 281362306a36Sopenharmony_ci default: 281462306a36Sopenharmony_ci gspca_err(gspca_dev, "FATAL: Unknown sensor version: 0x%02x\n", 281562306a36Sopenharmony_ci rc); 281662306a36Sopenharmony_ci return; 281762306a36Sopenharmony_ci } 281862306a36Sopenharmony_ci 281962306a36Sopenharmony_ci /* Set sensor-specific vars */ 282062306a36Sopenharmony_ci sd->sif = 1; 282162306a36Sopenharmony_ci} 282262306a36Sopenharmony_ci 282362306a36Sopenharmony_ci/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ 282462306a36Sopenharmony_cistatic void ov51x_led_control(struct sd *sd, int on) 282562306a36Sopenharmony_ci{ 282662306a36Sopenharmony_ci if (sd->invert_led) 282762306a36Sopenharmony_ci on = !on; 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ci switch (sd->bridge) { 283062306a36Sopenharmony_ci /* OV511 has no LED control */ 283162306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 283262306a36Sopenharmony_ci reg_w(sd, R511_SYS_LED_CTL, on); 283362306a36Sopenharmony_ci break; 283462306a36Sopenharmony_ci case BRIDGE_OV518: 283562306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 283662306a36Sopenharmony_ci reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02); 283762306a36Sopenharmony_ci break; 283862306a36Sopenharmony_ci case BRIDGE_OV519: 283962306a36Sopenharmony_ci reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1); 284062306a36Sopenharmony_ci break; 284162306a36Sopenharmony_ci } 284262306a36Sopenharmony_ci} 284362306a36Sopenharmony_ci 284462306a36Sopenharmony_cistatic void sd_reset_snapshot(struct gspca_dev *gspca_dev) 284562306a36Sopenharmony_ci{ 284662306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_ci if (!sd->snapshot_needs_reset) 284962306a36Sopenharmony_ci return; 285062306a36Sopenharmony_ci 285162306a36Sopenharmony_ci /* Note it is important that we clear sd->snapshot_needs_reset, 285262306a36Sopenharmony_ci before actually clearing the snapshot state in the bridge 285362306a36Sopenharmony_ci otherwise we might race with the pkt_scan interrupt handler */ 285462306a36Sopenharmony_ci sd->snapshot_needs_reset = 0; 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_ci switch (sd->bridge) { 285762306a36Sopenharmony_ci case BRIDGE_OV511: 285862306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 285962306a36Sopenharmony_ci reg_w(sd, R51x_SYS_SNAP, 0x02); 286062306a36Sopenharmony_ci reg_w(sd, R51x_SYS_SNAP, 0x00); 286162306a36Sopenharmony_ci break; 286262306a36Sopenharmony_ci case BRIDGE_OV518: 286362306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 286462306a36Sopenharmony_ci reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */ 286562306a36Sopenharmony_ci reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */ 286662306a36Sopenharmony_ci break; 286762306a36Sopenharmony_ci case BRIDGE_OV519: 286862306a36Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x40); 286962306a36Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x00); 287062306a36Sopenharmony_ci break; 287162306a36Sopenharmony_ci } 287262306a36Sopenharmony_ci} 287362306a36Sopenharmony_ci 287462306a36Sopenharmony_cistatic void ov51x_upload_quan_tables(struct sd *sd) 287562306a36Sopenharmony_ci{ 287662306a36Sopenharmony_ci static const unsigned char yQuanTable511[] = { 287762306a36Sopenharmony_ci 0, 1, 1, 2, 2, 3, 3, 4, 287862306a36Sopenharmony_ci 1, 1, 1, 2, 2, 3, 4, 4, 287962306a36Sopenharmony_ci 1, 1, 2, 2, 3, 4, 4, 4, 288062306a36Sopenharmony_ci 2, 2, 2, 3, 4, 4, 4, 4, 288162306a36Sopenharmony_ci 2, 2, 3, 4, 4, 5, 5, 5, 288262306a36Sopenharmony_ci 3, 3, 4, 4, 5, 5, 5, 5, 288362306a36Sopenharmony_ci 3, 4, 4, 4, 5, 5, 5, 5, 288462306a36Sopenharmony_ci 4, 4, 4, 4, 5, 5, 5, 5 288562306a36Sopenharmony_ci }; 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_ci static const unsigned char uvQuanTable511[] = { 288862306a36Sopenharmony_ci 0, 2, 2, 3, 4, 4, 4, 4, 288962306a36Sopenharmony_ci 2, 2, 2, 4, 4, 4, 4, 4, 289062306a36Sopenharmony_ci 2, 2, 3, 4, 4, 4, 4, 4, 289162306a36Sopenharmony_ci 3, 4, 4, 4, 4, 4, 4, 4, 289262306a36Sopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 289362306a36Sopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 289462306a36Sopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 289562306a36Sopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4 289662306a36Sopenharmony_ci }; 289762306a36Sopenharmony_ci 289862306a36Sopenharmony_ci /* OV518 quantization tables are 8x4 (instead of 8x8) */ 289962306a36Sopenharmony_ci static const unsigned char yQuanTable518[] = { 290062306a36Sopenharmony_ci 5, 4, 5, 6, 6, 7, 7, 7, 290162306a36Sopenharmony_ci 5, 5, 5, 5, 6, 7, 7, 7, 290262306a36Sopenharmony_ci 6, 6, 6, 6, 7, 7, 7, 8, 290362306a36Sopenharmony_ci 7, 7, 6, 7, 7, 7, 8, 8 290462306a36Sopenharmony_ci }; 290562306a36Sopenharmony_ci static const unsigned char uvQuanTable518[] = { 290662306a36Sopenharmony_ci 6, 6, 6, 7, 7, 7, 7, 7, 290762306a36Sopenharmony_ci 6, 6, 6, 7, 7, 7, 7, 7, 290862306a36Sopenharmony_ci 6, 6, 6, 7, 7, 7, 7, 8, 290962306a36Sopenharmony_ci 7, 7, 7, 7, 7, 7, 8, 8 291062306a36Sopenharmony_ci }; 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 291362306a36Sopenharmony_ci const unsigned char *pYTable, *pUVTable; 291462306a36Sopenharmony_ci unsigned char val0, val1; 291562306a36Sopenharmony_ci int i, size, reg = R51x_COMP_LUT_BEGIN; 291662306a36Sopenharmony_ci 291762306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Uploading quantization tables\n"); 291862306a36Sopenharmony_ci 291962306a36Sopenharmony_ci if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { 292062306a36Sopenharmony_ci pYTable = yQuanTable511; 292162306a36Sopenharmony_ci pUVTable = uvQuanTable511; 292262306a36Sopenharmony_ci size = 32; 292362306a36Sopenharmony_ci } else { 292462306a36Sopenharmony_ci pYTable = yQuanTable518; 292562306a36Sopenharmony_ci pUVTable = uvQuanTable518; 292662306a36Sopenharmony_ci size = 16; 292762306a36Sopenharmony_ci } 292862306a36Sopenharmony_ci 292962306a36Sopenharmony_ci for (i = 0; i < size; i++) { 293062306a36Sopenharmony_ci val0 = *pYTable++; 293162306a36Sopenharmony_ci val1 = *pYTable++; 293262306a36Sopenharmony_ci val0 &= 0x0f; 293362306a36Sopenharmony_ci val1 &= 0x0f; 293462306a36Sopenharmony_ci val0 |= val1 << 4; 293562306a36Sopenharmony_ci reg_w(sd, reg, val0); 293662306a36Sopenharmony_ci 293762306a36Sopenharmony_ci val0 = *pUVTable++; 293862306a36Sopenharmony_ci val1 = *pUVTable++; 293962306a36Sopenharmony_ci val0 &= 0x0f; 294062306a36Sopenharmony_ci val1 &= 0x0f; 294162306a36Sopenharmony_ci val0 |= val1 << 4; 294262306a36Sopenharmony_ci reg_w(sd, reg + size, val0); 294362306a36Sopenharmony_ci 294462306a36Sopenharmony_ci reg++; 294562306a36Sopenharmony_ci } 294662306a36Sopenharmony_ci} 294762306a36Sopenharmony_ci 294862306a36Sopenharmony_ci/* This initializes the OV511/OV511+ and the sensor */ 294962306a36Sopenharmony_cistatic void ov511_configure(struct gspca_dev *gspca_dev) 295062306a36Sopenharmony_ci{ 295162306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 295262306a36Sopenharmony_ci 295362306a36Sopenharmony_ci /* For 511 and 511+ */ 295462306a36Sopenharmony_ci static const struct ov_regvals init_511[] = { 295562306a36Sopenharmony_ci { R51x_SYS_RESET, 0x7f }, 295662306a36Sopenharmony_ci { R51x_SYS_INIT, 0x01 }, 295762306a36Sopenharmony_ci { R51x_SYS_RESET, 0x7f }, 295862306a36Sopenharmony_ci { R51x_SYS_INIT, 0x01 }, 295962306a36Sopenharmony_ci { R51x_SYS_RESET, 0x3f }, 296062306a36Sopenharmony_ci { R51x_SYS_INIT, 0x01 }, 296162306a36Sopenharmony_ci { R51x_SYS_RESET, 0x3d }, 296262306a36Sopenharmony_ci }; 296362306a36Sopenharmony_ci 296462306a36Sopenharmony_ci static const struct ov_regvals norm_511[] = { 296562306a36Sopenharmony_ci { R511_DRAM_FLOW_CTL, 0x01 }, 296662306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x00 }, 296762306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x02 }, 296862306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x00 }, 296962306a36Sopenharmony_ci { R511_FIFO_OPTS, 0x1f }, 297062306a36Sopenharmony_ci { R511_COMP_EN, 0x00 }, 297162306a36Sopenharmony_ci { R511_COMP_LUT_EN, 0x03 }, 297262306a36Sopenharmony_ci }; 297362306a36Sopenharmony_ci 297462306a36Sopenharmony_ci static const struct ov_regvals norm_511_p[] = { 297562306a36Sopenharmony_ci { R511_DRAM_FLOW_CTL, 0xff }, 297662306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x00 }, 297762306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x02 }, 297862306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x00 }, 297962306a36Sopenharmony_ci { R511_FIFO_OPTS, 0xff }, 298062306a36Sopenharmony_ci { R511_COMP_EN, 0x00 }, 298162306a36Sopenharmony_ci { R511_COMP_LUT_EN, 0x03 }, 298262306a36Sopenharmony_ci }; 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_ci static const struct ov_regvals compress_511[] = { 298562306a36Sopenharmony_ci { 0x70, 0x1f }, 298662306a36Sopenharmony_ci { 0x71, 0x05 }, 298762306a36Sopenharmony_ci { 0x72, 0x06 }, 298862306a36Sopenharmony_ci { 0x73, 0x06 }, 298962306a36Sopenharmony_ci { 0x74, 0x14 }, 299062306a36Sopenharmony_ci { 0x75, 0x03 }, 299162306a36Sopenharmony_ci { 0x76, 0x04 }, 299262306a36Sopenharmony_ci { 0x77, 0x04 }, 299362306a36Sopenharmony_ci }; 299462306a36Sopenharmony_ci 299562306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Device custom id %x\n", 299662306a36Sopenharmony_ci reg_r(sd, R51x_SYS_CUST_ID)); 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_ci write_regvals(sd, init_511, ARRAY_SIZE(init_511)); 299962306a36Sopenharmony_ci 300062306a36Sopenharmony_ci switch (sd->bridge) { 300162306a36Sopenharmony_ci case BRIDGE_OV511: 300262306a36Sopenharmony_ci write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); 300362306a36Sopenharmony_ci break; 300462306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 300562306a36Sopenharmony_ci write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); 300662306a36Sopenharmony_ci break; 300762306a36Sopenharmony_ci } 300862306a36Sopenharmony_ci 300962306a36Sopenharmony_ci /* Init compression */ 301062306a36Sopenharmony_ci write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); 301162306a36Sopenharmony_ci 301262306a36Sopenharmony_ci ov51x_upload_quan_tables(sd); 301362306a36Sopenharmony_ci} 301462306a36Sopenharmony_ci 301562306a36Sopenharmony_ci/* This initializes the OV518/OV518+ and the sensor */ 301662306a36Sopenharmony_cistatic void ov518_configure(struct gspca_dev *gspca_dev) 301762306a36Sopenharmony_ci{ 301862306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 301962306a36Sopenharmony_ci 302062306a36Sopenharmony_ci /* For 518 and 518+ */ 302162306a36Sopenharmony_ci static const struct ov_regvals init_518[] = { 302262306a36Sopenharmony_ci { R51x_SYS_RESET, 0x40 }, 302362306a36Sopenharmony_ci { R51x_SYS_INIT, 0xe1 }, 302462306a36Sopenharmony_ci { R51x_SYS_RESET, 0x3e }, 302562306a36Sopenharmony_ci { R51x_SYS_INIT, 0xe1 }, 302662306a36Sopenharmony_ci { R51x_SYS_RESET, 0x00 }, 302762306a36Sopenharmony_ci { R51x_SYS_INIT, 0xe1 }, 302862306a36Sopenharmony_ci { 0x46, 0x00 }, 302962306a36Sopenharmony_ci { 0x5d, 0x03 }, 303062306a36Sopenharmony_ci }; 303162306a36Sopenharmony_ci 303262306a36Sopenharmony_ci static const struct ov_regvals norm_518[] = { 303362306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x02 }, /* Reset */ 303462306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x01 }, /* Enable */ 303562306a36Sopenharmony_ci { 0x31, 0x0f }, 303662306a36Sopenharmony_ci { 0x5d, 0x03 }, 303762306a36Sopenharmony_ci { 0x24, 0x9f }, 303862306a36Sopenharmony_ci { 0x25, 0x90 }, 303962306a36Sopenharmony_ci { 0x20, 0x00 }, 304062306a36Sopenharmony_ci { 0x51, 0x04 }, 304162306a36Sopenharmony_ci { 0x71, 0x19 }, 304262306a36Sopenharmony_ci { 0x2f, 0x80 }, 304362306a36Sopenharmony_ci }; 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci static const struct ov_regvals norm_518_p[] = { 304662306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x02 }, /* Reset */ 304762306a36Sopenharmony_ci { R51x_SYS_SNAP, 0x01 }, /* Enable */ 304862306a36Sopenharmony_ci { 0x31, 0x0f }, 304962306a36Sopenharmony_ci { 0x5d, 0x03 }, 305062306a36Sopenharmony_ci { 0x24, 0x9f }, 305162306a36Sopenharmony_ci { 0x25, 0x90 }, 305262306a36Sopenharmony_ci { 0x20, 0x60 }, 305362306a36Sopenharmony_ci { 0x51, 0x02 }, 305462306a36Sopenharmony_ci { 0x71, 0x19 }, 305562306a36Sopenharmony_ci { 0x40, 0xff }, 305662306a36Sopenharmony_ci { 0x41, 0x42 }, 305762306a36Sopenharmony_ci { 0x46, 0x00 }, 305862306a36Sopenharmony_ci { 0x33, 0x04 }, 305962306a36Sopenharmony_ci { 0x21, 0x19 }, 306062306a36Sopenharmony_ci { 0x3f, 0x10 }, 306162306a36Sopenharmony_ci { 0x2f, 0x80 }, 306262306a36Sopenharmony_ci }; 306362306a36Sopenharmony_ci 306462306a36Sopenharmony_ci /* First 5 bits of custom ID reg are a revision ID on OV518 */ 306562306a36Sopenharmony_ci sd->revision = reg_r(sd, R51x_SYS_CUST_ID) & 0x1f; 306662306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Device revision %d\n", sd->revision); 306762306a36Sopenharmony_ci 306862306a36Sopenharmony_ci write_regvals(sd, init_518, ARRAY_SIZE(init_518)); 306962306a36Sopenharmony_ci 307062306a36Sopenharmony_ci /* Set LED GPIO pin to output mode */ 307162306a36Sopenharmony_ci reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_ci switch (sd->bridge) { 307462306a36Sopenharmony_ci case BRIDGE_OV518: 307562306a36Sopenharmony_ci write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); 307662306a36Sopenharmony_ci break; 307762306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 307862306a36Sopenharmony_ci write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); 307962306a36Sopenharmony_ci break; 308062306a36Sopenharmony_ci } 308162306a36Sopenharmony_ci 308262306a36Sopenharmony_ci ov51x_upload_quan_tables(sd); 308362306a36Sopenharmony_ci 308462306a36Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 308562306a36Sopenharmony_ci} 308662306a36Sopenharmony_ci 308762306a36Sopenharmony_cistatic void ov519_configure(struct sd *sd) 308862306a36Sopenharmony_ci{ 308962306a36Sopenharmony_ci static const struct ov_regvals init_519[] = { 309062306a36Sopenharmony_ci { 0x5a, 0x6d }, /* EnableSystem */ 309162306a36Sopenharmony_ci { 0x53, 0x9b }, /* don't enable the microcontroller */ 309262306a36Sopenharmony_ci { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */ 309362306a36Sopenharmony_ci { 0x5d, 0x03 }, 309462306a36Sopenharmony_ci { 0x49, 0x01 }, 309562306a36Sopenharmony_ci { 0x48, 0x00 }, 309662306a36Sopenharmony_ci /* Set LED pin to output mode. Bit 4 must be cleared or sensor 309762306a36Sopenharmony_ci * detection will fail. This deserves further investigation. */ 309862306a36Sopenharmony_ci { OV519_GPIO_IO_CTRL0, 0xee }, 309962306a36Sopenharmony_ci { OV519_R51_RESET1, 0x0f }, 310062306a36Sopenharmony_ci { OV519_R51_RESET1, 0x00 }, 310162306a36Sopenharmony_ci { 0x22, 0x00 }, 310262306a36Sopenharmony_ci /* windows reads 0x55 at this point*/ 310362306a36Sopenharmony_ci }; 310462306a36Sopenharmony_ci 310562306a36Sopenharmony_ci write_regvals(sd, init_519, ARRAY_SIZE(init_519)); 310662306a36Sopenharmony_ci} 310762306a36Sopenharmony_ci 310862306a36Sopenharmony_cistatic void ovfx2_configure(struct sd *sd) 310962306a36Sopenharmony_ci{ 311062306a36Sopenharmony_ci static const struct ov_regvals init_fx2[] = { 311162306a36Sopenharmony_ci { 0x00, 0x60 }, 311262306a36Sopenharmony_ci { 0x02, 0x01 }, 311362306a36Sopenharmony_ci { 0x0f, 0x1d }, 311462306a36Sopenharmony_ci { 0xe9, 0x82 }, 311562306a36Sopenharmony_ci { 0xea, 0xc7 }, 311662306a36Sopenharmony_ci { 0xeb, 0x10 }, 311762306a36Sopenharmony_ci { 0xec, 0xf6 }, 311862306a36Sopenharmony_ci }; 311962306a36Sopenharmony_ci 312062306a36Sopenharmony_ci sd->stopped = 1; 312162306a36Sopenharmony_ci 312262306a36Sopenharmony_ci write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); 312362306a36Sopenharmony_ci} 312462306a36Sopenharmony_ci 312562306a36Sopenharmony_ci/* set the mode */ 312662306a36Sopenharmony_ci/* This function works for ov7660 only */ 312762306a36Sopenharmony_cistatic void ov519_set_mode(struct sd *sd) 312862306a36Sopenharmony_ci{ 312962306a36Sopenharmony_ci static const struct ov_regvals bridge_ov7660[2][10] = { 313062306a36Sopenharmony_ci {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00}, 313162306a36Sopenharmony_ci {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, 313262306a36Sopenharmony_ci {0x25, 0x01}, {0x26, 0x00}}, 313362306a36Sopenharmony_ci {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00}, 313462306a36Sopenharmony_ci {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, 313562306a36Sopenharmony_ci {0x25, 0x03}, {0x26, 0x00}} 313662306a36Sopenharmony_ci }; 313762306a36Sopenharmony_ci static const struct ov_i2c_regvals sensor_ov7660[2][3] = { 313862306a36Sopenharmony_ci {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}}, 313962306a36Sopenharmony_ci {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}} 314062306a36Sopenharmony_ci }; 314162306a36Sopenharmony_ci static const struct ov_i2c_regvals sensor_ov7660_2[] = { 314262306a36Sopenharmony_ci {OV7670_R17_HSTART, 0x13}, 314362306a36Sopenharmony_ci {OV7670_R18_HSTOP, 0x01}, 314462306a36Sopenharmony_ci {OV7670_R32_HREF, 0x92}, 314562306a36Sopenharmony_ci {OV7670_R19_VSTART, 0x02}, 314662306a36Sopenharmony_ci {OV7670_R1A_VSTOP, 0x7a}, 314762306a36Sopenharmony_ci {OV7670_R03_VREF, 0x00}, 314862306a36Sopenharmony_ci/* {0x33, 0x00}, */ 314962306a36Sopenharmony_ci/* {0x34, 0x07}, */ 315062306a36Sopenharmony_ci/* {0x36, 0x00}, */ 315162306a36Sopenharmony_ci/* {0x6b, 0x0a}, */ 315262306a36Sopenharmony_ci }; 315362306a36Sopenharmony_ci 315462306a36Sopenharmony_ci write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode], 315562306a36Sopenharmony_ci ARRAY_SIZE(bridge_ov7660[0])); 315662306a36Sopenharmony_ci write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode], 315762306a36Sopenharmony_ci ARRAY_SIZE(sensor_ov7660[0])); 315862306a36Sopenharmony_ci write_i2c_regvals(sd, sensor_ov7660_2, 315962306a36Sopenharmony_ci ARRAY_SIZE(sensor_ov7660_2)); 316062306a36Sopenharmony_ci} 316162306a36Sopenharmony_ci 316262306a36Sopenharmony_ci/* set the frame rate */ 316362306a36Sopenharmony_ci/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */ 316462306a36Sopenharmony_cistatic void ov519_set_fr(struct sd *sd) 316562306a36Sopenharmony_ci{ 316662306a36Sopenharmony_ci int fr; 316762306a36Sopenharmony_ci u8 clock; 316862306a36Sopenharmony_ci /* frame rate table with indices: 316962306a36Sopenharmony_ci * - mode = 0: 320x240, 1: 640x480 317062306a36Sopenharmony_ci * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5 317162306a36Sopenharmony_ci * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock) 317262306a36Sopenharmony_ci */ 317362306a36Sopenharmony_ci static const u8 fr_tb[2][6][3] = { 317462306a36Sopenharmony_ci {{0x04, 0xff, 0x00}, 317562306a36Sopenharmony_ci {0x04, 0x1f, 0x00}, 317662306a36Sopenharmony_ci {0x04, 0x1b, 0x00}, 317762306a36Sopenharmony_ci {0x04, 0x15, 0x00}, 317862306a36Sopenharmony_ci {0x04, 0x09, 0x00}, 317962306a36Sopenharmony_ci {0x04, 0x01, 0x00}}, 318062306a36Sopenharmony_ci {{0x0c, 0xff, 0x00}, 318162306a36Sopenharmony_ci {0x0c, 0x1f, 0x00}, 318262306a36Sopenharmony_ci {0x0c, 0x1b, 0x00}, 318362306a36Sopenharmony_ci {0x04, 0xff, 0x01}, 318462306a36Sopenharmony_ci {0x04, 0x1f, 0x01}, 318562306a36Sopenharmony_ci {0x04, 0x1b, 0x01}}, 318662306a36Sopenharmony_ci }; 318762306a36Sopenharmony_ci 318862306a36Sopenharmony_ci if (frame_rate > 0) 318962306a36Sopenharmony_ci sd->frame_rate = frame_rate; 319062306a36Sopenharmony_ci if (sd->frame_rate >= 30) 319162306a36Sopenharmony_ci fr = 0; 319262306a36Sopenharmony_ci else if (sd->frame_rate >= 25) 319362306a36Sopenharmony_ci fr = 1; 319462306a36Sopenharmony_ci else if (sd->frame_rate >= 20) 319562306a36Sopenharmony_ci fr = 2; 319662306a36Sopenharmony_ci else if (sd->frame_rate >= 15) 319762306a36Sopenharmony_ci fr = 3; 319862306a36Sopenharmony_ci else if (sd->frame_rate >= 10) 319962306a36Sopenharmony_ci fr = 4; 320062306a36Sopenharmony_ci else 320162306a36Sopenharmony_ci fr = 5; 320262306a36Sopenharmony_ci reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]); 320362306a36Sopenharmony_ci reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]); 320462306a36Sopenharmony_ci clock = fr_tb[sd->gspca_dev.curr_mode][fr][2]; 320562306a36Sopenharmony_ci if (sd->sensor == SEN_OV7660) 320662306a36Sopenharmony_ci clock |= 0x80; /* enable double clock */ 320762306a36Sopenharmony_ci ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); 320862306a36Sopenharmony_ci} 320962306a36Sopenharmony_ci 321062306a36Sopenharmony_cistatic void setautogain(struct gspca_dev *gspca_dev, s32 val) 321162306a36Sopenharmony_ci{ 321262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 321362306a36Sopenharmony_ci 321462306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, val ? 0x05 : 0x00, 0x05); 321562306a36Sopenharmony_ci} 321662306a36Sopenharmony_ci 321762306a36Sopenharmony_ci/* this function is called at probe time */ 321862306a36Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev, 321962306a36Sopenharmony_ci const struct usb_device_id *id) 322062306a36Sopenharmony_ci{ 322162306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 322262306a36Sopenharmony_ci struct cam *cam = &gspca_dev->cam; 322362306a36Sopenharmony_ci 322462306a36Sopenharmony_ci sd->bridge = id->driver_info & BRIDGE_MASK; 322562306a36Sopenharmony_ci sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0; 322662306a36Sopenharmony_ci 322762306a36Sopenharmony_ci switch (sd->bridge) { 322862306a36Sopenharmony_ci case BRIDGE_OV511: 322962306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 323062306a36Sopenharmony_ci cam->cam_mode = ov511_vga_mode; 323162306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov511_vga_mode); 323262306a36Sopenharmony_ci break; 323362306a36Sopenharmony_ci case BRIDGE_OV518: 323462306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 323562306a36Sopenharmony_ci cam->cam_mode = ov518_vga_mode; 323662306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov518_vga_mode); 323762306a36Sopenharmony_ci break; 323862306a36Sopenharmony_ci case BRIDGE_OV519: 323962306a36Sopenharmony_ci cam->cam_mode = ov519_vga_mode; 324062306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov519_vga_mode); 324162306a36Sopenharmony_ci break; 324262306a36Sopenharmony_ci case BRIDGE_OVFX2: 324362306a36Sopenharmony_ci cam->cam_mode = ov519_vga_mode; 324462306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov519_vga_mode); 324562306a36Sopenharmony_ci cam->bulk_size = OVFX2_BULK_SIZE; 324662306a36Sopenharmony_ci cam->bulk_nurbs = MAX_NURBS; 324762306a36Sopenharmony_ci cam->bulk = 1; 324862306a36Sopenharmony_ci break; 324962306a36Sopenharmony_ci case BRIDGE_W9968CF: 325062306a36Sopenharmony_ci cam->cam_mode = w9968cf_vga_mode; 325162306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); 325262306a36Sopenharmony_ci break; 325362306a36Sopenharmony_ci } 325462306a36Sopenharmony_ci 325562306a36Sopenharmony_ci sd->frame_rate = 15; 325662306a36Sopenharmony_ci 325762306a36Sopenharmony_ci return 0; 325862306a36Sopenharmony_ci} 325962306a36Sopenharmony_ci 326062306a36Sopenharmony_ci/* this function is called at probe and resume time */ 326162306a36Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev) 326262306a36Sopenharmony_ci{ 326362306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 326462306a36Sopenharmony_ci struct cam *cam = &gspca_dev->cam; 326562306a36Sopenharmony_ci 326662306a36Sopenharmony_ci switch (sd->bridge) { 326762306a36Sopenharmony_ci case BRIDGE_OV511: 326862306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 326962306a36Sopenharmony_ci ov511_configure(gspca_dev); 327062306a36Sopenharmony_ci break; 327162306a36Sopenharmony_ci case BRIDGE_OV518: 327262306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 327362306a36Sopenharmony_ci ov518_configure(gspca_dev); 327462306a36Sopenharmony_ci break; 327562306a36Sopenharmony_ci case BRIDGE_OV519: 327662306a36Sopenharmony_ci ov519_configure(sd); 327762306a36Sopenharmony_ci break; 327862306a36Sopenharmony_ci case BRIDGE_OVFX2: 327962306a36Sopenharmony_ci ovfx2_configure(sd); 328062306a36Sopenharmony_ci break; 328162306a36Sopenharmony_ci case BRIDGE_W9968CF: 328262306a36Sopenharmony_ci w9968cf_configure(sd); 328362306a36Sopenharmony_ci break; 328462306a36Sopenharmony_ci } 328562306a36Sopenharmony_ci 328662306a36Sopenharmony_ci /* The OV519 must be more aggressive about sensor detection since 328762306a36Sopenharmony_ci * I2C write will never fail if the sensor is not present. We have 328862306a36Sopenharmony_ci * to try to initialize the sensor to detect its presence */ 328962306a36Sopenharmony_ci sd->sensor = -1; 329062306a36Sopenharmony_ci 329162306a36Sopenharmony_ci /* Test for 76xx */ 329262306a36Sopenharmony_ci if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { 329362306a36Sopenharmony_ci ov7xx0_configure(sd); 329462306a36Sopenharmony_ci 329562306a36Sopenharmony_ci /* Test for 6xx0 */ 329662306a36Sopenharmony_ci } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { 329762306a36Sopenharmony_ci ov6xx0_configure(sd); 329862306a36Sopenharmony_ci 329962306a36Sopenharmony_ci /* Test for 8xx0 */ 330062306a36Sopenharmony_ci } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { 330162306a36Sopenharmony_ci ov8xx0_configure(sd); 330262306a36Sopenharmony_ci 330362306a36Sopenharmony_ci /* Test for 3xxx / 2xxx */ 330462306a36Sopenharmony_ci } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { 330562306a36Sopenharmony_ci ov_hires_configure(sd); 330662306a36Sopenharmony_ci } else { 330762306a36Sopenharmony_ci gspca_err(gspca_dev, "Can't determine sensor slave IDs\n"); 330862306a36Sopenharmony_ci goto error; 330962306a36Sopenharmony_ci } 331062306a36Sopenharmony_ci 331162306a36Sopenharmony_ci if (sd->sensor < 0) 331262306a36Sopenharmony_ci goto error; 331362306a36Sopenharmony_ci 331462306a36Sopenharmony_ci ov51x_led_control(sd, 0); /* turn LED off */ 331562306a36Sopenharmony_ci 331662306a36Sopenharmony_ci switch (sd->bridge) { 331762306a36Sopenharmony_ci case BRIDGE_OV511: 331862306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 331962306a36Sopenharmony_ci if (sd->sif) { 332062306a36Sopenharmony_ci cam->cam_mode = ov511_sif_mode; 332162306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov511_sif_mode); 332262306a36Sopenharmony_ci } 332362306a36Sopenharmony_ci break; 332462306a36Sopenharmony_ci case BRIDGE_OV518: 332562306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 332662306a36Sopenharmony_ci if (sd->sif) { 332762306a36Sopenharmony_ci cam->cam_mode = ov518_sif_mode; 332862306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov518_sif_mode); 332962306a36Sopenharmony_ci } 333062306a36Sopenharmony_ci break; 333162306a36Sopenharmony_ci case BRIDGE_OV519: 333262306a36Sopenharmony_ci if (sd->sif) { 333362306a36Sopenharmony_ci cam->cam_mode = ov519_sif_mode; 333462306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov519_sif_mode); 333562306a36Sopenharmony_ci } 333662306a36Sopenharmony_ci break; 333762306a36Sopenharmony_ci case BRIDGE_OVFX2: 333862306a36Sopenharmony_ci switch (sd->sensor) { 333962306a36Sopenharmony_ci case SEN_OV2610: 334062306a36Sopenharmony_ci case SEN_OV2610AE: 334162306a36Sopenharmony_ci cam->cam_mode = ovfx2_ov2610_mode; 334262306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode); 334362306a36Sopenharmony_ci break; 334462306a36Sopenharmony_ci case SEN_OV3610: 334562306a36Sopenharmony_ci cam->cam_mode = ovfx2_ov3610_mode; 334662306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode); 334762306a36Sopenharmony_ci break; 334862306a36Sopenharmony_ci case SEN_OV9600: 334962306a36Sopenharmony_ci cam->cam_mode = ovfx2_ov9600_mode; 335062306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode); 335162306a36Sopenharmony_ci break; 335262306a36Sopenharmony_ci default: 335362306a36Sopenharmony_ci if (sd->sif) { 335462306a36Sopenharmony_ci cam->cam_mode = ov519_sif_mode; 335562306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov519_sif_mode); 335662306a36Sopenharmony_ci } 335762306a36Sopenharmony_ci break; 335862306a36Sopenharmony_ci } 335962306a36Sopenharmony_ci break; 336062306a36Sopenharmony_ci case BRIDGE_W9968CF: 336162306a36Sopenharmony_ci if (sd->sif) 336262306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1; 336362306a36Sopenharmony_ci 336462306a36Sopenharmony_ci /* w9968cf needs initialisation once the sensor is known */ 336562306a36Sopenharmony_ci w9968cf_init(sd); 336662306a36Sopenharmony_ci break; 336762306a36Sopenharmony_ci } 336862306a36Sopenharmony_ci 336962306a36Sopenharmony_ci /* initialize the sensor */ 337062306a36Sopenharmony_ci switch (sd->sensor) { 337162306a36Sopenharmony_ci case SEN_OV2610: 337262306a36Sopenharmony_ci write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610)); 337362306a36Sopenharmony_ci 337462306a36Sopenharmony_ci /* Enable autogain, autoexpo, awb, bandfilter */ 337562306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x27, 0x27); 337662306a36Sopenharmony_ci break; 337762306a36Sopenharmony_ci case SEN_OV2610AE: 337862306a36Sopenharmony_ci write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae)); 337962306a36Sopenharmony_ci 338062306a36Sopenharmony_ci /* enable autoexpo */ 338162306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x05, 0x05); 338262306a36Sopenharmony_ci break; 338362306a36Sopenharmony_ci case SEN_OV3610: 338462306a36Sopenharmony_ci write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b)); 338562306a36Sopenharmony_ci 338662306a36Sopenharmony_ci /* Enable autogain, autoexpo, awb, bandfilter */ 338762306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x27, 0x27); 338862306a36Sopenharmony_ci break; 338962306a36Sopenharmony_ci case SEN_OV6620: 339062306a36Sopenharmony_ci write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)); 339162306a36Sopenharmony_ci break; 339262306a36Sopenharmony_ci case SEN_OV6630: 339362306a36Sopenharmony_ci case SEN_OV66308AF: 339462306a36Sopenharmony_ci write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)); 339562306a36Sopenharmony_ci break; 339662306a36Sopenharmony_ci default: 339762306a36Sopenharmony_ci/* case SEN_OV7610: */ 339862306a36Sopenharmony_ci/* case SEN_OV76BE: */ 339962306a36Sopenharmony_ci write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)); 340062306a36Sopenharmony_ci i2c_w_mask(sd, 0x0e, 0x00, 0x40); 340162306a36Sopenharmony_ci break; 340262306a36Sopenharmony_ci case SEN_OV7620: 340362306a36Sopenharmony_ci case SEN_OV7620AE: 340462306a36Sopenharmony_ci write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)); 340562306a36Sopenharmony_ci break; 340662306a36Sopenharmony_ci case SEN_OV7640: 340762306a36Sopenharmony_ci case SEN_OV7648: 340862306a36Sopenharmony_ci write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); 340962306a36Sopenharmony_ci break; 341062306a36Sopenharmony_ci case SEN_OV7660: 341162306a36Sopenharmony_ci i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET); 341262306a36Sopenharmony_ci msleep(14); 341362306a36Sopenharmony_ci reg_w(sd, OV519_R57_SNAPSHOT, 0x23); 341462306a36Sopenharmony_ci write_regvals(sd, init_519_ov7660, 341562306a36Sopenharmony_ci ARRAY_SIZE(init_519_ov7660)); 341662306a36Sopenharmony_ci write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660)); 341762306a36Sopenharmony_ci sd->gspca_dev.curr_mode = 1; /* 640x480 */ 341862306a36Sopenharmony_ci ov519_set_mode(sd); 341962306a36Sopenharmony_ci ov519_set_fr(sd); 342062306a36Sopenharmony_ci sd_reset_snapshot(gspca_dev); 342162306a36Sopenharmony_ci ov51x_restart(sd); 342262306a36Sopenharmony_ci ov51x_stop(sd); /* not in win traces */ 342362306a36Sopenharmony_ci ov51x_led_control(sd, 0); 342462306a36Sopenharmony_ci break; 342562306a36Sopenharmony_ci case SEN_OV7670: 342662306a36Sopenharmony_ci write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)); 342762306a36Sopenharmony_ci break; 342862306a36Sopenharmony_ci case SEN_OV8610: 342962306a36Sopenharmony_ci write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)); 343062306a36Sopenharmony_ci break; 343162306a36Sopenharmony_ci case SEN_OV9600: 343262306a36Sopenharmony_ci write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600)); 343362306a36Sopenharmony_ci 343462306a36Sopenharmony_ci /* enable autoexpo */ 343562306a36Sopenharmony_ci/* i2c_w_mask(sd, 0x13, 0x05, 0x05); */ 343662306a36Sopenharmony_ci break; 343762306a36Sopenharmony_ci } 343862306a36Sopenharmony_ci return gspca_dev->usb_err; 343962306a36Sopenharmony_cierror: 344062306a36Sopenharmony_ci gspca_err(gspca_dev, "OV519 Config failed\n"); 344162306a36Sopenharmony_ci return -EINVAL; 344262306a36Sopenharmony_ci} 344362306a36Sopenharmony_ci 344462306a36Sopenharmony_ci/* function called at start time before URB creation */ 344562306a36Sopenharmony_cistatic int sd_isoc_init(struct gspca_dev *gspca_dev) 344662306a36Sopenharmony_ci{ 344762306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 344862306a36Sopenharmony_ci 344962306a36Sopenharmony_ci switch (sd->bridge) { 345062306a36Sopenharmony_ci case BRIDGE_OVFX2: 345162306a36Sopenharmony_ci if (gspca_dev->pixfmt.width != 800) 345262306a36Sopenharmony_ci gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE; 345362306a36Sopenharmony_ci else 345462306a36Sopenharmony_ci gspca_dev->cam.bulk_size = 7 * 4096; 345562306a36Sopenharmony_ci break; 345662306a36Sopenharmony_ci } 345762306a36Sopenharmony_ci return 0; 345862306a36Sopenharmony_ci} 345962306a36Sopenharmony_ci 346062306a36Sopenharmony_ci/* Set up the OV511/OV511+ with the given image parameters. 346162306a36Sopenharmony_ci * 346262306a36Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions) 346362306a36Sopenharmony_ci */ 346462306a36Sopenharmony_cistatic void ov511_mode_init_regs(struct sd *sd) 346562306a36Sopenharmony_ci{ 346662306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 346762306a36Sopenharmony_ci int hsegs, vsegs, packet_size, fps, needed; 346862306a36Sopenharmony_ci int interlaced = 0; 346962306a36Sopenharmony_ci struct usb_host_interface *alt; 347062306a36Sopenharmony_ci struct usb_interface *intf; 347162306a36Sopenharmony_ci 347262306a36Sopenharmony_ci intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); 347362306a36Sopenharmony_ci alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); 347462306a36Sopenharmony_ci if (!alt) { 347562306a36Sopenharmony_ci gspca_err(gspca_dev, "Couldn't get altsetting\n"); 347662306a36Sopenharmony_ci sd->gspca_dev.usb_err = -EIO; 347762306a36Sopenharmony_ci return; 347862306a36Sopenharmony_ci } 347962306a36Sopenharmony_ci 348062306a36Sopenharmony_ci if (alt->desc.bNumEndpoints < 1) { 348162306a36Sopenharmony_ci sd->gspca_dev.usb_err = -ENODEV; 348262306a36Sopenharmony_ci return; 348362306a36Sopenharmony_ci } 348462306a36Sopenharmony_ci 348562306a36Sopenharmony_ci packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); 348662306a36Sopenharmony_ci reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); 348762306a36Sopenharmony_ci 348862306a36Sopenharmony_ci reg_w(sd, R511_CAM_UV_EN, 0x01); 348962306a36Sopenharmony_ci reg_w(sd, R511_SNAP_UV_EN, 0x01); 349062306a36Sopenharmony_ci reg_w(sd, R511_SNAP_OPTS, 0x03); 349162306a36Sopenharmony_ci 349262306a36Sopenharmony_ci /* Here I'm assuming that snapshot size == image size. 349362306a36Sopenharmony_ci * I hope that's always true. --claudio 349462306a36Sopenharmony_ci */ 349562306a36Sopenharmony_ci hsegs = (sd->gspca_dev.pixfmt.width >> 3) - 1; 349662306a36Sopenharmony_ci vsegs = (sd->gspca_dev.pixfmt.height >> 3) - 1; 349762306a36Sopenharmony_ci 349862306a36Sopenharmony_ci reg_w(sd, R511_CAM_PXCNT, hsegs); 349962306a36Sopenharmony_ci reg_w(sd, R511_CAM_LNCNT, vsegs); 350062306a36Sopenharmony_ci reg_w(sd, R511_CAM_PXDIV, 0x00); 350162306a36Sopenharmony_ci reg_w(sd, R511_CAM_LNDIV, 0x00); 350262306a36Sopenharmony_ci 350362306a36Sopenharmony_ci /* YUV420, low pass filter on */ 350462306a36Sopenharmony_ci reg_w(sd, R511_CAM_OPTS, 0x03); 350562306a36Sopenharmony_ci 350662306a36Sopenharmony_ci /* Snapshot additions */ 350762306a36Sopenharmony_ci reg_w(sd, R511_SNAP_PXCNT, hsegs); 350862306a36Sopenharmony_ci reg_w(sd, R511_SNAP_LNCNT, vsegs); 350962306a36Sopenharmony_ci reg_w(sd, R511_SNAP_PXDIV, 0x00); 351062306a36Sopenharmony_ci reg_w(sd, R511_SNAP_LNDIV, 0x00); 351162306a36Sopenharmony_ci 351262306a36Sopenharmony_ci /******** Set the framerate ********/ 351362306a36Sopenharmony_ci if (frame_rate > 0) 351462306a36Sopenharmony_ci sd->frame_rate = frame_rate; 351562306a36Sopenharmony_ci 351662306a36Sopenharmony_ci switch (sd->sensor) { 351762306a36Sopenharmony_ci case SEN_OV6620: 351862306a36Sopenharmony_ci /* No framerate control, doesn't like higher rates yet */ 351962306a36Sopenharmony_ci sd->clockdiv = 3; 352062306a36Sopenharmony_ci break; 352162306a36Sopenharmony_ci 352262306a36Sopenharmony_ci /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed 352362306a36Sopenharmony_ci for more sensors we need to do this for them too */ 352462306a36Sopenharmony_ci case SEN_OV7620: 352562306a36Sopenharmony_ci case SEN_OV7620AE: 352662306a36Sopenharmony_ci case SEN_OV7640: 352762306a36Sopenharmony_ci case SEN_OV7648: 352862306a36Sopenharmony_ci case SEN_OV76BE: 352962306a36Sopenharmony_ci if (sd->gspca_dev.pixfmt.width == 320) 353062306a36Sopenharmony_ci interlaced = 1; 353162306a36Sopenharmony_ci fallthrough; 353262306a36Sopenharmony_ci case SEN_OV6630: 353362306a36Sopenharmony_ci case SEN_OV7610: 353462306a36Sopenharmony_ci case SEN_OV7670: 353562306a36Sopenharmony_ci switch (sd->frame_rate) { 353662306a36Sopenharmony_ci case 30: 353762306a36Sopenharmony_ci case 25: 353862306a36Sopenharmony_ci /* Not enough bandwidth to do 640x480 @ 30 fps */ 353962306a36Sopenharmony_ci if (sd->gspca_dev.pixfmt.width != 640) { 354062306a36Sopenharmony_ci sd->clockdiv = 0; 354162306a36Sopenharmony_ci break; 354262306a36Sopenharmony_ci } 354362306a36Sopenharmony_ci /* For 640x480 case */ 354462306a36Sopenharmony_ci fallthrough; 354562306a36Sopenharmony_ci default: 354662306a36Sopenharmony_ci/* case 20: */ 354762306a36Sopenharmony_ci/* case 15: */ 354862306a36Sopenharmony_ci sd->clockdiv = 1; 354962306a36Sopenharmony_ci break; 355062306a36Sopenharmony_ci case 10: 355162306a36Sopenharmony_ci sd->clockdiv = 2; 355262306a36Sopenharmony_ci break; 355362306a36Sopenharmony_ci case 5: 355462306a36Sopenharmony_ci sd->clockdiv = 5; 355562306a36Sopenharmony_ci break; 355662306a36Sopenharmony_ci } 355762306a36Sopenharmony_ci if (interlaced) { 355862306a36Sopenharmony_ci sd->clockdiv = (sd->clockdiv + 1) * 2 - 1; 355962306a36Sopenharmony_ci /* Higher then 10 does not work */ 356062306a36Sopenharmony_ci if (sd->clockdiv > 10) 356162306a36Sopenharmony_ci sd->clockdiv = 10; 356262306a36Sopenharmony_ci } 356362306a36Sopenharmony_ci break; 356462306a36Sopenharmony_ci 356562306a36Sopenharmony_ci case SEN_OV8610: 356662306a36Sopenharmony_ci /* No framerate control ?? */ 356762306a36Sopenharmony_ci sd->clockdiv = 0; 356862306a36Sopenharmony_ci break; 356962306a36Sopenharmony_ci } 357062306a36Sopenharmony_ci 357162306a36Sopenharmony_ci /* Check if we have enough bandwidth to disable compression */ 357262306a36Sopenharmony_ci fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1; 357362306a36Sopenharmony_ci needed = fps * sd->gspca_dev.pixfmt.width * 357462306a36Sopenharmony_ci sd->gspca_dev.pixfmt.height * 3 / 2; 357562306a36Sopenharmony_ci /* 1000 isoc packets/sec */ 357662306a36Sopenharmony_ci if (needed > 1000 * packet_size) { 357762306a36Sopenharmony_ci /* Enable Y and UV quantization and compression */ 357862306a36Sopenharmony_ci reg_w(sd, R511_COMP_EN, 0x07); 357962306a36Sopenharmony_ci reg_w(sd, R511_COMP_LUT_EN, 0x03); 358062306a36Sopenharmony_ci } else { 358162306a36Sopenharmony_ci reg_w(sd, R511_COMP_EN, 0x06); 358262306a36Sopenharmony_ci reg_w(sd, R511_COMP_LUT_EN, 0x00); 358362306a36Sopenharmony_ci } 358462306a36Sopenharmony_ci 358562306a36Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); 358662306a36Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0); 358762306a36Sopenharmony_ci} 358862306a36Sopenharmony_ci 358962306a36Sopenharmony_ci/* Sets up the OV518/OV518+ with the given image parameters 359062306a36Sopenharmony_ci * 359162306a36Sopenharmony_ci * OV518 needs a completely different approach, until we can figure out what 359262306a36Sopenharmony_ci * the individual registers do. Also, only 15 FPS is supported now. 359362306a36Sopenharmony_ci * 359462306a36Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions) 359562306a36Sopenharmony_ci */ 359662306a36Sopenharmony_cistatic void ov518_mode_init_regs(struct sd *sd) 359762306a36Sopenharmony_ci{ 359862306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 359962306a36Sopenharmony_ci int hsegs, vsegs, packet_size; 360062306a36Sopenharmony_ci struct usb_host_interface *alt; 360162306a36Sopenharmony_ci struct usb_interface *intf; 360262306a36Sopenharmony_ci 360362306a36Sopenharmony_ci intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); 360462306a36Sopenharmony_ci alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); 360562306a36Sopenharmony_ci if (!alt) { 360662306a36Sopenharmony_ci gspca_err(gspca_dev, "Couldn't get altsetting\n"); 360762306a36Sopenharmony_ci sd->gspca_dev.usb_err = -EIO; 360862306a36Sopenharmony_ci return; 360962306a36Sopenharmony_ci } 361062306a36Sopenharmony_ci 361162306a36Sopenharmony_ci if (alt->desc.bNumEndpoints < 1) { 361262306a36Sopenharmony_ci sd->gspca_dev.usb_err = -ENODEV; 361362306a36Sopenharmony_ci return; 361462306a36Sopenharmony_ci } 361562306a36Sopenharmony_ci 361662306a36Sopenharmony_ci packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); 361762306a36Sopenharmony_ci ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); 361862306a36Sopenharmony_ci 361962306a36Sopenharmony_ci /******** Set the mode ********/ 362062306a36Sopenharmony_ci reg_w(sd, 0x2b, 0); 362162306a36Sopenharmony_ci reg_w(sd, 0x2c, 0); 362262306a36Sopenharmony_ci reg_w(sd, 0x2d, 0); 362362306a36Sopenharmony_ci reg_w(sd, 0x2e, 0); 362462306a36Sopenharmony_ci reg_w(sd, 0x3b, 0); 362562306a36Sopenharmony_ci reg_w(sd, 0x3c, 0); 362662306a36Sopenharmony_ci reg_w(sd, 0x3d, 0); 362762306a36Sopenharmony_ci reg_w(sd, 0x3e, 0); 362862306a36Sopenharmony_ci 362962306a36Sopenharmony_ci if (sd->bridge == BRIDGE_OV518) { 363062306a36Sopenharmony_ci /* Set 8-bit (YVYU) input format */ 363162306a36Sopenharmony_ci reg_w_mask(sd, 0x20, 0x08, 0x08); 363262306a36Sopenharmony_ci 363362306a36Sopenharmony_ci /* Set 12-bit (4:2:0) output format */ 363462306a36Sopenharmony_ci reg_w_mask(sd, 0x28, 0x80, 0xf0); 363562306a36Sopenharmony_ci reg_w_mask(sd, 0x38, 0x80, 0xf0); 363662306a36Sopenharmony_ci } else { 363762306a36Sopenharmony_ci reg_w(sd, 0x28, 0x80); 363862306a36Sopenharmony_ci reg_w(sd, 0x38, 0x80); 363962306a36Sopenharmony_ci } 364062306a36Sopenharmony_ci 364162306a36Sopenharmony_ci hsegs = sd->gspca_dev.pixfmt.width / 16; 364262306a36Sopenharmony_ci vsegs = sd->gspca_dev.pixfmt.height / 4; 364362306a36Sopenharmony_ci 364462306a36Sopenharmony_ci reg_w(sd, 0x29, hsegs); 364562306a36Sopenharmony_ci reg_w(sd, 0x2a, vsegs); 364662306a36Sopenharmony_ci 364762306a36Sopenharmony_ci reg_w(sd, 0x39, hsegs); 364862306a36Sopenharmony_ci reg_w(sd, 0x3a, vsegs); 364962306a36Sopenharmony_ci 365062306a36Sopenharmony_ci /* Windows driver does this here; who knows why */ 365162306a36Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 365262306a36Sopenharmony_ci 365362306a36Sopenharmony_ci /******** Set the framerate ********/ 365462306a36Sopenharmony_ci if (sd->bridge == BRIDGE_OV518PLUS && sd->revision == 0 && 365562306a36Sopenharmony_ci sd->sensor == SEN_OV7620AE) 365662306a36Sopenharmony_ci sd->clockdiv = 0; 365762306a36Sopenharmony_ci else 365862306a36Sopenharmony_ci sd->clockdiv = 1; 365962306a36Sopenharmony_ci 366062306a36Sopenharmony_ci /* Mode independent, but framerate dependent, regs */ 366162306a36Sopenharmony_ci /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ 366262306a36Sopenharmony_ci reg_w(sd, 0x51, 0x04); 366362306a36Sopenharmony_ci reg_w(sd, 0x22, 0x18); 366462306a36Sopenharmony_ci reg_w(sd, 0x23, 0xff); 366562306a36Sopenharmony_ci 366662306a36Sopenharmony_ci if (sd->bridge == BRIDGE_OV518PLUS) { 366762306a36Sopenharmony_ci switch (sd->sensor) { 366862306a36Sopenharmony_ci case SEN_OV7620AE: 366962306a36Sopenharmony_ci /* 367062306a36Sopenharmony_ci * HdG: 640x480 needs special handling on device 367162306a36Sopenharmony_ci * revision 2, we check for device revision > 0 to 367262306a36Sopenharmony_ci * avoid regressions, as we don't know the correct 367362306a36Sopenharmony_ci * thing todo for revision 1. 367462306a36Sopenharmony_ci * 367562306a36Sopenharmony_ci * Also this likely means we don't need to 367662306a36Sopenharmony_ci * differentiate between the OV7620 and OV7620AE, 367762306a36Sopenharmony_ci * earlier testing hitting this same problem likely 367862306a36Sopenharmony_ci * happened to be with revision < 2 cams using an 367962306a36Sopenharmony_ci * OV7620 and revision 2 cams using an OV7620AE. 368062306a36Sopenharmony_ci */ 368162306a36Sopenharmony_ci if (sd->revision > 0 && 368262306a36Sopenharmony_ci sd->gspca_dev.pixfmt.width == 640) { 368362306a36Sopenharmony_ci reg_w(sd, 0x20, 0x60); 368462306a36Sopenharmony_ci reg_w(sd, 0x21, 0x1f); 368562306a36Sopenharmony_ci } else { 368662306a36Sopenharmony_ci reg_w(sd, 0x20, 0x00); 368762306a36Sopenharmony_ci reg_w(sd, 0x21, 0x19); 368862306a36Sopenharmony_ci } 368962306a36Sopenharmony_ci break; 369062306a36Sopenharmony_ci case SEN_OV7620: 369162306a36Sopenharmony_ci reg_w(sd, 0x20, 0x00); 369262306a36Sopenharmony_ci reg_w(sd, 0x21, 0x19); 369362306a36Sopenharmony_ci break; 369462306a36Sopenharmony_ci default: 369562306a36Sopenharmony_ci reg_w(sd, 0x21, 0x19); 369662306a36Sopenharmony_ci } 369762306a36Sopenharmony_ci } else 369862306a36Sopenharmony_ci reg_w(sd, 0x71, 0x17); /* Compression-related? */ 369962306a36Sopenharmony_ci 370062306a36Sopenharmony_ci /* FIXME: Sensor-specific */ 370162306a36Sopenharmony_ci /* Bit 5 is what matters here. Of course, it is "reserved" */ 370262306a36Sopenharmony_ci i2c_w(sd, 0x54, 0x23); 370362306a36Sopenharmony_ci 370462306a36Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 370562306a36Sopenharmony_ci 370662306a36Sopenharmony_ci if (sd->bridge == BRIDGE_OV518PLUS) { 370762306a36Sopenharmony_ci reg_w(sd, 0x24, 0x94); 370862306a36Sopenharmony_ci reg_w(sd, 0x25, 0x90); 370962306a36Sopenharmony_ci ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ 371062306a36Sopenharmony_ci ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */ 371162306a36Sopenharmony_ci ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */ 371262306a36Sopenharmony_ci ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */ 371362306a36Sopenharmony_ci ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */ 371462306a36Sopenharmony_ci ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */ 371562306a36Sopenharmony_ci ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */ 371662306a36Sopenharmony_ci ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */ 371762306a36Sopenharmony_ci ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */ 371862306a36Sopenharmony_ci } else { 371962306a36Sopenharmony_ci reg_w(sd, 0x24, 0x9f); 372062306a36Sopenharmony_ci reg_w(sd, 0x25, 0x90); 372162306a36Sopenharmony_ci ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ 372262306a36Sopenharmony_ci ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */ 372362306a36Sopenharmony_ci ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */ 372462306a36Sopenharmony_ci ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */ 372562306a36Sopenharmony_ci ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */ 372662306a36Sopenharmony_ci ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */ 372762306a36Sopenharmony_ci ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */ 372862306a36Sopenharmony_ci ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */ 372962306a36Sopenharmony_ci ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */ 373062306a36Sopenharmony_ci } 373162306a36Sopenharmony_ci 373262306a36Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 373362306a36Sopenharmony_ci} 373462306a36Sopenharmony_ci 373562306a36Sopenharmony_ci/* Sets up the OV519 with the given image parameters 373662306a36Sopenharmony_ci * 373762306a36Sopenharmony_ci * OV519 needs a completely different approach, until we can figure out what 373862306a36Sopenharmony_ci * the individual registers do. 373962306a36Sopenharmony_ci * 374062306a36Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions) 374162306a36Sopenharmony_ci */ 374262306a36Sopenharmony_cistatic void ov519_mode_init_regs(struct sd *sd) 374362306a36Sopenharmony_ci{ 374462306a36Sopenharmony_ci static const struct ov_regvals mode_init_519_ov7670[] = { 374562306a36Sopenharmony_ci { 0x5d, 0x03 }, /* Turn off suspend mode */ 374662306a36Sopenharmony_ci { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ 374762306a36Sopenharmony_ci { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ 374862306a36Sopenharmony_ci { 0xa2, 0x20 }, /* a2-a5 are undocumented */ 374962306a36Sopenharmony_ci { 0xa3, 0x18 }, 375062306a36Sopenharmony_ci { 0xa4, 0x04 }, 375162306a36Sopenharmony_ci { 0xa5, 0x28 }, 375262306a36Sopenharmony_ci { 0x37, 0x00 }, /* SetUsbInit */ 375362306a36Sopenharmony_ci { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ 375462306a36Sopenharmony_ci /* Enable both fields, YUV Input, disable defect comp (why?) */ 375562306a36Sopenharmony_ci { 0x20, 0x0c }, 375662306a36Sopenharmony_ci { 0x21, 0x38 }, 375762306a36Sopenharmony_ci { 0x22, 0x1d }, 375862306a36Sopenharmony_ci { 0x17, 0x50 }, /* undocumented */ 375962306a36Sopenharmony_ci { 0x37, 0x00 }, /* undocumented */ 376062306a36Sopenharmony_ci { 0x40, 0xff }, /* I2C timeout counter */ 376162306a36Sopenharmony_ci { 0x46, 0x00 }, /* I2C clock prescaler */ 376262306a36Sopenharmony_ci { 0x59, 0x04 }, /* new from windrv 090403 */ 376362306a36Sopenharmony_ci { 0xff, 0x00 }, /* undocumented */ 376462306a36Sopenharmony_ci /* windows reads 0x55 at this point, why? */ 376562306a36Sopenharmony_ci }; 376662306a36Sopenharmony_ci 376762306a36Sopenharmony_ci static const struct ov_regvals mode_init_519[] = { 376862306a36Sopenharmony_ci { 0x5d, 0x03 }, /* Turn off suspend mode */ 376962306a36Sopenharmony_ci { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ 377062306a36Sopenharmony_ci { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ 377162306a36Sopenharmony_ci { 0xa2, 0x20 }, /* a2-a5 are undocumented */ 377262306a36Sopenharmony_ci { 0xa3, 0x18 }, 377362306a36Sopenharmony_ci { 0xa4, 0x04 }, 377462306a36Sopenharmony_ci { 0xa5, 0x28 }, 377562306a36Sopenharmony_ci { 0x37, 0x00 }, /* SetUsbInit */ 377662306a36Sopenharmony_ci { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ 377762306a36Sopenharmony_ci /* Enable both fields, YUV Input, disable defect comp (why?) */ 377862306a36Sopenharmony_ci { 0x22, 0x1d }, 377962306a36Sopenharmony_ci { 0x17, 0x50 }, /* undocumented */ 378062306a36Sopenharmony_ci { 0x37, 0x00 }, /* undocumented */ 378162306a36Sopenharmony_ci { 0x40, 0xff }, /* I2C timeout counter */ 378262306a36Sopenharmony_ci { 0x46, 0x00 }, /* I2C clock prescaler */ 378362306a36Sopenharmony_ci { 0x59, 0x04 }, /* new from windrv 090403 */ 378462306a36Sopenharmony_ci { 0xff, 0x00 }, /* undocumented */ 378562306a36Sopenharmony_ci /* windows reads 0x55 at this point, why? */ 378662306a36Sopenharmony_ci }; 378762306a36Sopenharmony_ci 378862306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 378962306a36Sopenharmony_ci 379062306a36Sopenharmony_ci /******** Set the mode ********/ 379162306a36Sopenharmony_ci switch (sd->sensor) { 379262306a36Sopenharmony_ci default: 379362306a36Sopenharmony_ci write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); 379462306a36Sopenharmony_ci if (sd->sensor == SEN_OV7640 || 379562306a36Sopenharmony_ci sd->sensor == SEN_OV7648) { 379662306a36Sopenharmony_ci /* Select 8-bit input mode */ 379762306a36Sopenharmony_ci reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); 379862306a36Sopenharmony_ci } 379962306a36Sopenharmony_ci break; 380062306a36Sopenharmony_ci case SEN_OV7660: 380162306a36Sopenharmony_ci return; /* done by ov519_set_mode/fr() */ 380262306a36Sopenharmony_ci case SEN_OV7670: 380362306a36Sopenharmony_ci write_regvals(sd, mode_init_519_ov7670, 380462306a36Sopenharmony_ci ARRAY_SIZE(mode_init_519_ov7670)); 380562306a36Sopenharmony_ci break; 380662306a36Sopenharmony_ci } 380762306a36Sopenharmony_ci 380862306a36Sopenharmony_ci reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.pixfmt.width >> 4); 380962306a36Sopenharmony_ci reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.pixfmt.height >> 3); 381062306a36Sopenharmony_ci if (sd->sensor == SEN_OV7670 && 381162306a36Sopenharmony_ci sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) 381262306a36Sopenharmony_ci reg_w(sd, OV519_R12_X_OFFSETL, 0x04); 381362306a36Sopenharmony_ci else if (sd->sensor == SEN_OV7648 && 381462306a36Sopenharmony_ci sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) 381562306a36Sopenharmony_ci reg_w(sd, OV519_R12_X_OFFSETL, 0x01); 381662306a36Sopenharmony_ci else 381762306a36Sopenharmony_ci reg_w(sd, OV519_R12_X_OFFSETL, 0x00); 381862306a36Sopenharmony_ci reg_w(sd, OV519_R13_X_OFFSETH, 0x00); 381962306a36Sopenharmony_ci reg_w(sd, OV519_R14_Y_OFFSETL, 0x00); 382062306a36Sopenharmony_ci reg_w(sd, OV519_R15_Y_OFFSETH, 0x00); 382162306a36Sopenharmony_ci reg_w(sd, OV519_R16_DIVIDER, 0x00); 382262306a36Sopenharmony_ci reg_w(sd, OV519_R25_FORMAT, 0x03); /* YUV422 */ 382362306a36Sopenharmony_ci reg_w(sd, 0x26, 0x00); /* Undocumented */ 382462306a36Sopenharmony_ci 382562306a36Sopenharmony_ci /******** Set the framerate ********/ 382662306a36Sopenharmony_ci if (frame_rate > 0) 382762306a36Sopenharmony_ci sd->frame_rate = frame_rate; 382862306a36Sopenharmony_ci 382962306a36Sopenharmony_ci/* FIXME: These are only valid at the max resolution. */ 383062306a36Sopenharmony_ci sd->clockdiv = 0; 383162306a36Sopenharmony_ci switch (sd->sensor) { 383262306a36Sopenharmony_ci case SEN_OV7640: 383362306a36Sopenharmony_ci case SEN_OV7648: 383462306a36Sopenharmony_ci switch (sd->frame_rate) { 383562306a36Sopenharmony_ci default: 383662306a36Sopenharmony_ci/* case 30: */ 383762306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x0c); 383862306a36Sopenharmony_ci reg_w(sd, 0x23, 0xff); 383962306a36Sopenharmony_ci break; 384062306a36Sopenharmony_ci case 25: 384162306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x0c); 384262306a36Sopenharmony_ci reg_w(sd, 0x23, 0x1f); 384362306a36Sopenharmony_ci break; 384462306a36Sopenharmony_ci case 20: 384562306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x0c); 384662306a36Sopenharmony_ci reg_w(sd, 0x23, 0x1b); 384762306a36Sopenharmony_ci break; 384862306a36Sopenharmony_ci case 15: 384962306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x04); 385062306a36Sopenharmony_ci reg_w(sd, 0x23, 0xff); 385162306a36Sopenharmony_ci sd->clockdiv = 1; 385262306a36Sopenharmony_ci break; 385362306a36Sopenharmony_ci case 10: 385462306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x04); 385562306a36Sopenharmony_ci reg_w(sd, 0x23, 0x1f); 385662306a36Sopenharmony_ci sd->clockdiv = 1; 385762306a36Sopenharmony_ci break; 385862306a36Sopenharmony_ci case 5: 385962306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x04); 386062306a36Sopenharmony_ci reg_w(sd, 0x23, 0x1b); 386162306a36Sopenharmony_ci sd->clockdiv = 1; 386262306a36Sopenharmony_ci break; 386362306a36Sopenharmony_ci } 386462306a36Sopenharmony_ci break; 386562306a36Sopenharmony_ci case SEN_OV8610: 386662306a36Sopenharmony_ci switch (sd->frame_rate) { 386762306a36Sopenharmony_ci default: /* 15 fps */ 386862306a36Sopenharmony_ci/* case 15: */ 386962306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x06); 387062306a36Sopenharmony_ci reg_w(sd, 0x23, 0xff); 387162306a36Sopenharmony_ci break; 387262306a36Sopenharmony_ci case 10: 387362306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x06); 387462306a36Sopenharmony_ci reg_w(sd, 0x23, 0x1f); 387562306a36Sopenharmony_ci break; 387662306a36Sopenharmony_ci case 5: 387762306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x06); 387862306a36Sopenharmony_ci reg_w(sd, 0x23, 0x1b); 387962306a36Sopenharmony_ci break; 388062306a36Sopenharmony_ci } 388162306a36Sopenharmony_ci break; 388262306a36Sopenharmony_ci case SEN_OV7670: /* guesses, based on 7640 */ 388362306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Setting framerate to %d fps\n", 388462306a36Sopenharmony_ci (sd->frame_rate == 0) ? 15 : sd->frame_rate); 388562306a36Sopenharmony_ci reg_w(sd, 0xa4, 0x10); 388662306a36Sopenharmony_ci switch (sd->frame_rate) { 388762306a36Sopenharmony_ci case 30: 388862306a36Sopenharmony_ci reg_w(sd, 0x23, 0xff); 388962306a36Sopenharmony_ci break; 389062306a36Sopenharmony_ci case 20: 389162306a36Sopenharmony_ci reg_w(sd, 0x23, 0x1b); 389262306a36Sopenharmony_ci break; 389362306a36Sopenharmony_ci default: 389462306a36Sopenharmony_ci/* case 15: */ 389562306a36Sopenharmony_ci reg_w(sd, 0x23, 0xff); 389662306a36Sopenharmony_ci sd->clockdiv = 1; 389762306a36Sopenharmony_ci break; 389862306a36Sopenharmony_ci } 389962306a36Sopenharmony_ci break; 390062306a36Sopenharmony_ci } 390162306a36Sopenharmony_ci} 390262306a36Sopenharmony_ci 390362306a36Sopenharmony_cistatic void mode_init_ov_sensor_regs(struct sd *sd) 390462306a36Sopenharmony_ci{ 390562306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 390662306a36Sopenharmony_ci int qvga, xstart, xend, ystart, yend; 390762306a36Sopenharmony_ci u8 v; 390862306a36Sopenharmony_ci 390962306a36Sopenharmony_ci qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; 391062306a36Sopenharmony_ci 391162306a36Sopenharmony_ci /******** Mode (VGA/QVGA) and sensor specific regs ********/ 391262306a36Sopenharmony_ci switch (sd->sensor) { 391362306a36Sopenharmony_ci case SEN_OV2610: 391462306a36Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 391562306a36Sopenharmony_ci i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); 391662306a36Sopenharmony_ci i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); 391762306a36Sopenharmony_ci i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); 391862306a36Sopenharmony_ci i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); 391962306a36Sopenharmony_ci i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); 392062306a36Sopenharmony_ci i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); 392162306a36Sopenharmony_ci return; 392262306a36Sopenharmony_ci case SEN_OV2610AE: { 392362306a36Sopenharmony_ci u8 v; 392462306a36Sopenharmony_ci 392562306a36Sopenharmony_ci /* frame rates: 392662306a36Sopenharmony_ci * 10fps / 5 fps for 1600x1200 392762306a36Sopenharmony_ci * 40fps / 20fps for 800x600 392862306a36Sopenharmony_ci */ 392962306a36Sopenharmony_ci v = 80; 393062306a36Sopenharmony_ci if (qvga) { 393162306a36Sopenharmony_ci if (sd->frame_rate < 25) 393262306a36Sopenharmony_ci v = 0x81; 393362306a36Sopenharmony_ci } else { 393462306a36Sopenharmony_ci if (sd->frame_rate < 10) 393562306a36Sopenharmony_ci v = 0x81; 393662306a36Sopenharmony_ci } 393762306a36Sopenharmony_ci i2c_w(sd, 0x11, v); 393862306a36Sopenharmony_ci i2c_w(sd, 0x12, qvga ? 0x60 : 0x20); 393962306a36Sopenharmony_ci return; 394062306a36Sopenharmony_ci } 394162306a36Sopenharmony_ci case SEN_OV3610: 394262306a36Sopenharmony_ci if (qvga) { 394362306a36Sopenharmony_ci xstart = (1040 - gspca_dev->pixfmt.width) / 2 + 394462306a36Sopenharmony_ci (0x1f << 4); 394562306a36Sopenharmony_ci ystart = (776 - gspca_dev->pixfmt.height) / 2; 394662306a36Sopenharmony_ci } else { 394762306a36Sopenharmony_ci xstart = (2076 - gspca_dev->pixfmt.width) / 2 + 394862306a36Sopenharmony_ci (0x10 << 4); 394962306a36Sopenharmony_ci ystart = (1544 - gspca_dev->pixfmt.height) / 2; 395062306a36Sopenharmony_ci } 395162306a36Sopenharmony_ci xend = xstart + gspca_dev->pixfmt.width; 395262306a36Sopenharmony_ci yend = ystart + gspca_dev->pixfmt.height; 395362306a36Sopenharmony_ci /* Writing to the COMH register resets the other windowing regs 395462306a36Sopenharmony_ci to their default values, so we must do this first. */ 395562306a36Sopenharmony_ci i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0); 395662306a36Sopenharmony_ci i2c_w_mask(sd, 0x32, 395762306a36Sopenharmony_ci (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7), 395862306a36Sopenharmony_ci 0x3f); 395962306a36Sopenharmony_ci i2c_w_mask(sd, 0x03, 396062306a36Sopenharmony_ci (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3), 396162306a36Sopenharmony_ci 0x0f); 396262306a36Sopenharmony_ci i2c_w(sd, 0x17, xstart >> 4); 396362306a36Sopenharmony_ci i2c_w(sd, 0x18, xend >> 4); 396462306a36Sopenharmony_ci i2c_w(sd, 0x19, ystart >> 3); 396562306a36Sopenharmony_ci i2c_w(sd, 0x1a, yend >> 3); 396662306a36Sopenharmony_ci return; 396762306a36Sopenharmony_ci case SEN_OV8610: 396862306a36Sopenharmony_ci /* For OV8610 qvga means qsvga */ 396962306a36Sopenharmony_ci i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); 397062306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 397162306a36Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 397262306a36Sopenharmony_ci i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */ 397362306a36Sopenharmony_ci i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */ 397462306a36Sopenharmony_ci break; 397562306a36Sopenharmony_ci case SEN_OV7610: 397662306a36Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 397762306a36Sopenharmony_ci i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); 397862306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 397962306a36Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 398062306a36Sopenharmony_ci break; 398162306a36Sopenharmony_ci case SEN_OV7620: 398262306a36Sopenharmony_ci case SEN_OV7620AE: 398362306a36Sopenharmony_ci case SEN_OV76BE: 398462306a36Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 398562306a36Sopenharmony_ci i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); 398662306a36Sopenharmony_ci i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); 398762306a36Sopenharmony_ci i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); 398862306a36Sopenharmony_ci i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); 398962306a36Sopenharmony_ci i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); 399062306a36Sopenharmony_ci i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); 399162306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 399262306a36Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 399362306a36Sopenharmony_ci if (sd->sensor == SEN_OV76BE) 399462306a36Sopenharmony_ci i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); 399562306a36Sopenharmony_ci break; 399662306a36Sopenharmony_ci case SEN_OV7640: 399762306a36Sopenharmony_ci case SEN_OV7648: 399862306a36Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 399962306a36Sopenharmony_ci i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); 400062306a36Sopenharmony_ci /* Setting this undocumented bit in qvga mode removes a very 400162306a36Sopenharmony_ci annoying vertical shaking of the image */ 400262306a36Sopenharmony_ci i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); 400362306a36Sopenharmony_ci /* Unknown */ 400462306a36Sopenharmony_ci i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); 400562306a36Sopenharmony_ci /* Allow higher automatic gain (to allow higher framerates) */ 400662306a36Sopenharmony_ci i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); 400762306a36Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ 400862306a36Sopenharmony_ci break; 400962306a36Sopenharmony_ci case SEN_OV7670: 401062306a36Sopenharmony_ci /* set COM7_FMT_VGA or COM7_FMT_QVGA 401162306a36Sopenharmony_ci * do we need to set anything else? 401262306a36Sopenharmony_ci * HSTART etc are set in set_ov_sensor_window itself */ 401362306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R12_COM7, 401462306a36Sopenharmony_ci qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, 401562306a36Sopenharmony_ci OV7670_COM7_FMT_MASK); 401662306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 401762306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB, 401862306a36Sopenharmony_ci OV7670_COM8_AWB); 401962306a36Sopenharmony_ci if (qvga) { /* QVGA from ov7670.c by 402062306a36Sopenharmony_ci * Jonathan Corbet */ 402162306a36Sopenharmony_ci xstart = 164; 402262306a36Sopenharmony_ci xend = 28; 402362306a36Sopenharmony_ci ystart = 14; 402462306a36Sopenharmony_ci yend = 494; 402562306a36Sopenharmony_ci } else { /* VGA */ 402662306a36Sopenharmony_ci xstart = 158; 402762306a36Sopenharmony_ci xend = 14; 402862306a36Sopenharmony_ci ystart = 10; 402962306a36Sopenharmony_ci yend = 490; 403062306a36Sopenharmony_ci } 403162306a36Sopenharmony_ci /* OV7670 hardware window registers are split across 403262306a36Sopenharmony_ci * multiple locations */ 403362306a36Sopenharmony_ci i2c_w(sd, OV7670_R17_HSTART, xstart >> 3); 403462306a36Sopenharmony_ci i2c_w(sd, OV7670_R18_HSTOP, xend >> 3); 403562306a36Sopenharmony_ci v = i2c_r(sd, OV7670_R32_HREF); 403662306a36Sopenharmony_ci v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); 403762306a36Sopenharmony_ci msleep(10); /* need to sleep between read and write to 403862306a36Sopenharmony_ci * same reg! */ 403962306a36Sopenharmony_ci i2c_w(sd, OV7670_R32_HREF, v); 404062306a36Sopenharmony_ci 404162306a36Sopenharmony_ci i2c_w(sd, OV7670_R19_VSTART, ystart >> 2); 404262306a36Sopenharmony_ci i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2); 404362306a36Sopenharmony_ci v = i2c_r(sd, OV7670_R03_VREF); 404462306a36Sopenharmony_ci v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); 404562306a36Sopenharmony_ci msleep(10); /* need to sleep between read and write to 404662306a36Sopenharmony_ci * same reg! */ 404762306a36Sopenharmony_ci i2c_w(sd, OV7670_R03_VREF, v); 404862306a36Sopenharmony_ci break; 404962306a36Sopenharmony_ci case SEN_OV6620: 405062306a36Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 405162306a36Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 405262306a36Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 405362306a36Sopenharmony_ci break; 405462306a36Sopenharmony_ci case SEN_OV6630: 405562306a36Sopenharmony_ci case SEN_OV66308AF: 405662306a36Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 405762306a36Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 405862306a36Sopenharmony_ci break; 405962306a36Sopenharmony_ci case SEN_OV9600: { 406062306a36Sopenharmony_ci const struct ov_i2c_regvals *vals; 406162306a36Sopenharmony_ci static const struct ov_i2c_regvals sxga_15[] = { 406262306a36Sopenharmony_ci {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75} 406362306a36Sopenharmony_ci }; 406462306a36Sopenharmony_ci static const struct ov_i2c_regvals sxga_7_5[] = { 406562306a36Sopenharmony_ci {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75} 406662306a36Sopenharmony_ci }; 406762306a36Sopenharmony_ci static const struct ov_i2c_regvals vga_30[] = { 406862306a36Sopenharmony_ci {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60} 406962306a36Sopenharmony_ci }; 407062306a36Sopenharmony_ci static const struct ov_i2c_regvals vga_15[] = { 407162306a36Sopenharmony_ci {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70} 407262306a36Sopenharmony_ci }; 407362306a36Sopenharmony_ci 407462306a36Sopenharmony_ci /* frame rates: 407562306a36Sopenharmony_ci * 15fps / 7.5 fps for 1280x1024 407662306a36Sopenharmony_ci * 30fps / 15fps for 640x480 407762306a36Sopenharmony_ci */ 407862306a36Sopenharmony_ci i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40); 407962306a36Sopenharmony_ci if (qvga) 408062306a36Sopenharmony_ci vals = sd->frame_rate < 30 ? vga_15 : vga_30; 408162306a36Sopenharmony_ci else 408262306a36Sopenharmony_ci vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15; 408362306a36Sopenharmony_ci write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15)); 408462306a36Sopenharmony_ci return; 408562306a36Sopenharmony_ci } 408662306a36Sopenharmony_ci default: 408762306a36Sopenharmony_ci return; 408862306a36Sopenharmony_ci } 408962306a36Sopenharmony_ci 409062306a36Sopenharmony_ci /******** Clock programming ********/ 409162306a36Sopenharmony_ci i2c_w(sd, 0x11, sd->clockdiv); 409262306a36Sopenharmony_ci} 409362306a36Sopenharmony_ci 409462306a36Sopenharmony_ci/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */ 409562306a36Sopenharmony_cistatic void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) 409662306a36Sopenharmony_ci{ 409762306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 409862306a36Sopenharmony_ci 409962306a36Sopenharmony_ci if (sd->gspca_dev.streaming) 410062306a36Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x0f); /* block stream */ 410162306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R1E_MVFP, 410262306a36Sopenharmony_ci OV7670_MVFP_MIRROR * hflip | OV7670_MVFP_VFLIP * vflip, 410362306a36Sopenharmony_ci OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); 410462306a36Sopenharmony_ci if (sd->gspca_dev.streaming) 410562306a36Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x00); /* restart stream */ 410662306a36Sopenharmony_ci} 410762306a36Sopenharmony_ci 410862306a36Sopenharmony_cistatic void set_ov_sensor_window(struct sd *sd) 410962306a36Sopenharmony_ci{ 411062306a36Sopenharmony_ci struct gspca_dev *gspca_dev; 411162306a36Sopenharmony_ci int qvga, crop; 411262306a36Sopenharmony_ci int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; 411362306a36Sopenharmony_ci 411462306a36Sopenharmony_ci /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ 411562306a36Sopenharmony_ci switch (sd->sensor) { 411662306a36Sopenharmony_ci case SEN_OV2610: 411762306a36Sopenharmony_ci case SEN_OV2610AE: 411862306a36Sopenharmony_ci case SEN_OV3610: 411962306a36Sopenharmony_ci case SEN_OV7670: 412062306a36Sopenharmony_ci case SEN_OV9600: 412162306a36Sopenharmony_ci mode_init_ov_sensor_regs(sd); 412262306a36Sopenharmony_ci return; 412362306a36Sopenharmony_ci case SEN_OV7660: 412462306a36Sopenharmony_ci ov519_set_mode(sd); 412562306a36Sopenharmony_ci ov519_set_fr(sd); 412662306a36Sopenharmony_ci return; 412762306a36Sopenharmony_ci } 412862306a36Sopenharmony_ci 412962306a36Sopenharmony_ci gspca_dev = &sd->gspca_dev; 413062306a36Sopenharmony_ci qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; 413162306a36Sopenharmony_ci crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; 413262306a36Sopenharmony_ci 413362306a36Sopenharmony_ci /* The different sensor ICs handle setting up of window differently. 413462306a36Sopenharmony_ci * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ 413562306a36Sopenharmony_ci switch (sd->sensor) { 413662306a36Sopenharmony_ci case SEN_OV8610: 413762306a36Sopenharmony_ci hwsbase = 0x1e; 413862306a36Sopenharmony_ci hwebase = 0x1e; 413962306a36Sopenharmony_ci vwsbase = 0x02; 414062306a36Sopenharmony_ci vwebase = 0x02; 414162306a36Sopenharmony_ci break; 414262306a36Sopenharmony_ci case SEN_OV7610: 414362306a36Sopenharmony_ci case SEN_OV76BE: 414462306a36Sopenharmony_ci hwsbase = 0x38; 414562306a36Sopenharmony_ci hwebase = 0x3a; 414662306a36Sopenharmony_ci vwsbase = vwebase = 0x05; 414762306a36Sopenharmony_ci break; 414862306a36Sopenharmony_ci case SEN_OV6620: 414962306a36Sopenharmony_ci case SEN_OV6630: 415062306a36Sopenharmony_ci case SEN_OV66308AF: 415162306a36Sopenharmony_ci hwsbase = 0x38; 415262306a36Sopenharmony_ci hwebase = 0x3a; 415362306a36Sopenharmony_ci vwsbase = 0x05; 415462306a36Sopenharmony_ci vwebase = 0x06; 415562306a36Sopenharmony_ci if (sd->sensor == SEN_OV66308AF && qvga) 415662306a36Sopenharmony_ci /* HDG: this fixes U and V getting swapped */ 415762306a36Sopenharmony_ci hwsbase++; 415862306a36Sopenharmony_ci if (crop) { 415962306a36Sopenharmony_ci hwsbase += 8; 416062306a36Sopenharmony_ci hwebase += 8; 416162306a36Sopenharmony_ci vwsbase += 11; 416262306a36Sopenharmony_ci vwebase += 11; 416362306a36Sopenharmony_ci } 416462306a36Sopenharmony_ci break; 416562306a36Sopenharmony_ci case SEN_OV7620: 416662306a36Sopenharmony_ci case SEN_OV7620AE: 416762306a36Sopenharmony_ci hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ 416862306a36Sopenharmony_ci hwebase = 0x2f; 416962306a36Sopenharmony_ci vwsbase = vwebase = 0x05; 417062306a36Sopenharmony_ci break; 417162306a36Sopenharmony_ci case SEN_OV7640: 417262306a36Sopenharmony_ci case SEN_OV7648: 417362306a36Sopenharmony_ci hwsbase = 0x1a; 417462306a36Sopenharmony_ci hwebase = 0x1a; 417562306a36Sopenharmony_ci vwsbase = vwebase = 0x03; 417662306a36Sopenharmony_ci break; 417762306a36Sopenharmony_ci default: 417862306a36Sopenharmony_ci return; 417962306a36Sopenharmony_ci } 418062306a36Sopenharmony_ci 418162306a36Sopenharmony_ci switch (sd->sensor) { 418262306a36Sopenharmony_ci case SEN_OV6620: 418362306a36Sopenharmony_ci case SEN_OV6630: 418462306a36Sopenharmony_ci case SEN_OV66308AF: 418562306a36Sopenharmony_ci if (qvga) { /* QCIF */ 418662306a36Sopenharmony_ci hwscale = 0; 418762306a36Sopenharmony_ci vwscale = 0; 418862306a36Sopenharmony_ci } else { /* CIF */ 418962306a36Sopenharmony_ci hwscale = 1; 419062306a36Sopenharmony_ci vwscale = 1; /* The datasheet says 0; 419162306a36Sopenharmony_ci * it's wrong */ 419262306a36Sopenharmony_ci } 419362306a36Sopenharmony_ci break; 419462306a36Sopenharmony_ci case SEN_OV8610: 419562306a36Sopenharmony_ci if (qvga) { /* QSVGA */ 419662306a36Sopenharmony_ci hwscale = 1; 419762306a36Sopenharmony_ci vwscale = 1; 419862306a36Sopenharmony_ci } else { /* SVGA */ 419962306a36Sopenharmony_ci hwscale = 2; 420062306a36Sopenharmony_ci vwscale = 2; 420162306a36Sopenharmony_ci } 420262306a36Sopenharmony_ci break; 420362306a36Sopenharmony_ci default: /* SEN_OV7xx0 */ 420462306a36Sopenharmony_ci if (qvga) { /* QVGA */ 420562306a36Sopenharmony_ci hwscale = 1; 420662306a36Sopenharmony_ci vwscale = 0; 420762306a36Sopenharmony_ci } else { /* VGA */ 420862306a36Sopenharmony_ci hwscale = 2; 420962306a36Sopenharmony_ci vwscale = 1; 421062306a36Sopenharmony_ci } 421162306a36Sopenharmony_ci } 421262306a36Sopenharmony_ci 421362306a36Sopenharmony_ci mode_init_ov_sensor_regs(sd); 421462306a36Sopenharmony_ci 421562306a36Sopenharmony_ci i2c_w(sd, 0x17, hwsbase); 421662306a36Sopenharmony_ci i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); 421762306a36Sopenharmony_ci i2c_w(sd, 0x19, vwsbase); 421862306a36Sopenharmony_ci i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); 421962306a36Sopenharmony_ci} 422062306a36Sopenharmony_ci 422162306a36Sopenharmony_ci/* -- start the camera -- */ 422262306a36Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev) 422362306a36Sopenharmony_ci{ 422462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 422562306a36Sopenharmony_ci 422662306a36Sopenharmony_ci /* Default for most bridges, allow bridge_mode_init_regs to override */ 422762306a36Sopenharmony_ci sd->sensor_width = sd->gspca_dev.pixfmt.width; 422862306a36Sopenharmony_ci sd->sensor_height = sd->gspca_dev.pixfmt.height; 422962306a36Sopenharmony_ci 423062306a36Sopenharmony_ci switch (sd->bridge) { 423162306a36Sopenharmony_ci case BRIDGE_OV511: 423262306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 423362306a36Sopenharmony_ci ov511_mode_init_regs(sd); 423462306a36Sopenharmony_ci break; 423562306a36Sopenharmony_ci case BRIDGE_OV518: 423662306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 423762306a36Sopenharmony_ci ov518_mode_init_regs(sd); 423862306a36Sopenharmony_ci break; 423962306a36Sopenharmony_ci case BRIDGE_OV519: 424062306a36Sopenharmony_ci ov519_mode_init_regs(sd); 424162306a36Sopenharmony_ci break; 424262306a36Sopenharmony_ci /* case BRIDGE_OVFX2: nothing to do */ 424362306a36Sopenharmony_ci case BRIDGE_W9968CF: 424462306a36Sopenharmony_ci w9968cf_mode_init_regs(sd); 424562306a36Sopenharmony_ci break; 424662306a36Sopenharmony_ci } 424762306a36Sopenharmony_ci 424862306a36Sopenharmony_ci set_ov_sensor_window(sd); 424962306a36Sopenharmony_ci 425062306a36Sopenharmony_ci /* Force clear snapshot state in case the snapshot button was 425162306a36Sopenharmony_ci pressed while we weren't streaming */ 425262306a36Sopenharmony_ci sd->snapshot_needs_reset = 1; 425362306a36Sopenharmony_ci sd_reset_snapshot(gspca_dev); 425462306a36Sopenharmony_ci 425562306a36Sopenharmony_ci sd->first_frame = 3; 425662306a36Sopenharmony_ci 425762306a36Sopenharmony_ci ov51x_restart(sd); 425862306a36Sopenharmony_ci ov51x_led_control(sd, 1); 425962306a36Sopenharmony_ci return gspca_dev->usb_err; 426062306a36Sopenharmony_ci} 426162306a36Sopenharmony_ci 426262306a36Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev) 426362306a36Sopenharmony_ci{ 426462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 426562306a36Sopenharmony_ci 426662306a36Sopenharmony_ci ov51x_stop(sd); 426762306a36Sopenharmony_ci ov51x_led_control(sd, 0); 426862306a36Sopenharmony_ci} 426962306a36Sopenharmony_ci 427062306a36Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev) 427162306a36Sopenharmony_ci{ 427262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 427362306a36Sopenharmony_ci 427462306a36Sopenharmony_ci if (!sd->gspca_dev.present) 427562306a36Sopenharmony_ci return; 427662306a36Sopenharmony_ci if (sd->bridge == BRIDGE_W9968CF) 427762306a36Sopenharmony_ci w9968cf_stop0(sd); 427862306a36Sopenharmony_ci 427962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT) 428062306a36Sopenharmony_ci /* If the last button state is pressed, release it now! */ 428162306a36Sopenharmony_ci if (sd->snapshot_pressed) { 428262306a36Sopenharmony_ci input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); 428362306a36Sopenharmony_ci input_sync(gspca_dev->input_dev); 428462306a36Sopenharmony_ci sd->snapshot_pressed = 0; 428562306a36Sopenharmony_ci } 428662306a36Sopenharmony_ci#endif 428762306a36Sopenharmony_ci if (sd->bridge == BRIDGE_OV519) 428862306a36Sopenharmony_ci reg_w(sd, OV519_R57_SNAPSHOT, 0x23); 428962306a36Sopenharmony_ci} 429062306a36Sopenharmony_ci 429162306a36Sopenharmony_cistatic void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) 429262306a36Sopenharmony_ci{ 429362306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 429462306a36Sopenharmony_ci 429562306a36Sopenharmony_ci if (sd->snapshot_pressed != state) { 429662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT) 429762306a36Sopenharmony_ci input_report_key(gspca_dev->input_dev, KEY_CAMERA, state); 429862306a36Sopenharmony_ci input_sync(gspca_dev->input_dev); 429962306a36Sopenharmony_ci#endif 430062306a36Sopenharmony_ci if (state) 430162306a36Sopenharmony_ci sd->snapshot_needs_reset = 1; 430262306a36Sopenharmony_ci 430362306a36Sopenharmony_ci sd->snapshot_pressed = state; 430462306a36Sopenharmony_ci } else { 430562306a36Sopenharmony_ci /* On the ov511 / ov519 we need to reset the button state 430662306a36Sopenharmony_ci multiple times, as resetting does not work as long as the 430762306a36Sopenharmony_ci button stays pressed */ 430862306a36Sopenharmony_ci switch (sd->bridge) { 430962306a36Sopenharmony_ci case BRIDGE_OV511: 431062306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 431162306a36Sopenharmony_ci case BRIDGE_OV519: 431262306a36Sopenharmony_ci if (state) 431362306a36Sopenharmony_ci sd->snapshot_needs_reset = 1; 431462306a36Sopenharmony_ci break; 431562306a36Sopenharmony_ci } 431662306a36Sopenharmony_ci } 431762306a36Sopenharmony_ci} 431862306a36Sopenharmony_ci 431962306a36Sopenharmony_cistatic void ov511_pkt_scan(struct gspca_dev *gspca_dev, 432062306a36Sopenharmony_ci u8 *in, /* isoc packet */ 432162306a36Sopenharmony_ci int len) /* iso packet length */ 432262306a36Sopenharmony_ci{ 432362306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 432462306a36Sopenharmony_ci 432562306a36Sopenharmony_ci /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th 432662306a36Sopenharmony_ci * byte non-zero. The EOF packet has image width/height in the 432762306a36Sopenharmony_ci * 10th and 11th bytes. The 9th byte is given as follows: 432862306a36Sopenharmony_ci * 432962306a36Sopenharmony_ci * bit 7: EOF 433062306a36Sopenharmony_ci * 6: compression enabled 433162306a36Sopenharmony_ci * 5: 422/420/400 modes 433262306a36Sopenharmony_ci * 4: 422/420/400 modes 433362306a36Sopenharmony_ci * 3: 1 433462306a36Sopenharmony_ci * 2: snapshot button on 433562306a36Sopenharmony_ci * 1: snapshot frame 433662306a36Sopenharmony_ci * 0: even/odd field 433762306a36Sopenharmony_ci */ 433862306a36Sopenharmony_ci if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && 433962306a36Sopenharmony_ci (in[8] & 0x08)) { 434062306a36Sopenharmony_ci ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1); 434162306a36Sopenharmony_ci if (in[8] & 0x80) { 434262306a36Sopenharmony_ci /* Frame end */ 434362306a36Sopenharmony_ci if ((in[9] + 1) * 8 != gspca_dev->pixfmt.width || 434462306a36Sopenharmony_ci (in[10] + 1) * 8 != gspca_dev->pixfmt.height) { 434562306a36Sopenharmony_ci gspca_err(gspca_dev, "Invalid frame size, got: %dx%d, requested: %dx%d\n", 434662306a36Sopenharmony_ci (in[9] + 1) * 8, (in[10] + 1) * 8, 434762306a36Sopenharmony_ci gspca_dev->pixfmt.width, 434862306a36Sopenharmony_ci gspca_dev->pixfmt.height); 434962306a36Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 435062306a36Sopenharmony_ci return; 435162306a36Sopenharmony_ci } 435262306a36Sopenharmony_ci /* Add 11 byte footer to frame, might be useful */ 435362306a36Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, in, 11); 435462306a36Sopenharmony_ci return; 435562306a36Sopenharmony_ci } else { 435662306a36Sopenharmony_ci /* Frame start */ 435762306a36Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0); 435862306a36Sopenharmony_ci sd->packet_nr = 0; 435962306a36Sopenharmony_ci } 436062306a36Sopenharmony_ci } 436162306a36Sopenharmony_ci 436262306a36Sopenharmony_ci /* Ignore the packet number */ 436362306a36Sopenharmony_ci len--; 436462306a36Sopenharmony_ci 436562306a36Sopenharmony_ci /* intermediate packet */ 436662306a36Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, in, len); 436762306a36Sopenharmony_ci} 436862306a36Sopenharmony_ci 436962306a36Sopenharmony_cistatic void ov518_pkt_scan(struct gspca_dev *gspca_dev, 437062306a36Sopenharmony_ci u8 *data, /* isoc packet */ 437162306a36Sopenharmony_ci int len) /* iso packet length */ 437262306a36Sopenharmony_ci{ 437362306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 437462306a36Sopenharmony_ci 437562306a36Sopenharmony_ci /* A false positive here is likely, until OVT gives me 437662306a36Sopenharmony_ci * the definitive SOF/EOF format */ 437762306a36Sopenharmony_ci if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { 437862306a36Sopenharmony_ci ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1); 437962306a36Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 438062306a36Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); 438162306a36Sopenharmony_ci sd->packet_nr = 0; 438262306a36Sopenharmony_ci } 438362306a36Sopenharmony_ci 438462306a36Sopenharmony_ci if (gspca_dev->last_packet_type == DISCARD_PACKET) 438562306a36Sopenharmony_ci return; 438662306a36Sopenharmony_ci 438762306a36Sopenharmony_ci /* Does this device use packet numbers ? */ 438862306a36Sopenharmony_ci if (len & 7) { 438962306a36Sopenharmony_ci len--; 439062306a36Sopenharmony_ci if (sd->packet_nr == data[len]) 439162306a36Sopenharmony_ci sd->packet_nr++; 439262306a36Sopenharmony_ci /* The last few packets of the frame (which are all 0's 439362306a36Sopenharmony_ci except that they may contain part of the footer), are 439462306a36Sopenharmony_ci numbered 0 */ 439562306a36Sopenharmony_ci else if (sd->packet_nr == 0 || data[len]) { 439662306a36Sopenharmony_ci gspca_err(gspca_dev, "Invalid packet nr: %d (expect: %d)\n", 439762306a36Sopenharmony_ci (int)data[len], (int)sd->packet_nr); 439862306a36Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 439962306a36Sopenharmony_ci return; 440062306a36Sopenharmony_ci } 440162306a36Sopenharmony_ci } 440262306a36Sopenharmony_ci 440362306a36Sopenharmony_ci /* intermediate packet */ 440462306a36Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 440562306a36Sopenharmony_ci} 440662306a36Sopenharmony_ci 440762306a36Sopenharmony_cistatic void ov519_pkt_scan(struct gspca_dev *gspca_dev, 440862306a36Sopenharmony_ci u8 *data, /* isoc packet */ 440962306a36Sopenharmony_ci int len) /* iso packet length */ 441062306a36Sopenharmony_ci{ 441162306a36Sopenharmony_ci /* Header of ov519 is 16 bytes: 441262306a36Sopenharmony_ci * Byte Value Description 441362306a36Sopenharmony_ci * 0 0xff magic 441462306a36Sopenharmony_ci * 1 0xff magic 441562306a36Sopenharmony_ci * 2 0xff magic 441662306a36Sopenharmony_ci * 3 0xXX 0x50 = SOF, 0x51 = EOF 441762306a36Sopenharmony_ci * 9 0xXX 0x01 initial frame without data, 441862306a36Sopenharmony_ci * 0x00 standard frame with image 441962306a36Sopenharmony_ci * 14 Lo in EOF: length of image data / 8 442062306a36Sopenharmony_ci * 15 Hi 442162306a36Sopenharmony_ci */ 442262306a36Sopenharmony_ci 442362306a36Sopenharmony_ci if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { 442462306a36Sopenharmony_ci switch (data[3]) { 442562306a36Sopenharmony_ci case 0x50: /* start of frame */ 442662306a36Sopenharmony_ci /* Don't check the button state here, as the state 442762306a36Sopenharmony_ci usually (always ?) changes at EOF and checking it 442862306a36Sopenharmony_ci here leads to unnecessary snapshot state resets. */ 442962306a36Sopenharmony_ci#define HDRSZ 16 443062306a36Sopenharmony_ci data += HDRSZ; 443162306a36Sopenharmony_ci len -= HDRSZ; 443262306a36Sopenharmony_ci#undef HDRSZ 443362306a36Sopenharmony_ci if (data[0] == 0xff || data[1] == 0xd8) 443462306a36Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, 443562306a36Sopenharmony_ci data, len); 443662306a36Sopenharmony_ci else 443762306a36Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 443862306a36Sopenharmony_ci return; 443962306a36Sopenharmony_ci case 0x51: /* end of frame */ 444062306a36Sopenharmony_ci ov51x_handle_button(gspca_dev, data[11] & 1); 444162306a36Sopenharmony_ci if (data[9] != 0) 444262306a36Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 444362306a36Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, 444462306a36Sopenharmony_ci NULL, 0); 444562306a36Sopenharmony_ci return; 444662306a36Sopenharmony_ci } 444762306a36Sopenharmony_ci } 444862306a36Sopenharmony_ci 444962306a36Sopenharmony_ci /* intermediate packet */ 445062306a36Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 445162306a36Sopenharmony_ci} 445262306a36Sopenharmony_ci 445362306a36Sopenharmony_cistatic void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, 445462306a36Sopenharmony_ci u8 *data, /* isoc packet */ 445562306a36Sopenharmony_ci int len) /* iso packet length */ 445662306a36Sopenharmony_ci{ 445762306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 445862306a36Sopenharmony_ci 445962306a36Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 446062306a36Sopenharmony_ci 446162306a36Sopenharmony_ci /* A short read signals EOF */ 446262306a36Sopenharmony_ci if (len < gspca_dev->cam.bulk_size) { 446362306a36Sopenharmony_ci /* If the frame is short, and it is one of the first ones 446462306a36Sopenharmony_ci the sensor and bridge are still syncing, so drop it. */ 446562306a36Sopenharmony_ci if (sd->first_frame) { 446662306a36Sopenharmony_ci sd->first_frame--; 446762306a36Sopenharmony_ci if (gspca_dev->image_len < 446862306a36Sopenharmony_ci sd->gspca_dev.pixfmt.width * 446962306a36Sopenharmony_ci sd->gspca_dev.pixfmt.height) 447062306a36Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 447162306a36Sopenharmony_ci } 447262306a36Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 447362306a36Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); 447462306a36Sopenharmony_ci } 447562306a36Sopenharmony_ci} 447662306a36Sopenharmony_ci 447762306a36Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev, 447862306a36Sopenharmony_ci u8 *data, /* isoc packet */ 447962306a36Sopenharmony_ci int len) /* iso packet length */ 448062306a36Sopenharmony_ci{ 448162306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 448262306a36Sopenharmony_ci 448362306a36Sopenharmony_ci switch (sd->bridge) { 448462306a36Sopenharmony_ci case BRIDGE_OV511: 448562306a36Sopenharmony_ci case BRIDGE_OV511PLUS: 448662306a36Sopenharmony_ci ov511_pkt_scan(gspca_dev, data, len); 448762306a36Sopenharmony_ci break; 448862306a36Sopenharmony_ci case BRIDGE_OV518: 448962306a36Sopenharmony_ci case BRIDGE_OV518PLUS: 449062306a36Sopenharmony_ci ov518_pkt_scan(gspca_dev, data, len); 449162306a36Sopenharmony_ci break; 449262306a36Sopenharmony_ci case BRIDGE_OV519: 449362306a36Sopenharmony_ci ov519_pkt_scan(gspca_dev, data, len); 449462306a36Sopenharmony_ci break; 449562306a36Sopenharmony_ci case BRIDGE_OVFX2: 449662306a36Sopenharmony_ci ovfx2_pkt_scan(gspca_dev, data, len); 449762306a36Sopenharmony_ci break; 449862306a36Sopenharmony_ci case BRIDGE_W9968CF: 449962306a36Sopenharmony_ci w9968cf_pkt_scan(gspca_dev, data, len); 450062306a36Sopenharmony_ci break; 450162306a36Sopenharmony_ci } 450262306a36Sopenharmony_ci} 450362306a36Sopenharmony_ci 450462306a36Sopenharmony_ci/* -- management routines -- */ 450562306a36Sopenharmony_ci 450662306a36Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev, s32 val) 450762306a36Sopenharmony_ci{ 450862306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 450962306a36Sopenharmony_ci static const struct ov_i2c_regvals brit_7660[][7] = { 451062306a36Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90}, 451162306a36Sopenharmony_ci {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}}, 451262306a36Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1}, 451362306a36Sopenharmony_ci {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}}, 451462306a36Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2}, 451562306a36Sopenharmony_ci {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}}, 451662306a36Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3}, 451762306a36Sopenharmony_ci {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}}, 451862306a36Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3}, 451962306a36Sopenharmony_ci {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}}, 452062306a36Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3}, 452162306a36Sopenharmony_ci {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}}, 452262306a36Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4}, 452362306a36Sopenharmony_ci {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}} 452462306a36Sopenharmony_ci }; 452562306a36Sopenharmony_ci 452662306a36Sopenharmony_ci switch (sd->sensor) { 452762306a36Sopenharmony_ci case SEN_OV8610: 452862306a36Sopenharmony_ci case SEN_OV7610: 452962306a36Sopenharmony_ci case SEN_OV76BE: 453062306a36Sopenharmony_ci case SEN_OV6620: 453162306a36Sopenharmony_ci case SEN_OV6630: 453262306a36Sopenharmony_ci case SEN_OV66308AF: 453362306a36Sopenharmony_ci case SEN_OV7640: 453462306a36Sopenharmony_ci case SEN_OV7648: 453562306a36Sopenharmony_ci i2c_w(sd, OV7610_REG_BRT, val); 453662306a36Sopenharmony_ci break; 453762306a36Sopenharmony_ci case SEN_OV7620: 453862306a36Sopenharmony_ci case SEN_OV7620AE: 453962306a36Sopenharmony_ci i2c_w(sd, OV7610_REG_BRT, val); 454062306a36Sopenharmony_ci break; 454162306a36Sopenharmony_ci case SEN_OV7660: 454262306a36Sopenharmony_ci write_i2c_regvals(sd, brit_7660[val], 454362306a36Sopenharmony_ci ARRAY_SIZE(brit_7660[0])); 454462306a36Sopenharmony_ci break; 454562306a36Sopenharmony_ci case SEN_OV7670: 454662306a36Sopenharmony_ci/*win trace 454762306a36Sopenharmony_ci * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ 454862306a36Sopenharmony_ci i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val)); 454962306a36Sopenharmony_ci break; 455062306a36Sopenharmony_ci } 455162306a36Sopenharmony_ci} 455262306a36Sopenharmony_ci 455362306a36Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev, s32 val) 455462306a36Sopenharmony_ci{ 455562306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 455662306a36Sopenharmony_ci static const struct ov_i2c_regvals contrast_7660[][31] = { 455762306a36Sopenharmony_ci {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0}, 455862306a36Sopenharmony_ci {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30}, 455962306a36Sopenharmony_ci {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24}, 456062306a36Sopenharmony_ci {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34}, 456162306a36Sopenharmony_ci {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65}, 456262306a36Sopenharmony_ci {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83}, 456362306a36Sopenharmony_ci {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f}, 456462306a36Sopenharmony_ci {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}}, 456562306a36Sopenharmony_ci {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94}, 456662306a36Sopenharmony_ci {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30}, 456762306a36Sopenharmony_ci {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24}, 456862306a36Sopenharmony_ci {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31}, 456962306a36Sopenharmony_ci {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62}, 457062306a36Sopenharmony_ci {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81}, 457162306a36Sopenharmony_ci {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1}, 457262306a36Sopenharmony_ci {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}}, 457362306a36Sopenharmony_ci {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84}, 457462306a36Sopenharmony_ci {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40}, 457562306a36Sopenharmony_ci {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24}, 457662306a36Sopenharmony_ci {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34}, 457762306a36Sopenharmony_ci {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d}, 457862306a36Sopenharmony_ci {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81}, 457962306a36Sopenharmony_ci {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e}, 458062306a36Sopenharmony_ci {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}}, 458162306a36Sopenharmony_ci {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70}, 458262306a36Sopenharmony_ci {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48}, 458362306a36Sopenharmony_ci {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34}, 458462306a36Sopenharmony_ci {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22}, 458562306a36Sopenharmony_ci {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58}, 458662306a36Sopenharmony_ci {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80}, 458762306a36Sopenharmony_ci {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9}, 458862306a36Sopenharmony_ci {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}}, 458962306a36Sopenharmony_ci {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80}, 459062306a36Sopenharmony_ci {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60}, 459162306a36Sopenharmony_ci {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38}, 459262306a36Sopenharmony_ci {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e}, 459362306a36Sopenharmony_ci {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46}, 459462306a36Sopenharmony_ci {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c}, 459562306a36Sopenharmony_ci {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4}, 459662306a36Sopenharmony_ci {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}}, 459762306a36Sopenharmony_ci {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80}, 459862306a36Sopenharmony_ci {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30}, 459962306a36Sopenharmony_ci {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50}, 460062306a36Sopenharmony_ci {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08}, 460162306a36Sopenharmony_ci {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a}, 460262306a36Sopenharmony_ci {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b}, 460362306a36Sopenharmony_ci {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3}, 460462306a36Sopenharmony_ci {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}}, 460562306a36Sopenharmony_ci {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60}, 460662306a36Sopenharmony_ci {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8}, 460762306a36Sopenharmony_ci {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c}, 460862306a36Sopenharmony_ci {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04}, 460962306a36Sopenharmony_ci {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22}, 461062306a36Sopenharmony_ci {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b}, 461162306a36Sopenharmony_ci {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde}, 461262306a36Sopenharmony_ci {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}}, 461362306a36Sopenharmony_ci }; 461462306a36Sopenharmony_ci 461562306a36Sopenharmony_ci switch (sd->sensor) { 461662306a36Sopenharmony_ci case SEN_OV7610: 461762306a36Sopenharmony_ci case SEN_OV6620: 461862306a36Sopenharmony_ci i2c_w(sd, OV7610_REG_CNT, val); 461962306a36Sopenharmony_ci break; 462062306a36Sopenharmony_ci case SEN_OV6630: 462162306a36Sopenharmony_ci case SEN_OV66308AF: 462262306a36Sopenharmony_ci i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); 462362306a36Sopenharmony_ci break; 462462306a36Sopenharmony_ci case SEN_OV8610: { 462562306a36Sopenharmony_ci static const u8 ctab[] = { 462662306a36Sopenharmony_ci 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f 462762306a36Sopenharmony_ci }; 462862306a36Sopenharmony_ci 462962306a36Sopenharmony_ci /* Use Y gamma control instead. Bit 0 enables it. */ 463062306a36Sopenharmony_ci i2c_w(sd, 0x64, ctab[val >> 5]); 463162306a36Sopenharmony_ci break; 463262306a36Sopenharmony_ci } 463362306a36Sopenharmony_ci case SEN_OV7620: 463462306a36Sopenharmony_ci case SEN_OV7620AE: { 463562306a36Sopenharmony_ci static const u8 ctab[] = { 463662306a36Sopenharmony_ci 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, 463762306a36Sopenharmony_ci 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff 463862306a36Sopenharmony_ci }; 463962306a36Sopenharmony_ci 464062306a36Sopenharmony_ci /* Use Y gamma control instead. Bit 0 enables it. */ 464162306a36Sopenharmony_ci i2c_w(sd, 0x64, ctab[val >> 4]); 464262306a36Sopenharmony_ci break; 464362306a36Sopenharmony_ci } 464462306a36Sopenharmony_ci case SEN_OV7660: 464562306a36Sopenharmony_ci write_i2c_regvals(sd, contrast_7660[val], 464662306a36Sopenharmony_ci ARRAY_SIZE(contrast_7660[0])); 464762306a36Sopenharmony_ci break; 464862306a36Sopenharmony_ci case SEN_OV7670: 464962306a36Sopenharmony_ci /* check that this isn't just the same as ov7610 */ 465062306a36Sopenharmony_ci i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); 465162306a36Sopenharmony_ci break; 465262306a36Sopenharmony_ci } 465362306a36Sopenharmony_ci} 465462306a36Sopenharmony_ci 465562306a36Sopenharmony_cistatic void setexposure(struct gspca_dev *gspca_dev, s32 val) 465662306a36Sopenharmony_ci{ 465762306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 465862306a36Sopenharmony_ci 465962306a36Sopenharmony_ci i2c_w(sd, 0x10, val); 466062306a36Sopenharmony_ci} 466162306a36Sopenharmony_ci 466262306a36Sopenharmony_cistatic void setcolors(struct gspca_dev *gspca_dev, s32 val) 466362306a36Sopenharmony_ci{ 466462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 466562306a36Sopenharmony_ci static const struct ov_i2c_regvals colors_7660[][6] = { 466662306a36Sopenharmony_ci {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a}, 466762306a36Sopenharmony_ci {0x53, 0x19}, {0x54, 0x23}}, 466862306a36Sopenharmony_ci {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11}, 466962306a36Sopenharmony_ci {0x53, 0x2c}, {0x54, 0x3e}}, 467062306a36Sopenharmony_ci {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19}, 467162306a36Sopenharmony_ci {0x53, 0x40}, {0x54, 0x59}}, 467262306a36Sopenharmony_ci {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20}, 467362306a36Sopenharmony_ci {0x53, 0x53}, {0x54, 0x73}}, 467462306a36Sopenharmony_ci {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28}, 467562306a36Sopenharmony_ci {0x53, 0x66}, {0x54, 0x8e}}, 467662306a36Sopenharmony_ci }; 467762306a36Sopenharmony_ci 467862306a36Sopenharmony_ci switch (sd->sensor) { 467962306a36Sopenharmony_ci case SEN_OV8610: 468062306a36Sopenharmony_ci case SEN_OV7610: 468162306a36Sopenharmony_ci case SEN_OV76BE: 468262306a36Sopenharmony_ci case SEN_OV6620: 468362306a36Sopenharmony_ci case SEN_OV6630: 468462306a36Sopenharmony_ci case SEN_OV66308AF: 468562306a36Sopenharmony_ci i2c_w(sd, OV7610_REG_SAT, val); 468662306a36Sopenharmony_ci break; 468762306a36Sopenharmony_ci case SEN_OV7620: 468862306a36Sopenharmony_ci case SEN_OV7620AE: 468962306a36Sopenharmony_ci /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ 469062306a36Sopenharmony_ci/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e); 469162306a36Sopenharmony_ci if (rc < 0) 469262306a36Sopenharmony_ci goto out; */ 469362306a36Sopenharmony_ci i2c_w(sd, OV7610_REG_SAT, val); 469462306a36Sopenharmony_ci break; 469562306a36Sopenharmony_ci case SEN_OV7640: 469662306a36Sopenharmony_ci case SEN_OV7648: 469762306a36Sopenharmony_ci i2c_w(sd, OV7610_REG_SAT, val & 0xf0); 469862306a36Sopenharmony_ci break; 469962306a36Sopenharmony_ci case SEN_OV7660: 470062306a36Sopenharmony_ci write_i2c_regvals(sd, colors_7660[val], 470162306a36Sopenharmony_ci ARRAY_SIZE(colors_7660[0])); 470262306a36Sopenharmony_ci break; 470362306a36Sopenharmony_ci case SEN_OV7670: 470462306a36Sopenharmony_ci /* supported later once I work out how to do it 470562306a36Sopenharmony_ci * transparently fail now! */ 470662306a36Sopenharmony_ci /* set REG_COM13 values for UV sat auto mode */ 470762306a36Sopenharmony_ci break; 470862306a36Sopenharmony_ci } 470962306a36Sopenharmony_ci} 471062306a36Sopenharmony_ci 471162306a36Sopenharmony_cistatic void setautobright(struct gspca_dev *gspca_dev, s32 val) 471262306a36Sopenharmony_ci{ 471362306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 471462306a36Sopenharmony_ci 471562306a36Sopenharmony_ci i2c_w_mask(sd, 0x2d, val ? 0x10 : 0x00, 0x10); 471662306a36Sopenharmony_ci} 471762306a36Sopenharmony_ci 471862306a36Sopenharmony_cistatic void setfreq_i(struct sd *sd, s32 val) 471962306a36Sopenharmony_ci{ 472062306a36Sopenharmony_ci if (sd->sensor == SEN_OV7660 472162306a36Sopenharmony_ci || sd->sensor == SEN_OV7670) { 472262306a36Sopenharmony_ci switch (val) { 472362306a36Sopenharmony_ci case 0: /* Banding filter disabled */ 472462306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); 472562306a36Sopenharmony_ci break; 472662306a36Sopenharmony_ci case 1: /* 50 hz */ 472762306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, 472862306a36Sopenharmony_ci OV7670_COM8_BFILT); 472962306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18); 473062306a36Sopenharmony_ci break; 473162306a36Sopenharmony_ci case 2: /* 60 hz */ 473262306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, 473362306a36Sopenharmony_ci OV7670_COM8_BFILT); 473462306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18); 473562306a36Sopenharmony_ci break; 473662306a36Sopenharmony_ci case 3: /* Auto hz - ov7670 only */ 473762306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, 473862306a36Sopenharmony_ci OV7670_COM8_BFILT); 473962306a36Sopenharmony_ci i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO, 474062306a36Sopenharmony_ci 0x18); 474162306a36Sopenharmony_ci break; 474262306a36Sopenharmony_ci } 474362306a36Sopenharmony_ci } else { 474462306a36Sopenharmony_ci switch (val) { 474562306a36Sopenharmony_ci case 0: /* Banding filter disabled */ 474662306a36Sopenharmony_ci i2c_w_mask(sd, 0x2d, 0x00, 0x04); 474762306a36Sopenharmony_ci i2c_w_mask(sd, 0x2a, 0x00, 0x80); 474862306a36Sopenharmony_ci break; 474962306a36Sopenharmony_ci case 1: /* 50 hz (filter on and framerate adj) */ 475062306a36Sopenharmony_ci i2c_w_mask(sd, 0x2d, 0x04, 0x04); 475162306a36Sopenharmony_ci i2c_w_mask(sd, 0x2a, 0x80, 0x80); 475262306a36Sopenharmony_ci /* 20 fps -> 16.667 fps */ 475362306a36Sopenharmony_ci if (sd->sensor == SEN_OV6620 || 475462306a36Sopenharmony_ci sd->sensor == SEN_OV6630 || 475562306a36Sopenharmony_ci sd->sensor == SEN_OV66308AF) 475662306a36Sopenharmony_ci i2c_w(sd, 0x2b, 0x5e); 475762306a36Sopenharmony_ci else 475862306a36Sopenharmony_ci i2c_w(sd, 0x2b, 0xac); 475962306a36Sopenharmony_ci break; 476062306a36Sopenharmony_ci case 2: /* 60 hz (filter on, ...) */ 476162306a36Sopenharmony_ci i2c_w_mask(sd, 0x2d, 0x04, 0x04); 476262306a36Sopenharmony_ci if (sd->sensor == SEN_OV6620 || 476362306a36Sopenharmony_ci sd->sensor == SEN_OV6630 || 476462306a36Sopenharmony_ci sd->sensor == SEN_OV66308AF) { 476562306a36Sopenharmony_ci /* 20 fps -> 15 fps */ 476662306a36Sopenharmony_ci i2c_w_mask(sd, 0x2a, 0x80, 0x80); 476762306a36Sopenharmony_ci i2c_w(sd, 0x2b, 0xa8); 476862306a36Sopenharmony_ci } else { 476962306a36Sopenharmony_ci /* no framerate adj. */ 477062306a36Sopenharmony_ci i2c_w_mask(sd, 0x2a, 0x00, 0x80); 477162306a36Sopenharmony_ci } 477262306a36Sopenharmony_ci break; 477362306a36Sopenharmony_ci } 477462306a36Sopenharmony_ci } 477562306a36Sopenharmony_ci} 477662306a36Sopenharmony_ci 477762306a36Sopenharmony_cistatic void setfreq(struct gspca_dev *gspca_dev, s32 val) 477862306a36Sopenharmony_ci{ 477962306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 478062306a36Sopenharmony_ci 478162306a36Sopenharmony_ci setfreq_i(sd, val); 478262306a36Sopenharmony_ci 478362306a36Sopenharmony_ci /* Ugly but necessary */ 478462306a36Sopenharmony_ci if (sd->bridge == BRIDGE_W9968CF) 478562306a36Sopenharmony_ci w9968cf_set_crop_window(sd); 478662306a36Sopenharmony_ci} 478762306a36Sopenharmony_ci 478862306a36Sopenharmony_cistatic int sd_get_jcomp(struct gspca_dev *gspca_dev, 478962306a36Sopenharmony_ci struct v4l2_jpegcompression *jcomp) 479062306a36Sopenharmony_ci{ 479162306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 479262306a36Sopenharmony_ci 479362306a36Sopenharmony_ci if (sd->bridge != BRIDGE_W9968CF) 479462306a36Sopenharmony_ci return -ENOTTY; 479562306a36Sopenharmony_ci 479662306a36Sopenharmony_ci memset(jcomp, 0, sizeof *jcomp); 479762306a36Sopenharmony_ci jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); 479862306a36Sopenharmony_ci jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT | 479962306a36Sopenharmony_ci V4L2_JPEG_MARKER_DRI; 480062306a36Sopenharmony_ci return 0; 480162306a36Sopenharmony_ci} 480262306a36Sopenharmony_ci 480362306a36Sopenharmony_cistatic int sd_set_jcomp(struct gspca_dev *gspca_dev, 480462306a36Sopenharmony_ci const struct v4l2_jpegcompression *jcomp) 480562306a36Sopenharmony_ci{ 480662306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 480762306a36Sopenharmony_ci 480862306a36Sopenharmony_ci if (sd->bridge != BRIDGE_W9968CF) 480962306a36Sopenharmony_ci return -ENOTTY; 481062306a36Sopenharmony_ci 481162306a36Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); 481262306a36Sopenharmony_ci return 0; 481362306a36Sopenharmony_ci} 481462306a36Sopenharmony_ci 481562306a36Sopenharmony_cistatic int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 481662306a36Sopenharmony_ci{ 481762306a36Sopenharmony_ci struct gspca_dev *gspca_dev = 481862306a36Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 481962306a36Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 482062306a36Sopenharmony_ci 482162306a36Sopenharmony_ci gspca_dev->usb_err = 0; 482262306a36Sopenharmony_ci 482362306a36Sopenharmony_ci switch (ctrl->id) { 482462306a36Sopenharmony_ci case V4L2_CID_AUTOGAIN: 482562306a36Sopenharmony_ci gspca_dev->exposure->val = i2c_r(sd, 0x10); 482662306a36Sopenharmony_ci break; 482762306a36Sopenharmony_ci } 482862306a36Sopenharmony_ci return 0; 482962306a36Sopenharmony_ci} 483062306a36Sopenharmony_ci 483162306a36Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl) 483262306a36Sopenharmony_ci{ 483362306a36Sopenharmony_ci struct gspca_dev *gspca_dev = 483462306a36Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 483562306a36Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 483662306a36Sopenharmony_ci 483762306a36Sopenharmony_ci gspca_dev->usb_err = 0; 483862306a36Sopenharmony_ci 483962306a36Sopenharmony_ci if (!gspca_dev->streaming) 484062306a36Sopenharmony_ci return 0; 484162306a36Sopenharmony_ci 484262306a36Sopenharmony_ci switch (ctrl->id) { 484362306a36Sopenharmony_ci case V4L2_CID_BRIGHTNESS: 484462306a36Sopenharmony_ci setbrightness(gspca_dev, ctrl->val); 484562306a36Sopenharmony_ci break; 484662306a36Sopenharmony_ci case V4L2_CID_CONTRAST: 484762306a36Sopenharmony_ci setcontrast(gspca_dev, ctrl->val); 484862306a36Sopenharmony_ci break; 484962306a36Sopenharmony_ci case V4L2_CID_POWER_LINE_FREQUENCY: 485062306a36Sopenharmony_ci setfreq(gspca_dev, ctrl->val); 485162306a36Sopenharmony_ci break; 485262306a36Sopenharmony_ci case V4L2_CID_AUTOBRIGHTNESS: 485362306a36Sopenharmony_ci if (ctrl->is_new) 485462306a36Sopenharmony_ci setautobright(gspca_dev, ctrl->val); 485562306a36Sopenharmony_ci if (!ctrl->val && sd->brightness->is_new) 485662306a36Sopenharmony_ci setbrightness(gspca_dev, sd->brightness->val); 485762306a36Sopenharmony_ci break; 485862306a36Sopenharmony_ci case V4L2_CID_SATURATION: 485962306a36Sopenharmony_ci setcolors(gspca_dev, ctrl->val); 486062306a36Sopenharmony_ci break; 486162306a36Sopenharmony_ci case V4L2_CID_HFLIP: 486262306a36Sopenharmony_ci sethvflip(gspca_dev, ctrl->val, sd->vflip->val); 486362306a36Sopenharmony_ci break; 486462306a36Sopenharmony_ci case V4L2_CID_AUTOGAIN: 486562306a36Sopenharmony_ci if (ctrl->is_new) 486662306a36Sopenharmony_ci setautogain(gspca_dev, ctrl->val); 486762306a36Sopenharmony_ci if (!ctrl->val && gspca_dev->exposure->is_new) 486862306a36Sopenharmony_ci setexposure(gspca_dev, gspca_dev->exposure->val); 486962306a36Sopenharmony_ci break; 487062306a36Sopenharmony_ci case V4L2_CID_JPEG_COMPRESSION_QUALITY: 487162306a36Sopenharmony_ci return -EBUSY; /* Should never happen, as we grab the ctrl */ 487262306a36Sopenharmony_ci } 487362306a36Sopenharmony_ci return gspca_dev->usb_err; 487462306a36Sopenharmony_ci} 487562306a36Sopenharmony_ci 487662306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = { 487762306a36Sopenharmony_ci .g_volatile_ctrl = sd_g_volatile_ctrl, 487862306a36Sopenharmony_ci .s_ctrl = sd_s_ctrl, 487962306a36Sopenharmony_ci}; 488062306a36Sopenharmony_ci 488162306a36Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev) 488262306a36Sopenharmony_ci{ 488362306a36Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 488462306a36Sopenharmony_ci struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 488562306a36Sopenharmony_ci 488662306a36Sopenharmony_ci gspca_dev->vdev.ctrl_handler = hdl; 488762306a36Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 10); 488862306a36Sopenharmony_ci if (valid_controls[sd->sensor].has_brightness) 488962306a36Sopenharmony_ci sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 489062306a36Sopenharmony_ci V4L2_CID_BRIGHTNESS, 0, 489162306a36Sopenharmony_ci sd->sensor == SEN_OV7660 ? 6 : 255, 1, 489262306a36Sopenharmony_ci sd->sensor == SEN_OV7660 ? 3 : 127); 489362306a36Sopenharmony_ci if (valid_controls[sd->sensor].has_contrast) { 489462306a36Sopenharmony_ci if (sd->sensor == SEN_OV7660) 489562306a36Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 489662306a36Sopenharmony_ci V4L2_CID_CONTRAST, 0, 6, 1, 3); 489762306a36Sopenharmony_ci else 489862306a36Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 489962306a36Sopenharmony_ci V4L2_CID_CONTRAST, 0, 255, 1, 490062306a36Sopenharmony_ci (sd->sensor == SEN_OV6630 || 490162306a36Sopenharmony_ci sd->sensor == SEN_OV66308AF) ? 200 : 127); 490262306a36Sopenharmony_ci } 490362306a36Sopenharmony_ci if (valid_controls[sd->sensor].has_sat) 490462306a36Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 490562306a36Sopenharmony_ci V4L2_CID_SATURATION, 0, 490662306a36Sopenharmony_ci sd->sensor == SEN_OV7660 ? 4 : 255, 1, 490762306a36Sopenharmony_ci sd->sensor == SEN_OV7660 ? 2 : 127); 490862306a36Sopenharmony_ci if (valid_controls[sd->sensor].has_exposure) 490962306a36Sopenharmony_ci gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 491062306a36Sopenharmony_ci V4L2_CID_EXPOSURE, 0, 255, 1, 127); 491162306a36Sopenharmony_ci if (valid_controls[sd->sensor].has_hvflip) { 491262306a36Sopenharmony_ci sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 491362306a36Sopenharmony_ci V4L2_CID_HFLIP, 0, 1, 1, 0); 491462306a36Sopenharmony_ci sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 491562306a36Sopenharmony_ci V4L2_CID_VFLIP, 0, 1, 1, 0); 491662306a36Sopenharmony_ci } 491762306a36Sopenharmony_ci if (valid_controls[sd->sensor].has_autobright) 491862306a36Sopenharmony_ci sd->autobright = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 491962306a36Sopenharmony_ci V4L2_CID_AUTOBRIGHTNESS, 0, 1, 1, 1); 492062306a36Sopenharmony_ci if (valid_controls[sd->sensor].has_autogain) 492162306a36Sopenharmony_ci gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 492262306a36Sopenharmony_ci V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 492362306a36Sopenharmony_ci if (valid_controls[sd->sensor].has_freq) { 492462306a36Sopenharmony_ci if (sd->sensor == SEN_OV7670) 492562306a36Sopenharmony_ci sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, 492662306a36Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY, 492762306a36Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0, 492862306a36Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY_AUTO); 492962306a36Sopenharmony_ci else 493062306a36Sopenharmony_ci sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, 493162306a36Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY, 493262306a36Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0); 493362306a36Sopenharmony_ci } 493462306a36Sopenharmony_ci if (sd->bridge == BRIDGE_W9968CF) 493562306a36Sopenharmony_ci sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 493662306a36Sopenharmony_ci V4L2_CID_JPEG_COMPRESSION_QUALITY, 493762306a36Sopenharmony_ci QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF); 493862306a36Sopenharmony_ci 493962306a36Sopenharmony_ci if (hdl->error) { 494062306a36Sopenharmony_ci gspca_err(gspca_dev, "Could not initialize controls\n"); 494162306a36Sopenharmony_ci return hdl->error; 494262306a36Sopenharmony_ci } 494362306a36Sopenharmony_ci if (gspca_dev->autogain) 494462306a36Sopenharmony_ci v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, true); 494562306a36Sopenharmony_ci if (sd->autobright) 494662306a36Sopenharmony_ci v4l2_ctrl_auto_cluster(2, &sd->autobright, 0, false); 494762306a36Sopenharmony_ci if (sd->hflip) 494862306a36Sopenharmony_ci v4l2_ctrl_cluster(2, &sd->hflip); 494962306a36Sopenharmony_ci return 0; 495062306a36Sopenharmony_ci} 495162306a36Sopenharmony_ci 495262306a36Sopenharmony_ci/* sub-driver description */ 495362306a36Sopenharmony_cistatic const struct sd_desc sd_desc = { 495462306a36Sopenharmony_ci .name = MODULE_NAME, 495562306a36Sopenharmony_ci .config = sd_config, 495662306a36Sopenharmony_ci .init = sd_init, 495762306a36Sopenharmony_ci .init_controls = sd_init_controls, 495862306a36Sopenharmony_ci .isoc_init = sd_isoc_init, 495962306a36Sopenharmony_ci .start = sd_start, 496062306a36Sopenharmony_ci .stopN = sd_stopN, 496162306a36Sopenharmony_ci .stop0 = sd_stop0, 496262306a36Sopenharmony_ci .pkt_scan = sd_pkt_scan, 496362306a36Sopenharmony_ci .dq_callback = sd_reset_snapshot, 496462306a36Sopenharmony_ci .get_jcomp = sd_get_jcomp, 496562306a36Sopenharmony_ci .set_jcomp = sd_set_jcomp, 496662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT) 496762306a36Sopenharmony_ci .other_input = 1, 496862306a36Sopenharmony_ci#endif 496962306a36Sopenharmony_ci}; 497062306a36Sopenharmony_ci 497162306a36Sopenharmony_ci/* -- module initialisation -- */ 497262306a36Sopenharmony_cistatic const struct usb_device_id device_table[] = { 497362306a36Sopenharmony_ci {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF }, 497462306a36Sopenharmony_ci {USB_DEVICE(0x041e, 0x4052), 497562306a36Sopenharmony_ci .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, 497662306a36Sopenharmony_ci {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, 497762306a36Sopenharmony_ci {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, 497862306a36Sopenharmony_ci {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, 497962306a36Sopenharmony_ci {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 }, 498062306a36Sopenharmony_ci {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, 498162306a36Sopenharmony_ci {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 }, 498262306a36Sopenharmony_ci {USB_DEVICE(0x045e, 0x028c), 498362306a36Sopenharmony_ci .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, 498462306a36Sopenharmony_ci {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, 498562306a36Sopenharmony_ci {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, 498662306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, 498762306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, 498862306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0x0519), 498962306a36Sopenharmony_ci .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, 499062306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0x0530), 499162306a36Sopenharmony_ci .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, 499262306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 }, 499362306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, 499462306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, 499562306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, 499662306a36Sopenharmony_ci {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, 499762306a36Sopenharmony_ci {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, 499862306a36Sopenharmony_ci {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, 499962306a36Sopenharmony_ci {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, 500062306a36Sopenharmony_ci {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, 500162306a36Sopenharmony_ci {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 }, 500262306a36Sopenharmony_ci {} 500362306a36Sopenharmony_ci}; 500462306a36Sopenharmony_ci 500562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table); 500662306a36Sopenharmony_ci 500762306a36Sopenharmony_ci/* -- device connect -- */ 500862306a36Sopenharmony_cistatic int sd_probe(struct usb_interface *intf, 500962306a36Sopenharmony_ci const struct usb_device_id *id) 501062306a36Sopenharmony_ci{ 501162306a36Sopenharmony_ci return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 501262306a36Sopenharmony_ci THIS_MODULE); 501362306a36Sopenharmony_ci} 501462306a36Sopenharmony_ci 501562306a36Sopenharmony_cistatic struct usb_driver sd_driver = { 501662306a36Sopenharmony_ci .name = MODULE_NAME, 501762306a36Sopenharmony_ci .id_table = device_table, 501862306a36Sopenharmony_ci .probe = sd_probe, 501962306a36Sopenharmony_ci .disconnect = gspca_disconnect, 502062306a36Sopenharmony_ci#ifdef CONFIG_PM 502162306a36Sopenharmony_ci .suspend = gspca_suspend, 502262306a36Sopenharmony_ci .resume = gspca_resume, 502362306a36Sopenharmony_ci .reset_resume = gspca_resume, 502462306a36Sopenharmony_ci#endif 502562306a36Sopenharmony_ci}; 502662306a36Sopenharmony_ci 502762306a36Sopenharmony_cimodule_usb_driver(sd_driver); 502862306a36Sopenharmony_ci 502962306a36Sopenharmony_cimodule_param(frame_rate, int, 0644); 503062306a36Sopenharmony_ciMODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)"); 5031