18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * OV519 driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr> 68c2ecf20Sopenharmony_ci * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This module is adapted from the ov51x-jpeg package, which itself 98c2ecf20Sopenharmony_ci * was adapted from the ov511 driver. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Original copyright for the ov511 driver is: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Copyright (c) 1999-2006 Mark W. McClelland 148c2ecf20Sopenharmony_ci * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach 158c2ecf20Sopenharmony_ci * Many improvements by Bret Wallach <bwallac1@san.rr.com> 168c2ecf20Sopenharmony_ci * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) 178c2ecf20Sopenharmony_ci * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> 188c2ecf20Sopenharmony_ci * Changes by Claudio Matsuoka <claudio@conectiva.com> 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * ov51x-jpeg original copyright is: 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Copyright (c) 2004-2007 Romain Beauxis <toots@rastageeks.org> 238c2ecf20Sopenharmony_ci * Support for OV7670 sensors was contributed by Sam Skipsey <aoanla@yahoo.com> 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define MODULE_NAME "ov519" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <linux/input.h> 318c2ecf20Sopenharmony_ci#include "gspca.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* The jpeg_hdr is used by w996Xcf only */ 348c2ecf20Sopenharmony_ci/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */ 358c2ecf20Sopenharmony_ci#define CONEX_CAM 368c2ecf20Sopenharmony_ci#include "jpeg.h" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); 398c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("OV519 USB Camera Driver"); 408c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* global parameters */ 438c2ecf20Sopenharmony_cistatic int frame_rate; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* Number of times to retry a failed I2C transaction. Increase this if you 468c2ecf20Sopenharmony_ci * are getting "Failed to read sensor ID..." */ 478c2ecf20Sopenharmony_cistatic int i2c_detect_tries = 10; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* ov519 device descriptor */ 508c2ecf20Sopenharmony_cistruct sd { 518c2ecf20Sopenharmony_ci struct gspca_dev gspca_dev; /* !! must be the first item */ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci struct v4l2_ctrl *jpegqual; 548c2ecf20Sopenharmony_ci struct v4l2_ctrl *freq; 558c2ecf20Sopenharmony_ci struct { /* h/vflip control cluster */ 568c2ecf20Sopenharmony_ci struct v4l2_ctrl *hflip; 578c2ecf20Sopenharmony_ci struct v4l2_ctrl *vflip; 588c2ecf20Sopenharmony_ci }; 598c2ecf20Sopenharmony_ci struct { /* autobrightness/brightness control cluster */ 608c2ecf20Sopenharmony_ci struct v4l2_ctrl *autobright; 618c2ecf20Sopenharmony_ci struct v4l2_ctrl *brightness; 628c2ecf20Sopenharmony_ci }; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci u8 revision; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci u8 packet_nr; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci char bridge; 698c2ecf20Sopenharmony_ci#define BRIDGE_OV511 0 708c2ecf20Sopenharmony_ci#define BRIDGE_OV511PLUS 1 718c2ecf20Sopenharmony_ci#define BRIDGE_OV518 2 728c2ecf20Sopenharmony_ci#define BRIDGE_OV518PLUS 3 738c2ecf20Sopenharmony_ci#define BRIDGE_OV519 4 /* = ov530 */ 748c2ecf20Sopenharmony_ci#define BRIDGE_OVFX2 5 758c2ecf20Sopenharmony_ci#define BRIDGE_W9968CF 6 768c2ecf20Sopenharmony_ci#define BRIDGE_MASK 7 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci char invert_led; 798c2ecf20Sopenharmony_ci#define BRIDGE_INVERT_LED 8 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci char snapshot_pressed; 828c2ecf20Sopenharmony_ci char snapshot_needs_reset; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci /* Determined by sensor type */ 858c2ecf20Sopenharmony_ci u8 sif; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define QUALITY_MIN 50 888c2ecf20Sopenharmony_ci#define QUALITY_MAX 70 898c2ecf20Sopenharmony_ci#define QUALITY_DEF 50 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci u8 stopped; /* Streaming is temporarily paused */ 928c2ecf20Sopenharmony_ci u8 first_frame; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci u8 frame_rate; /* current Framerate */ 958c2ecf20Sopenharmony_ci u8 clockdiv; /* clockdiv override */ 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci s8 sensor; /* Type of image sensor chip (SEN_*) */ 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci u8 sensor_addr; 1008c2ecf20Sopenharmony_ci u16 sensor_width; 1018c2ecf20Sopenharmony_ci u16 sensor_height; 1028c2ecf20Sopenharmony_ci s16 sensor_reg_cache[256]; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci u8 jpeg_hdr[JPEG_HDR_SZ]; 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_cienum sensors { 1078c2ecf20Sopenharmony_ci SEN_OV2610, 1088c2ecf20Sopenharmony_ci SEN_OV2610AE, 1098c2ecf20Sopenharmony_ci SEN_OV3610, 1108c2ecf20Sopenharmony_ci SEN_OV6620, 1118c2ecf20Sopenharmony_ci SEN_OV6630, 1128c2ecf20Sopenharmony_ci SEN_OV66308AF, 1138c2ecf20Sopenharmony_ci SEN_OV7610, 1148c2ecf20Sopenharmony_ci SEN_OV7620, 1158c2ecf20Sopenharmony_ci SEN_OV7620AE, 1168c2ecf20Sopenharmony_ci SEN_OV7640, 1178c2ecf20Sopenharmony_ci SEN_OV7648, 1188c2ecf20Sopenharmony_ci SEN_OV7660, 1198c2ecf20Sopenharmony_ci SEN_OV7670, 1208c2ecf20Sopenharmony_ci SEN_OV76BE, 1218c2ecf20Sopenharmony_ci SEN_OV8610, 1228c2ecf20Sopenharmony_ci SEN_OV9600, 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* Note this is a bit of a hack, but the w9968cf driver needs the code for all 1268c2ecf20Sopenharmony_ci the ov sensors which is already present here. When we have the time we 1278c2ecf20Sopenharmony_ci really should move the sensor drivers to v4l2 sub drivers. */ 1288c2ecf20Sopenharmony_ci#include "w996Xcf.c" 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* table of the disabled controls */ 1318c2ecf20Sopenharmony_cistruct ctrl_valid { 1328c2ecf20Sopenharmony_ci unsigned int has_brightness:1; 1338c2ecf20Sopenharmony_ci unsigned int has_contrast:1; 1348c2ecf20Sopenharmony_ci unsigned int has_exposure:1; 1358c2ecf20Sopenharmony_ci unsigned int has_autogain:1; 1368c2ecf20Sopenharmony_ci unsigned int has_sat:1; 1378c2ecf20Sopenharmony_ci unsigned int has_hvflip:1; 1388c2ecf20Sopenharmony_ci unsigned int has_autobright:1; 1398c2ecf20Sopenharmony_ci unsigned int has_freq:1; 1408c2ecf20Sopenharmony_ci}; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic const struct ctrl_valid valid_controls[] = { 1438c2ecf20Sopenharmony_ci [SEN_OV2610] = { 1448c2ecf20Sopenharmony_ci .has_exposure = 1, 1458c2ecf20Sopenharmony_ci .has_autogain = 1, 1468c2ecf20Sopenharmony_ci }, 1478c2ecf20Sopenharmony_ci [SEN_OV2610AE] = { 1488c2ecf20Sopenharmony_ci .has_exposure = 1, 1498c2ecf20Sopenharmony_ci .has_autogain = 1, 1508c2ecf20Sopenharmony_ci }, 1518c2ecf20Sopenharmony_ci [SEN_OV3610] = { 1528c2ecf20Sopenharmony_ci /* No controls */ 1538c2ecf20Sopenharmony_ci }, 1548c2ecf20Sopenharmony_ci [SEN_OV6620] = { 1558c2ecf20Sopenharmony_ci .has_brightness = 1, 1568c2ecf20Sopenharmony_ci .has_contrast = 1, 1578c2ecf20Sopenharmony_ci .has_sat = 1, 1588c2ecf20Sopenharmony_ci .has_autobright = 1, 1598c2ecf20Sopenharmony_ci .has_freq = 1, 1608c2ecf20Sopenharmony_ci }, 1618c2ecf20Sopenharmony_ci [SEN_OV6630] = { 1628c2ecf20Sopenharmony_ci .has_brightness = 1, 1638c2ecf20Sopenharmony_ci .has_contrast = 1, 1648c2ecf20Sopenharmony_ci .has_sat = 1, 1658c2ecf20Sopenharmony_ci .has_autobright = 1, 1668c2ecf20Sopenharmony_ci .has_freq = 1, 1678c2ecf20Sopenharmony_ci }, 1688c2ecf20Sopenharmony_ci [SEN_OV66308AF] = { 1698c2ecf20Sopenharmony_ci .has_brightness = 1, 1708c2ecf20Sopenharmony_ci .has_contrast = 1, 1718c2ecf20Sopenharmony_ci .has_sat = 1, 1728c2ecf20Sopenharmony_ci .has_autobright = 1, 1738c2ecf20Sopenharmony_ci .has_freq = 1, 1748c2ecf20Sopenharmony_ci }, 1758c2ecf20Sopenharmony_ci [SEN_OV7610] = { 1768c2ecf20Sopenharmony_ci .has_brightness = 1, 1778c2ecf20Sopenharmony_ci .has_contrast = 1, 1788c2ecf20Sopenharmony_ci .has_sat = 1, 1798c2ecf20Sopenharmony_ci .has_autobright = 1, 1808c2ecf20Sopenharmony_ci .has_freq = 1, 1818c2ecf20Sopenharmony_ci }, 1828c2ecf20Sopenharmony_ci [SEN_OV7620] = { 1838c2ecf20Sopenharmony_ci .has_brightness = 1, 1848c2ecf20Sopenharmony_ci .has_contrast = 1, 1858c2ecf20Sopenharmony_ci .has_sat = 1, 1868c2ecf20Sopenharmony_ci .has_autobright = 1, 1878c2ecf20Sopenharmony_ci .has_freq = 1, 1888c2ecf20Sopenharmony_ci }, 1898c2ecf20Sopenharmony_ci [SEN_OV7620AE] = { 1908c2ecf20Sopenharmony_ci .has_brightness = 1, 1918c2ecf20Sopenharmony_ci .has_contrast = 1, 1928c2ecf20Sopenharmony_ci .has_sat = 1, 1938c2ecf20Sopenharmony_ci .has_autobright = 1, 1948c2ecf20Sopenharmony_ci .has_freq = 1, 1958c2ecf20Sopenharmony_ci }, 1968c2ecf20Sopenharmony_ci [SEN_OV7640] = { 1978c2ecf20Sopenharmony_ci .has_brightness = 1, 1988c2ecf20Sopenharmony_ci .has_sat = 1, 1998c2ecf20Sopenharmony_ci .has_freq = 1, 2008c2ecf20Sopenharmony_ci }, 2018c2ecf20Sopenharmony_ci [SEN_OV7648] = { 2028c2ecf20Sopenharmony_ci .has_brightness = 1, 2038c2ecf20Sopenharmony_ci .has_sat = 1, 2048c2ecf20Sopenharmony_ci .has_freq = 1, 2058c2ecf20Sopenharmony_ci }, 2068c2ecf20Sopenharmony_ci [SEN_OV7660] = { 2078c2ecf20Sopenharmony_ci .has_brightness = 1, 2088c2ecf20Sopenharmony_ci .has_contrast = 1, 2098c2ecf20Sopenharmony_ci .has_sat = 1, 2108c2ecf20Sopenharmony_ci .has_hvflip = 1, 2118c2ecf20Sopenharmony_ci .has_freq = 1, 2128c2ecf20Sopenharmony_ci }, 2138c2ecf20Sopenharmony_ci [SEN_OV7670] = { 2148c2ecf20Sopenharmony_ci .has_brightness = 1, 2158c2ecf20Sopenharmony_ci .has_contrast = 1, 2168c2ecf20Sopenharmony_ci .has_hvflip = 1, 2178c2ecf20Sopenharmony_ci .has_freq = 1, 2188c2ecf20Sopenharmony_ci }, 2198c2ecf20Sopenharmony_ci [SEN_OV76BE] = { 2208c2ecf20Sopenharmony_ci .has_brightness = 1, 2218c2ecf20Sopenharmony_ci .has_contrast = 1, 2228c2ecf20Sopenharmony_ci .has_sat = 1, 2238c2ecf20Sopenharmony_ci .has_autobright = 1, 2248c2ecf20Sopenharmony_ci .has_freq = 1, 2258c2ecf20Sopenharmony_ci }, 2268c2ecf20Sopenharmony_ci [SEN_OV8610] = { 2278c2ecf20Sopenharmony_ci .has_brightness = 1, 2288c2ecf20Sopenharmony_ci .has_contrast = 1, 2298c2ecf20Sopenharmony_ci .has_sat = 1, 2308c2ecf20Sopenharmony_ci .has_autobright = 1, 2318c2ecf20Sopenharmony_ci }, 2328c2ecf20Sopenharmony_ci [SEN_OV9600] = { 2338c2ecf20Sopenharmony_ci .has_exposure = 1, 2348c2ecf20Sopenharmony_ci .has_autogain = 1, 2358c2ecf20Sopenharmony_ci }, 2368c2ecf20Sopenharmony_ci}; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ov519_vga_mode[] = { 2398c2ecf20Sopenharmony_ci {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 2408c2ecf20Sopenharmony_ci .bytesperline = 320, 2418c2ecf20Sopenharmony_ci .sizeimage = 320 * 240 * 3 / 8 + 590, 2428c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2438c2ecf20Sopenharmony_ci .priv = 1}, 2448c2ecf20Sopenharmony_ci {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 2458c2ecf20Sopenharmony_ci .bytesperline = 640, 2468c2ecf20Sopenharmony_ci .sizeimage = 640 * 480 * 3 / 8 + 590, 2478c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2488c2ecf20Sopenharmony_ci .priv = 0}, 2498c2ecf20Sopenharmony_ci}; 2508c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ov519_sif_mode[] = { 2518c2ecf20Sopenharmony_ci {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 2528c2ecf20Sopenharmony_ci .bytesperline = 160, 2538c2ecf20Sopenharmony_ci .sizeimage = 160 * 120 * 3 / 8 + 590, 2548c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2558c2ecf20Sopenharmony_ci .priv = 3}, 2568c2ecf20Sopenharmony_ci {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 2578c2ecf20Sopenharmony_ci .bytesperline = 176, 2588c2ecf20Sopenharmony_ci .sizeimage = 176 * 144 * 3 / 8 + 590, 2598c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2608c2ecf20Sopenharmony_ci .priv = 1}, 2618c2ecf20Sopenharmony_ci {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 2628c2ecf20Sopenharmony_ci .bytesperline = 320, 2638c2ecf20Sopenharmony_ci .sizeimage = 320 * 240 * 3 / 8 + 590, 2648c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2658c2ecf20Sopenharmony_ci .priv = 2}, 2668c2ecf20Sopenharmony_ci {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 2678c2ecf20Sopenharmony_ci .bytesperline = 352, 2688c2ecf20Sopenharmony_ci .sizeimage = 352 * 288 * 3 / 8 + 590, 2698c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2708c2ecf20Sopenharmony_ci .priv = 0}, 2718c2ecf20Sopenharmony_ci}; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/* Note some of the sizeimage values for the ov511 / ov518 may seem 2748c2ecf20Sopenharmony_ci larger then necessary, however they need to be this big as the ov511 / 2758c2ecf20Sopenharmony_ci ov518 always fills the entire isoc frame, using 0 padding bytes when 2768c2ecf20Sopenharmony_ci it doesn't have any data. So with low framerates the amount of data 2778c2ecf20Sopenharmony_ci transferred can become quite large (libv4l will remove all the 0 padding 2788c2ecf20Sopenharmony_ci in userspace). */ 2798c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ov518_vga_mode[] = { 2808c2ecf20Sopenharmony_ci {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 2818c2ecf20Sopenharmony_ci .bytesperline = 320, 2828c2ecf20Sopenharmony_ci .sizeimage = 320 * 240 * 3, 2838c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2848c2ecf20Sopenharmony_ci .priv = 1}, 2858c2ecf20Sopenharmony_ci {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 2868c2ecf20Sopenharmony_ci .bytesperline = 640, 2878c2ecf20Sopenharmony_ci .sizeimage = 640 * 480 * 2, 2888c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2898c2ecf20Sopenharmony_ci .priv = 0}, 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ov518_sif_mode[] = { 2928c2ecf20Sopenharmony_ci {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 2938c2ecf20Sopenharmony_ci .bytesperline = 160, 2948c2ecf20Sopenharmony_ci .sizeimage = 70000, 2958c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 2968c2ecf20Sopenharmony_ci .priv = 3}, 2978c2ecf20Sopenharmony_ci {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 2988c2ecf20Sopenharmony_ci .bytesperline = 176, 2998c2ecf20Sopenharmony_ci .sizeimage = 70000, 3008c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3018c2ecf20Sopenharmony_ci .priv = 1}, 3028c2ecf20Sopenharmony_ci {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 3038c2ecf20Sopenharmony_ci .bytesperline = 320, 3048c2ecf20Sopenharmony_ci .sizeimage = 320 * 240 * 3, 3058c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3068c2ecf20Sopenharmony_ci .priv = 2}, 3078c2ecf20Sopenharmony_ci {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, 3088c2ecf20Sopenharmony_ci .bytesperline = 352, 3098c2ecf20Sopenharmony_ci .sizeimage = 352 * 288 * 3, 3108c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3118c2ecf20Sopenharmony_ci .priv = 0}, 3128c2ecf20Sopenharmony_ci}; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ov511_vga_mode[] = { 3158c2ecf20Sopenharmony_ci {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 3168c2ecf20Sopenharmony_ci .bytesperline = 320, 3178c2ecf20Sopenharmony_ci .sizeimage = 320 * 240 * 3, 3188c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3198c2ecf20Sopenharmony_ci .priv = 1}, 3208c2ecf20Sopenharmony_ci {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 3218c2ecf20Sopenharmony_ci .bytesperline = 640, 3228c2ecf20Sopenharmony_ci .sizeimage = 640 * 480 * 2, 3238c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3248c2ecf20Sopenharmony_ci .priv = 0}, 3258c2ecf20Sopenharmony_ci}; 3268c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ov511_sif_mode[] = { 3278c2ecf20Sopenharmony_ci {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 3288c2ecf20Sopenharmony_ci .bytesperline = 160, 3298c2ecf20Sopenharmony_ci .sizeimage = 70000, 3308c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3318c2ecf20Sopenharmony_ci .priv = 3}, 3328c2ecf20Sopenharmony_ci {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 3338c2ecf20Sopenharmony_ci .bytesperline = 176, 3348c2ecf20Sopenharmony_ci .sizeimage = 70000, 3358c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3368c2ecf20Sopenharmony_ci .priv = 1}, 3378c2ecf20Sopenharmony_ci {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 3388c2ecf20Sopenharmony_ci .bytesperline = 320, 3398c2ecf20Sopenharmony_ci .sizeimage = 320 * 240 * 3, 3408c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3418c2ecf20Sopenharmony_ci .priv = 2}, 3428c2ecf20Sopenharmony_ci {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, 3438c2ecf20Sopenharmony_ci .bytesperline = 352, 3448c2ecf20Sopenharmony_ci .sizeimage = 352 * 288 * 3, 3458c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 3468c2ecf20Sopenharmony_ci .priv = 0}, 3478c2ecf20Sopenharmony_ci}; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov2610_mode[] = { 3508c2ecf20Sopenharmony_ci {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3518c2ecf20Sopenharmony_ci .bytesperline = 800, 3528c2ecf20Sopenharmony_ci .sizeimage = 800 * 600, 3538c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 3548c2ecf20Sopenharmony_ci .priv = 1}, 3558c2ecf20Sopenharmony_ci {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3568c2ecf20Sopenharmony_ci .bytesperline = 1600, 3578c2ecf20Sopenharmony_ci .sizeimage = 1600 * 1200, 3588c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB}, 3598c2ecf20Sopenharmony_ci}; 3608c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov3610_mode[] = { 3618c2ecf20Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3628c2ecf20Sopenharmony_ci .bytesperline = 640, 3638c2ecf20Sopenharmony_ci .sizeimage = 640 * 480, 3648c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 3658c2ecf20Sopenharmony_ci .priv = 1}, 3668c2ecf20Sopenharmony_ci {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3678c2ecf20Sopenharmony_ci .bytesperline = 800, 3688c2ecf20Sopenharmony_ci .sizeimage = 800 * 600, 3698c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 3708c2ecf20Sopenharmony_ci .priv = 1}, 3718c2ecf20Sopenharmony_ci {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3728c2ecf20Sopenharmony_ci .bytesperline = 1024, 3738c2ecf20Sopenharmony_ci .sizeimage = 1024 * 768, 3748c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 3758c2ecf20Sopenharmony_ci .priv = 1}, 3768c2ecf20Sopenharmony_ci {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3778c2ecf20Sopenharmony_ci .bytesperline = 1600, 3788c2ecf20Sopenharmony_ci .sizeimage = 1600 * 1200, 3798c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 3808c2ecf20Sopenharmony_ci .priv = 0}, 3818c2ecf20Sopenharmony_ci {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3828c2ecf20Sopenharmony_ci .bytesperline = 2048, 3838c2ecf20Sopenharmony_ci .sizeimage = 2048 * 1536, 3848c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 3858c2ecf20Sopenharmony_ci .priv = 0}, 3868c2ecf20Sopenharmony_ci}; 3878c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov9600_mode[] = { 3888c2ecf20Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3898c2ecf20Sopenharmony_ci .bytesperline = 640, 3908c2ecf20Sopenharmony_ci .sizeimage = 640 * 480, 3918c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 3928c2ecf20Sopenharmony_ci .priv = 1}, 3938c2ecf20Sopenharmony_ci {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 3948c2ecf20Sopenharmony_ci .bytesperline = 1280, 3958c2ecf20Sopenharmony_ci .sizeimage = 1280 * 1024, 3968c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB}, 3978c2ecf20Sopenharmony_ci}; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci/* Registers common to OV511 / OV518 */ 4008c2ecf20Sopenharmony_ci#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ 4018c2ecf20Sopenharmony_ci#define R51x_SYS_RESET 0x50 4028c2ecf20Sopenharmony_ci /* Reset type flags */ 4038c2ecf20Sopenharmony_ci #define OV511_RESET_OMNICE 0x08 4048c2ecf20Sopenharmony_ci#define R51x_SYS_INIT 0x53 4058c2ecf20Sopenharmony_ci#define R51x_SYS_SNAP 0x52 4068c2ecf20Sopenharmony_ci#define R51x_SYS_CUST_ID 0x5f 4078c2ecf20Sopenharmony_ci#define R51x_COMP_LUT_BEGIN 0x80 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci/* OV511 Camera interface register numbers */ 4108c2ecf20Sopenharmony_ci#define R511_CAM_DELAY 0x10 4118c2ecf20Sopenharmony_ci#define R511_CAM_EDGE 0x11 4128c2ecf20Sopenharmony_ci#define R511_CAM_PXCNT 0x12 4138c2ecf20Sopenharmony_ci#define R511_CAM_LNCNT 0x13 4148c2ecf20Sopenharmony_ci#define R511_CAM_PXDIV 0x14 4158c2ecf20Sopenharmony_ci#define R511_CAM_LNDIV 0x15 4168c2ecf20Sopenharmony_ci#define R511_CAM_UV_EN 0x16 4178c2ecf20Sopenharmony_ci#define R511_CAM_LINE_MODE 0x17 4188c2ecf20Sopenharmony_ci#define R511_CAM_OPTS 0x18 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci#define R511_SNAP_FRAME 0x19 4218c2ecf20Sopenharmony_ci#define R511_SNAP_PXCNT 0x1a 4228c2ecf20Sopenharmony_ci#define R511_SNAP_LNCNT 0x1b 4238c2ecf20Sopenharmony_ci#define R511_SNAP_PXDIV 0x1c 4248c2ecf20Sopenharmony_ci#define R511_SNAP_LNDIV 0x1d 4258c2ecf20Sopenharmony_ci#define R511_SNAP_UV_EN 0x1e 4268c2ecf20Sopenharmony_ci#define R511_SNAP_OPTS 0x1f 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci#define R511_DRAM_FLOW_CTL 0x20 4298c2ecf20Sopenharmony_ci#define R511_FIFO_OPTS 0x31 4308c2ecf20Sopenharmony_ci#define R511_I2C_CTL 0x40 4318c2ecf20Sopenharmony_ci#define R511_SYS_LED_CTL 0x55 /* OV511+ only */ 4328c2ecf20Sopenharmony_ci#define R511_COMP_EN 0x78 4338c2ecf20Sopenharmony_ci#define R511_COMP_LUT_EN 0x79 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/* OV518 Camera interface register numbers */ 4368c2ecf20Sopenharmony_ci#define R518_GPIO_OUT 0x56 /* OV518(+) only */ 4378c2ecf20Sopenharmony_ci#define R518_GPIO_CTL 0x57 /* OV518(+) only */ 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci/* OV519 Camera interface register numbers */ 4408c2ecf20Sopenharmony_ci#define OV519_R10_H_SIZE 0x10 4418c2ecf20Sopenharmony_ci#define OV519_R11_V_SIZE 0x11 4428c2ecf20Sopenharmony_ci#define OV519_R12_X_OFFSETL 0x12 4438c2ecf20Sopenharmony_ci#define OV519_R13_X_OFFSETH 0x13 4448c2ecf20Sopenharmony_ci#define OV519_R14_Y_OFFSETL 0x14 4458c2ecf20Sopenharmony_ci#define OV519_R15_Y_OFFSETH 0x15 4468c2ecf20Sopenharmony_ci#define OV519_R16_DIVIDER 0x16 4478c2ecf20Sopenharmony_ci#define OV519_R20_DFR 0x20 4488c2ecf20Sopenharmony_ci#define OV519_R25_FORMAT 0x25 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci/* OV519 System Controller register numbers */ 4518c2ecf20Sopenharmony_ci#define OV519_R51_RESET1 0x51 4528c2ecf20Sopenharmony_ci#define OV519_R54_EN_CLK1 0x54 4538c2ecf20Sopenharmony_ci#define OV519_R57_SNAPSHOT 0x57 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci#define OV519_GPIO_DATA_OUT0 0x71 4568c2ecf20Sopenharmony_ci#define OV519_GPIO_IO_CTRL0 0x72 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci/*#define OV511_ENDPOINT_ADDRESS 1 * Isoc endpoint number */ 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci/* 4618c2ecf20Sopenharmony_ci * The FX2 chip does not give us a zero length read at end of frame. 4628c2ecf20Sopenharmony_ci * It does, however, give a short read at the end of a frame, if 4638c2ecf20Sopenharmony_ci * necessary, rather than run two frames together. 4648c2ecf20Sopenharmony_ci * 4658c2ecf20Sopenharmony_ci * By choosing the right bulk transfer size, we are guaranteed to always 4668c2ecf20Sopenharmony_ci * get a short read for the last read of each frame. Frame sizes are 4678c2ecf20Sopenharmony_ci * always a composite number (width * height, or a multiple) so if we 4688c2ecf20Sopenharmony_ci * choose a prime number, we are guaranteed that the last read of a 4698c2ecf20Sopenharmony_ci * frame will be short. 4708c2ecf20Sopenharmony_ci * 4718c2ecf20Sopenharmony_ci * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB, 4728c2ecf20Sopenharmony_ci * otherwise EOVERFLOW "babbling" errors occur. I have not been able 4738c2ecf20Sopenharmony_ci * to figure out why. [PMiller] 4748c2ecf20Sopenharmony_ci * 4758c2ecf20Sopenharmony_ci * The constant (13 * 4096) is the largest "prime enough" number less than 64KB. 4768c2ecf20Sopenharmony_ci * 4778c2ecf20Sopenharmony_ci * It isn't enough to know the number of bytes per frame, in case we 4788c2ecf20Sopenharmony_ci * have data dropouts or buffer overruns (even though the FX2 double 4798c2ecf20Sopenharmony_ci * buffers, there are some pretty strict real time constraints for 4808c2ecf20Sopenharmony_ci * isochronous transfer for larger frame sizes). 4818c2ecf20Sopenharmony_ci */ 4828c2ecf20Sopenharmony_ci/*jfm: this value does not work for 800x600 - see isoc_init */ 4838c2ecf20Sopenharmony_ci#define OVFX2_BULK_SIZE (13 * 4096) 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci/* I2C registers */ 4868c2ecf20Sopenharmony_ci#define R51x_I2C_W_SID 0x41 4878c2ecf20Sopenharmony_ci#define R51x_I2C_SADDR_3 0x42 4888c2ecf20Sopenharmony_ci#define R51x_I2C_SADDR_2 0x43 4898c2ecf20Sopenharmony_ci#define R51x_I2C_R_SID 0x44 4908c2ecf20Sopenharmony_ci#define R51x_I2C_DATA 0x45 4918c2ecf20Sopenharmony_ci#define R518_I2C_CTL 0x47 /* OV518(+) only */ 4928c2ecf20Sopenharmony_ci#define OVFX2_I2C_ADDR 0x00 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci/* I2C ADDRESSES */ 4958c2ecf20Sopenharmony_ci#define OV7xx0_SID 0x42 4968c2ecf20Sopenharmony_ci#define OV_HIRES_SID 0x60 /* OV9xxx / OV2xxx / OV3xxx */ 4978c2ecf20Sopenharmony_ci#define OV8xx0_SID 0xa0 4988c2ecf20Sopenharmony_ci#define OV6xx0_SID 0xc0 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci/* OV7610 registers */ 5018c2ecf20Sopenharmony_ci#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ 5028c2ecf20Sopenharmony_ci#define OV7610_REG_BLUE 0x01 /* blue channel balance */ 5038c2ecf20Sopenharmony_ci#define OV7610_REG_RED 0x02 /* red channel balance */ 5048c2ecf20Sopenharmony_ci#define OV7610_REG_SAT 0x03 /* saturation */ 5058c2ecf20Sopenharmony_ci#define OV8610_REG_HUE 0x04 /* 04 reserved */ 5068c2ecf20Sopenharmony_ci#define OV7610_REG_CNT 0x05 /* Y contrast */ 5078c2ecf20Sopenharmony_ci#define OV7610_REG_BRT 0x06 /* Y brightness */ 5088c2ecf20Sopenharmony_ci#define OV7610_REG_COM_C 0x14 /* misc common regs */ 5098c2ecf20Sopenharmony_ci#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */ 5108c2ecf20Sopenharmony_ci#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */ 5118c2ecf20Sopenharmony_ci#define OV7610_REG_COM_I 0x29 /* misc settings */ 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci/* OV7660 and OV7670 registers */ 5148c2ecf20Sopenharmony_ci#define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ 5158c2ecf20Sopenharmony_ci#define OV7670_R01_BLUE 0x01 /* blue gain */ 5168c2ecf20Sopenharmony_ci#define OV7670_R02_RED 0x02 /* red gain */ 5178c2ecf20Sopenharmony_ci#define OV7670_R03_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ 5188c2ecf20Sopenharmony_ci#define OV7670_R04_COM1 0x04 /* Control 1 */ 5198c2ecf20Sopenharmony_ci/*#define OV7670_R07_AECHH 0x07 * AEC MS 5 bits */ 5208c2ecf20Sopenharmony_ci#define OV7670_R0C_COM3 0x0c /* Control 3 */ 5218c2ecf20Sopenharmony_ci#define OV7670_R0D_COM4 0x0d /* Control 4 */ 5228c2ecf20Sopenharmony_ci#define OV7670_R0E_COM5 0x0e /* All "reserved" */ 5238c2ecf20Sopenharmony_ci#define OV7670_R0F_COM6 0x0f /* Control 6 */ 5248c2ecf20Sopenharmony_ci#define OV7670_R10_AECH 0x10 /* More bits of AEC value */ 5258c2ecf20Sopenharmony_ci#define OV7670_R11_CLKRC 0x11 /* Clock control */ 5268c2ecf20Sopenharmony_ci#define OV7670_R12_COM7 0x12 /* Control 7 */ 5278c2ecf20Sopenharmony_ci#define OV7670_COM7_FMT_VGA 0x00 5288c2ecf20Sopenharmony_ci/*#define OV7670_COM7_YUV 0x00 * YUV */ 5298c2ecf20Sopenharmony_ci#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ 5308c2ecf20Sopenharmony_ci#define OV7670_COM7_FMT_MASK 0x38 5318c2ecf20Sopenharmony_ci#define OV7670_COM7_RESET 0x80 /* Register reset */ 5328c2ecf20Sopenharmony_ci#define OV7670_R13_COM8 0x13 /* Control 8 */ 5338c2ecf20Sopenharmony_ci#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ 5348c2ecf20Sopenharmony_ci#define OV7670_COM8_AWB 0x02 /* White balance enable */ 5358c2ecf20Sopenharmony_ci#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ 5368c2ecf20Sopenharmony_ci#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ 5378c2ecf20Sopenharmony_ci#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ 5388c2ecf20Sopenharmony_ci#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ 5398c2ecf20Sopenharmony_ci#define OV7670_R14_COM9 0x14 /* Control 9 - gain ceiling */ 5408c2ecf20Sopenharmony_ci#define OV7670_R15_COM10 0x15 /* Control 10 */ 5418c2ecf20Sopenharmony_ci#define OV7670_R17_HSTART 0x17 /* Horiz start high bits */ 5428c2ecf20Sopenharmony_ci#define OV7670_R18_HSTOP 0x18 /* Horiz stop high bits */ 5438c2ecf20Sopenharmony_ci#define OV7670_R19_VSTART 0x19 /* Vert start high bits */ 5448c2ecf20Sopenharmony_ci#define OV7670_R1A_VSTOP 0x1a /* Vert stop high bits */ 5458c2ecf20Sopenharmony_ci#define OV7670_R1E_MVFP 0x1e /* Mirror / vflip */ 5468c2ecf20Sopenharmony_ci#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ 5478c2ecf20Sopenharmony_ci#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ 5488c2ecf20Sopenharmony_ci#define OV7670_R24_AEW 0x24 /* AGC upper limit */ 5498c2ecf20Sopenharmony_ci#define OV7670_R25_AEB 0x25 /* AGC lower limit */ 5508c2ecf20Sopenharmony_ci#define OV7670_R26_VPT 0x26 /* AGC/AEC fast mode op region */ 5518c2ecf20Sopenharmony_ci#define OV7670_R32_HREF 0x32 /* HREF pieces */ 5528c2ecf20Sopenharmony_ci#define OV7670_R3A_TSLB 0x3a /* lots of stuff */ 5538c2ecf20Sopenharmony_ci#define OV7670_R3B_COM11 0x3b /* Control 11 */ 5548c2ecf20Sopenharmony_ci#define OV7670_COM11_EXP 0x02 5558c2ecf20Sopenharmony_ci#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ 5568c2ecf20Sopenharmony_ci#define OV7670_R3C_COM12 0x3c /* Control 12 */ 5578c2ecf20Sopenharmony_ci#define OV7670_R3D_COM13 0x3d /* Control 13 */ 5588c2ecf20Sopenharmony_ci#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ 5598c2ecf20Sopenharmony_ci#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ 5608c2ecf20Sopenharmony_ci#define OV7670_R3E_COM14 0x3e /* Control 14 */ 5618c2ecf20Sopenharmony_ci#define OV7670_R3F_EDGE 0x3f /* Edge enhancement factor */ 5628c2ecf20Sopenharmony_ci#define OV7670_R40_COM15 0x40 /* Control 15 */ 5638c2ecf20Sopenharmony_ci/*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ 5648c2ecf20Sopenharmony_ci#define OV7670_R41_COM16 0x41 /* Control 16 */ 5658c2ecf20Sopenharmony_ci#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ 5668c2ecf20Sopenharmony_ci/* end of ov7660 common registers */ 5678c2ecf20Sopenharmony_ci#define OV7670_R55_BRIGHT 0x55 /* Brightness */ 5688c2ecf20Sopenharmony_ci#define OV7670_R56_CONTRAS 0x56 /* Contrast control */ 5698c2ecf20Sopenharmony_ci#define OV7670_R69_GFIX 0x69 /* Fix gain control */ 5708c2ecf20Sopenharmony_ci/*#define OV7670_R8C_RGB444 0x8c * RGB 444 control */ 5718c2ecf20Sopenharmony_ci#define OV7670_R9F_HAECC1 0x9f /* Hist AEC/AGC control 1 */ 5728c2ecf20Sopenharmony_ci#define OV7670_RA0_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ 5738c2ecf20Sopenharmony_ci#define OV7670_RA5_BD50MAX 0xa5 /* 50hz banding step limit */ 5748c2ecf20Sopenharmony_ci#define OV7670_RA6_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ 5758c2ecf20Sopenharmony_ci#define OV7670_RA7_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ 5768c2ecf20Sopenharmony_ci#define OV7670_RA8_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ 5778c2ecf20Sopenharmony_ci#define OV7670_RA9_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ 5788c2ecf20Sopenharmony_ci#define OV7670_RAA_HAECC7 0xaa /* Hist AEC/AGC control 7 */ 5798c2ecf20Sopenharmony_ci#define OV7670_RAB_BD60MAX 0xab /* 60hz banding step limit */ 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_cistruct ov_regvals { 5828c2ecf20Sopenharmony_ci u8 reg; 5838c2ecf20Sopenharmony_ci u8 val; 5848c2ecf20Sopenharmony_ci}; 5858c2ecf20Sopenharmony_cistruct ov_i2c_regvals { 5868c2ecf20Sopenharmony_ci u8 reg; 5878c2ecf20Sopenharmony_ci u8 val; 5888c2ecf20Sopenharmony_ci}; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci/* Settings for OV2610 camera chip */ 5918c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_2610[] = { 5928c2ecf20Sopenharmony_ci { 0x12, 0x80 }, /* reset */ 5938c2ecf20Sopenharmony_ci}; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_2610ae[] = { 5968c2ecf20Sopenharmony_ci {0x12, 0x80}, /* reset */ 5978c2ecf20Sopenharmony_ci {0x13, 0xcd}, 5988c2ecf20Sopenharmony_ci {0x09, 0x01}, 5998c2ecf20Sopenharmony_ci {0x0d, 0x00}, 6008c2ecf20Sopenharmony_ci {0x11, 0x80}, 6018c2ecf20Sopenharmony_ci {0x12, 0x20}, /* 1600x1200 */ 6028c2ecf20Sopenharmony_ci {0x33, 0x0c}, 6038c2ecf20Sopenharmony_ci {0x35, 0x90}, 6048c2ecf20Sopenharmony_ci {0x36, 0x37}, 6058c2ecf20Sopenharmony_ci/* ms-win traces */ 6068c2ecf20Sopenharmony_ci {0x11, 0x83}, /* clock / 3 ? */ 6078c2ecf20Sopenharmony_ci {0x2d, 0x00}, /* 60 Hz filter */ 6088c2ecf20Sopenharmony_ci {0x24, 0xb0}, /* normal colors */ 6098c2ecf20Sopenharmony_ci {0x25, 0x90}, 6108c2ecf20Sopenharmony_ci {0x10, 0x43}, 6118c2ecf20Sopenharmony_ci}; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_3620b[] = { 6148c2ecf20Sopenharmony_ci /* 6158c2ecf20Sopenharmony_ci * From the datasheet: "Note that after writing to register COMH 6168c2ecf20Sopenharmony_ci * (0x12) to change the sensor mode, registers related to the 6178c2ecf20Sopenharmony_ci * sensor’s cropping window will be reset back to their default 6188c2ecf20Sopenharmony_ci * values." 6198c2ecf20Sopenharmony_ci * 6208c2ecf20Sopenharmony_ci * "wait 4096 external clock ... to make sure the sensor is 6218c2ecf20Sopenharmony_ci * stable and ready to access registers" i.e. 160us at 24MHz 6228c2ecf20Sopenharmony_ci */ 6238c2ecf20Sopenharmony_ci { 0x12, 0x80 }, /* COMH reset */ 6248c2ecf20Sopenharmony_ci { 0x12, 0x00 }, /* QXGA, master */ 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* 6278c2ecf20Sopenharmony_ci * 11 CLKRC "Clock Rate Control" 6288c2ecf20Sopenharmony_ci * [7] internal frequency doublers: on 6298c2ecf20Sopenharmony_ci * [6] video port mode: master 6308c2ecf20Sopenharmony_ci * [5:0] clock divider: 1 6318c2ecf20Sopenharmony_ci */ 6328c2ecf20Sopenharmony_ci { 0x11, 0x80 }, 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci /* 6358c2ecf20Sopenharmony_ci * 13 COMI "Common Control I" 6368c2ecf20Sopenharmony_ci * = 192 (0xC0) 11000000 6378c2ecf20Sopenharmony_ci * COMI[7] "AEC speed selection" 6388c2ecf20Sopenharmony_ci * = 1 (0x01) 1....... "Faster AEC correction" 6398c2ecf20Sopenharmony_ci * COMI[6] "AEC speed step selection" 6408c2ecf20Sopenharmony_ci * = 1 (0x01) .1...... "Big steps, fast" 6418c2ecf20Sopenharmony_ci * COMI[5] "Banding filter on off" 6428c2ecf20Sopenharmony_ci * = 0 (0x00) ..0..... "Off" 6438c2ecf20Sopenharmony_ci * COMI[4] "Banding filter option" 6448c2ecf20Sopenharmony_ci * = 0 (0x00) ...0.... "Main clock is 48 MHz and 6458c2ecf20Sopenharmony_ci * the PLL is ON" 6468c2ecf20Sopenharmony_ci * COMI[3] "Reserved" 6478c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... 6488c2ecf20Sopenharmony_ci * COMI[2] "AGC auto manual control selection" 6498c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "Manual" 6508c2ecf20Sopenharmony_ci * COMI[1] "AWB auto manual control selection" 6518c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "Manual" 6528c2ecf20Sopenharmony_ci * COMI[0] "Exposure control" 6538c2ecf20Sopenharmony_ci * = 0 (0x00) .......0 "Manual" 6548c2ecf20Sopenharmony_ci */ 6558c2ecf20Sopenharmony_ci { 0x13, 0xc0 }, 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci /* 6588c2ecf20Sopenharmony_ci * 09 COMC "Common Control C" 6598c2ecf20Sopenharmony_ci * = 8 (0x08) 00001000 6608c2ecf20Sopenharmony_ci * COMC[7:5] "Reserved" 6618c2ecf20Sopenharmony_ci * = 0 (0x00) 000..... 6628c2ecf20Sopenharmony_ci * COMC[4] "Sleep Mode Enable" 6638c2ecf20Sopenharmony_ci * = 0 (0x00) ...0.... "Normal mode" 6648c2ecf20Sopenharmony_ci * COMC[3:2] "Sensor sampling reset timing selection" 6658c2ecf20Sopenharmony_ci * = 2 (0x02) ....10.. "Longer reset time" 6668c2ecf20Sopenharmony_ci * COMC[1:0] "Output drive current select" 6678c2ecf20Sopenharmony_ci * = 0 (0x00) ......00 "Weakest" 6688c2ecf20Sopenharmony_ci */ 6698c2ecf20Sopenharmony_ci { 0x09, 0x08 }, 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci /* 6728c2ecf20Sopenharmony_ci * 0C COMD "Common Control D" 6738c2ecf20Sopenharmony_ci * = 8 (0x08) 00001000 6748c2ecf20Sopenharmony_ci * COMD[7] "Reserved" 6758c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... 6768c2ecf20Sopenharmony_ci * COMD[6] "Swap MSB and LSB at the output port" 6778c2ecf20Sopenharmony_ci * = 0 (0x00) .0...... "False" 6788c2ecf20Sopenharmony_ci * COMD[5:3] "Reserved" 6798c2ecf20Sopenharmony_ci * = 1 (0x01) ..001... 6808c2ecf20Sopenharmony_ci * COMD[2] "Output Average On Off" 6818c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "Output Normal" 6828c2ecf20Sopenharmony_ci * COMD[1] "Sensor precharge voltage selection" 6838c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "Selects internal 6848c2ecf20Sopenharmony_ci * reference precharge 6858c2ecf20Sopenharmony_ci * voltage" 6868c2ecf20Sopenharmony_ci * COMD[0] "Snapshot option" 6878c2ecf20Sopenharmony_ci * = 0 (0x00) .......0 "Enable live video output 6888c2ecf20Sopenharmony_ci * after snapshot sequence" 6898c2ecf20Sopenharmony_ci */ 6908c2ecf20Sopenharmony_ci { 0x0c, 0x08 }, 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci /* 6938c2ecf20Sopenharmony_ci * 0D COME "Common Control E" 6948c2ecf20Sopenharmony_ci * = 161 (0xA1) 10100001 6958c2ecf20Sopenharmony_ci * COME[7] "Output average option" 6968c2ecf20Sopenharmony_ci * = 1 (0x01) 1....... "Output average of 4 pixels" 6978c2ecf20Sopenharmony_ci * COME[6] "Anti-blooming control" 6988c2ecf20Sopenharmony_ci * = 0 (0x00) .0...... "Off" 6998c2ecf20Sopenharmony_ci * COME[5:3] "Reserved" 7008c2ecf20Sopenharmony_ci * = 4 (0x04) ..100... 7018c2ecf20Sopenharmony_ci * COME[2] "Clock output power down pin status" 7028c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "Tri-state data output pin 7038c2ecf20Sopenharmony_ci * on power down" 7048c2ecf20Sopenharmony_ci * COME[1] "Data output pin status selection at power down" 7058c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "Tri-state VSYNC, PCLK, 7068c2ecf20Sopenharmony_ci * HREF, and CHSYNC pins on 7078c2ecf20Sopenharmony_ci * power down" 7088c2ecf20Sopenharmony_ci * COME[0] "Auto zero circuit select" 7098c2ecf20Sopenharmony_ci * = 1 (0x01) .......1 "On" 7108c2ecf20Sopenharmony_ci */ 7118c2ecf20Sopenharmony_ci { 0x0d, 0xa1 }, 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci /* 7148c2ecf20Sopenharmony_ci * 0E COMF "Common Control F" 7158c2ecf20Sopenharmony_ci * = 112 (0x70) 01110000 7168c2ecf20Sopenharmony_ci * COMF[7] "System clock selection" 7178c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "Use 24 MHz system clock" 7188c2ecf20Sopenharmony_ci * COMF[6:4] "Reserved" 7198c2ecf20Sopenharmony_ci * = 7 (0x07) .111.... 7208c2ecf20Sopenharmony_ci * COMF[3] "Manual auto negative offset canceling selection" 7218c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... "Auto detect negative 7228c2ecf20Sopenharmony_ci * offset and cancel it" 7238c2ecf20Sopenharmony_ci * COMF[2:0] "Reserved" 7248c2ecf20Sopenharmony_ci * = 0 (0x00) .....000 7258c2ecf20Sopenharmony_ci */ 7268c2ecf20Sopenharmony_ci { 0x0e, 0x70 }, 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci /* 7298c2ecf20Sopenharmony_ci * 0F COMG "Common Control G" 7308c2ecf20Sopenharmony_ci * = 66 (0x42) 01000010 7318c2ecf20Sopenharmony_ci * COMG[7] "Optical black output selection" 7328c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "Disable" 7338c2ecf20Sopenharmony_ci * COMG[6] "Black level calibrate selection" 7348c2ecf20Sopenharmony_ci * = 1 (0x01) .1...... "Use optical black pixels 7358c2ecf20Sopenharmony_ci * to calibrate" 7368c2ecf20Sopenharmony_ci * COMG[5:4] "Reserved" 7378c2ecf20Sopenharmony_ci * = 0 (0x00) ..00.... 7388c2ecf20Sopenharmony_ci * COMG[3] "Channel offset adjustment" 7398c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... "Disable offset adjustment" 7408c2ecf20Sopenharmony_ci * COMG[2] "ADC black level calibration option" 7418c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "Use B/G line and G/R 7428c2ecf20Sopenharmony_ci * line to calibrate each 7438c2ecf20Sopenharmony_ci * channel's black level" 7448c2ecf20Sopenharmony_ci * COMG[1] "Reserved" 7458c2ecf20Sopenharmony_ci * = 1 (0x01) ......1. 7468c2ecf20Sopenharmony_ci * COMG[0] "ADC black level calibration enable" 7478c2ecf20Sopenharmony_ci * = 0 (0x00) .......0 "Disable" 7488c2ecf20Sopenharmony_ci */ 7498c2ecf20Sopenharmony_ci { 0x0f, 0x42 }, 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci /* 7528c2ecf20Sopenharmony_ci * 14 COMJ "Common Control J" 7538c2ecf20Sopenharmony_ci * = 198 (0xC6) 11000110 7548c2ecf20Sopenharmony_ci * COMJ[7:6] "AGC gain ceiling" 7558c2ecf20Sopenharmony_ci * = 3 (0x03) 11...... "8x" 7568c2ecf20Sopenharmony_ci * COMJ[5:4] "Reserved" 7578c2ecf20Sopenharmony_ci * = 0 (0x00) ..00.... 7588c2ecf20Sopenharmony_ci * COMJ[3] "Auto banding filter" 7598c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... "Banding filter is always 7608c2ecf20Sopenharmony_ci * on off depending on 7618c2ecf20Sopenharmony_ci * COMI[5] setting" 7628c2ecf20Sopenharmony_ci * COMJ[2] "VSYNC drop option" 7638c2ecf20Sopenharmony_ci * = 1 (0x01) .....1.. "SYNC is dropped if frame 7648c2ecf20Sopenharmony_ci * data is dropped" 7658c2ecf20Sopenharmony_ci * COMJ[1] "Frame data drop" 7668c2ecf20Sopenharmony_ci * = 1 (0x01) ......1. "Drop frame data if 7678c2ecf20Sopenharmony_ci * exposure is not within 7688c2ecf20Sopenharmony_ci * tolerance. In AEC mode, 7698c2ecf20Sopenharmony_ci * data is normally dropped 7708c2ecf20Sopenharmony_ci * when data is out of 7718c2ecf20Sopenharmony_ci * range." 7728c2ecf20Sopenharmony_ci * COMJ[0] "Reserved" 7738c2ecf20Sopenharmony_ci * = 0 (0x00) .......0 7748c2ecf20Sopenharmony_ci */ 7758c2ecf20Sopenharmony_ci { 0x14, 0xc6 }, 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci /* 7788c2ecf20Sopenharmony_ci * 15 COMK "Common Control K" 7798c2ecf20Sopenharmony_ci * = 2 (0x02) 00000010 7808c2ecf20Sopenharmony_ci * COMK[7] "CHSYNC pin output swap" 7818c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "CHSYNC" 7828c2ecf20Sopenharmony_ci * COMK[6] "HREF pin output swap" 7838c2ecf20Sopenharmony_ci * = 0 (0x00) .0...... "HREF" 7848c2ecf20Sopenharmony_ci * COMK[5] "PCLK output selection" 7858c2ecf20Sopenharmony_ci * = 0 (0x00) ..0..... "PCLK always output" 7868c2ecf20Sopenharmony_ci * COMK[4] "PCLK edge selection" 7878c2ecf20Sopenharmony_ci * = 0 (0x00) ...0.... "Data valid on falling edge" 7888c2ecf20Sopenharmony_ci * COMK[3] "HREF output polarity" 7898c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... "positive" 7908c2ecf20Sopenharmony_ci * COMK[2] "Reserved" 7918c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. 7928c2ecf20Sopenharmony_ci * COMK[1] "VSYNC polarity" 7938c2ecf20Sopenharmony_ci * = 1 (0x01) ......1. "negative" 7948c2ecf20Sopenharmony_ci * COMK[0] "HSYNC polarity" 7958c2ecf20Sopenharmony_ci * = 0 (0x00) .......0 "positive" 7968c2ecf20Sopenharmony_ci */ 7978c2ecf20Sopenharmony_ci { 0x15, 0x02 }, 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* 8008c2ecf20Sopenharmony_ci * 33 CHLF "Current Control" 8018c2ecf20Sopenharmony_ci * = 9 (0x09) 00001001 8028c2ecf20Sopenharmony_ci * CHLF[7:6] "Sensor current control" 8038c2ecf20Sopenharmony_ci * = 0 (0x00) 00...... 8048c2ecf20Sopenharmony_ci * CHLF[5] "Sensor current range control" 8058c2ecf20Sopenharmony_ci * = 0 (0x00) ..0..... "normal range" 8068c2ecf20Sopenharmony_ci * CHLF[4] "Sensor current" 8078c2ecf20Sopenharmony_ci * = 0 (0x00) ...0.... "normal current" 8088c2ecf20Sopenharmony_ci * CHLF[3] "Sensor buffer current control" 8098c2ecf20Sopenharmony_ci * = 1 (0x01) ....1... "half current" 8108c2ecf20Sopenharmony_ci * CHLF[2] "Column buffer current control" 8118c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "normal current" 8128c2ecf20Sopenharmony_ci * CHLF[1] "Analog DSP current control" 8138c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 8148c2ecf20Sopenharmony_ci * CHLF[1] "ADC current control" 8158c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 8168c2ecf20Sopenharmony_ci */ 8178c2ecf20Sopenharmony_ci { 0x33, 0x09 }, 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci /* 8208c2ecf20Sopenharmony_ci * 34 VBLM "Blooming Control" 8218c2ecf20Sopenharmony_ci * = 80 (0x50) 01010000 8228c2ecf20Sopenharmony_ci * VBLM[7] "Hard soft reset switch" 8238c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "Hard reset" 8248c2ecf20Sopenharmony_ci * VBLM[6:4] "Blooming voltage selection" 8258c2ecf20Sopenharmony_ci * = 5 (0x05) .101.... 8268c2ecf20Sopenharmony_ci * VBLM[3:0] "Sensor current control" 8278c2ecf20Sopenharmony_ci * = 0 (0x00) ....0000 8288c2ecf20Sopenharmony_ci */ 8298c2ecf20Sopenharmony_ci { 0x34, 0x50 }, 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci /* 8328c2ecf20Sopenharmony_ci * 36 VCHG "Sensor Precharge Voltage Control" 8338c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 8348c2ecf20Sopenharmony_ci * VCHG[7] "Reserved" 8358c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... 8368c2ecf20Sopenharmony_ci * VCHG[6:4] "Sensor precharge voltage control" 8378c2ecf20Sopenharmony_ci * = 0 (0x00) .000.... 8388c2ecf20Sopenharmony_ci * VCHG[3:0] "Sensor array common reference" 8398c2ecf20Sopenharmony_ci * = 0 (0x00) ....0000 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_ci { 0x36, 0x00 }, 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci /* 8448c2ecf20Sopenharmony_ci * 37 ADC "ADC Reference Control" 8458c2ecf20Sopenharmony_ci * = 4 (0x04) 00000100 8468c2ecf20Sopenharmony_ci * ADC[7:4] "Reserved" 8478c2ecf20Sopenharmony_ci * = 0 (0x00) 0000.... 8488c2ecf20Sopenharmony_ci * ADC[3] "ADC input signal range" 8498c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... "Input signal 1.0x" 8508c2ecf20Sopenharmony_ci * ADC[2:0] "ADC range control" 8518c2ecf20Sopenharmony_ci * = 4 (0x04) .....100 8528c2ecf20Sopenharmony_ci */ 8538c2ecf20Sopenharmony_ci { 0x37, 0x04 }, 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci /* 8568c2ecf20Sopenharmony_ci * 38 ACOM "Analog Common Ground" 8578c2ecf20Sopenharmony_ci * = 82 (0x52) 01010010 8588c2ecf20Sopenharmony_ci * ACOM[7] "Analog gain control" 8598c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "Gain 1x" 8608c2ecf20Sopenharmony_ci * ACOM[6] "Analog black level calibration" 8618c2ecf20Sopenharmony_ci * = 1 (0x01) .1...... "On" 8628c2ecf20Sopenharmony_ci * ACOM[5:0] "Reserved" 8638c2ecf20Sopenharmony_ci * = 18 (0x12) ..010010 8648c2ecf20Sopenharmony_ci */ 8658c2ecf20Sopenharmony_ci { 0x38, 0x52 }, 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci /* 8688c2ecf20Sopenharmony_ci * 3A FREFA "Internal Reference Adjustment" 8698c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 8708c2ecf20Sopenharmony_ci * FREFA[7:0] "Range" 8718c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 8728c2ecf20Sopenharmony_ci */ 8738c2ecf20Sopenharmony_ci { 0x3a, 0x00 }, 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci /* 8768c2ecf20Sopenharmony_ci * 3C FVOPT "Internal Reference Adjustment" 8778c2ecf20Sopenharmony_ci * = 31 (0x1F) 00011111 8788c2ecf20Sopenharmony_ci * FVOPT[7:0] "Range" 8798c2ecf20Sopenharmony_ci * = 31 (0x1F) 00011111 8808c2ecf20Sopenharmony_ci */ 8818c2ecf20Sopenharmony_ci { 0x3c, 0x1f }, 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci /* 8848c2ecf20Sopenharmony_ci * 44 Undocumented = 0 (0x00) 00000000 8858c2ecf20Sopenharmony_ci * 44[7:0] "It's a secret" 8868c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 8878c2ecf20Sopenharmony_ci */ 8888c2ecf20Sopenharmony_ci { 0x44, 0x00 }, 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci /* 8918c2ecf20Sopenharmony_ci * 40 Undocumented = 0 (0x00) 00000000 8928c2ecf20Sopenharmony_ci * 40[7:0] "It's a secret" 8938c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 8948c2ecf20Sopenharmony_ci */ 8958c2ecf20Sopenharmony_ci { 0x40, 0x00 }, 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* 8988c2ecf20Sopenharmony_ci * 41 Undocumented = 0 (0x00) 00000000 8998c2ecf20Sopenharmony_ci * 41[7:0] "It's a secret" 9008c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 9018c2ecf20Sopenharmony_ci */ 9028c2ecf20Sopenharmony_ci { 0x41, 0x00 }, 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci /* 9058c2ecf20Sopenharmony_ci * 42 Undocumented = 0 (0x00) 00000000 9068c2ecf20Sopenharmony_ci * 42[7:0] "It's a secret" 9078c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 9088c2ecf20Sopenharmony_ci */ 9098c2ecf20Sopenharmony_ci { 0x42, 0x00 }, 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci /* 9128c2ecf20Sopenharmony_ci * 43 Undocumented = 0 (0x00) 00000000 9138c2ecf20Sopenharmony_ci * 43[7:0] "It's a secret" 9148c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 9158c2ecf20Sopenharmony_ci */ 9168c2ecf20Sopenharmony_ci { 0x43, 0x00 }, 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci /* 9198c2ecf20Sopenharmony_ci * 45 Undocumented = 128 (0x80) 10000000 9208c2ecf20Sopenharmony_ci * 45[7:0] "It's a secret" 9218c2ecf20Sopenharmony_ci * = 128 (0x80) 10000000 9228c2ecf20Sopenharmony_ci */ 9238c2ecf20Sopenharmony_ci { 0x45, 0x80 }, 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci /* 9268c2ecf20Sopenharmony_ci * 48 Undocumented = 192 (0xC0) 11000000 9278c2ecf20Sopenharmony_ci * 48[7:0] "It's a secret" 9288c2ecf20Sopenharmony_ci * = 192 (0xC0) 11000000 9298c2ecf20Sopenharmony_ci */ 9308c2ecf20Sopenharmony_ci { 0x48, 0xc0 }, 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci /* 9338c2ecf20Sopenharmony_ci * 49 Undocumented = 25 (0x19) 00011001 9348c2ecf20Sopenharmony_ci * 49[7:0] "It's a secret" 9358c2ecf20Sopenharmony_ci * = 25 (0x19) 00011001 9368c2ecf20Sopenharmony_ci */ 9378c2ecf20Sopenharmony_ci { 0x49, 0x19 }, 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* 9408c2ecf20Sopenharmony_ci * 4B Undocumented = 128 (0x80) 10000000 9418c2ecf20Sopenharmony_ci * 4B[7:0] "It's a secret" 9428c2ecf20Sopenharmony_ci * = 128 (0x80) 10000000 9438c2ecf20Sopenharmony_ci */ 9448c2ecf20Sopenharmony_ci { 0x4b, 0x80 }, 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci /* 9478c2ecf20Sopenharmony_ci * 4D Undocumented = 196 (0xC4) 11000100 9488c2ecf20Sopenharmony_ci * 4D[7:0] "It's a secret" 9498c2ecf20Sopenharmony_ci * = 196 (0xC4) 11000100 9508c2ecf20Sopenharmony_ci */ 9518c2ecf20Sopenharmony_ci { 0x4d, 0xc4 }, 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* 9548c2ecf20Sopenharmony_ci * 35 VREF "Reference Voltage Control" 9558c2ecf20Sopenharmony_ci * = 76 (0x4c) 01001100 9568c2ecf20Sopenharmony_ci * VREF[7:5] "Column high reference control" 9578c2ecf20Sopenharmony_ci * = 2 (0x02) 010..... "higher voltage" 9588c2ecf20Sopenharmony_ci * VREF[4:2] "Column low reference control" 9598c2ecf20Sopenharmony_ci * = 3 (0x03) ...011.. "Highest voltage" 9608c2ecf20Sopenharmony_ci * VREF[1:0] "Reserved" 9618c2ecf20Sopenharmony_ci * = 0 (0x00) ......00 9628c2ecf20Sopenharmony_ci */ 9638c2ecf20Sopenharmony_ci { 0x35, 0x4c }, 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci /* 9668c2ecf20Sopenharmony_ci * 3D Undocumented = 0 (0x00) 00000000 9678c2ecf20Sopenharmony_ci * 3D[7:0] "It's a secret" 9688c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 9698c2ecf20Sopenharmony_ci */ 9708c2ecf20Sopenharmony_ci { 0x3d, 0x00 }, 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci /* 9738c2ecf20Sopenharmony_ci * 3E Undocumented = 0 (0x00) 00000000 9748c2ecf20Sopenharmony_ci * 3E[7:0] "It's a secret" 9758c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 9768c2ecf20Sopenharmony_ci */ 9778c2ecf20Sopenharmony_ci { 0x3e, 0x00 }, 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci /* 9808c2ecf20Sopenharmony_ci * 3B FREFB "Internal Reference Adjustment" 9818c2ecf20Sopenharmony_ci * = 24 (0x18) 00011000 9828c2ecf20Sopenharmony_ci * FREFB[7:0] "Range" 9838c2ecf20Sopenharmony_ci * = 24 (0x18) 00011000 9848c2ecf20Sopenharmony_ci */ 9858c2ecf20Sopenharmony_ci { 0x3b, 0x18 }, 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci /* 9888c2ecf20Sopenharmony_ci * 33 CHLF "Current Control" 9898c2ecf20Sopenharmony_ci * = 25 (0x19) 00011001 9908c2ecf20Sopenharmony_ci * CHLF[7:6] "Sensor current control" 9918c2ecf20Sopenharmony_ci * = 0 (0x00) 00...... 9928c2ecf20Sopenharmony_ci * CHLF[5] "Sensor current range control" 9938c2ecf20Sopenharmony_ci * = 0 (0x00) ..0..... "normal range" 9948c2ecf20Sopenharmony_ci * CHLF[4] "Sensor current" 9958c2ecf20Sopenharmony_ci * = 1 (0x01) ...1.... "double current" 9968c2ecf20Sopenharmony_ci * CHLF[3] "Sensor buffer current control" 9978c2ecf20Sopenharmony_ci * = 1 (0x01) ....1... "half current" 9988c2ecf20Sopenharmony_ci * CHLF[2] "Column buffer current control" 9998c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "normal current" 10008c2ecf20Sopenharmony_ci * CHLF[1] "Analog DSP current control" 10018c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 10028c2ecf20Sopenharmony_ci * CHLF[1] "ADC current control" 10038c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 10048c2ecf20Sopenharmony_ci */ 10058c2ecf20Sopenharmony_ci { 0x33, 0x19 }, 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci /* 10088c2ecf20Sopenharmony_ci * 34 VBLM "Blooming Control" 10098c2ecf20Sopenharmony_ci * = 90 (0x5A) 01011010 10108c2ecf20Sopenharmony_ci * VBLM[7] "Hard soft reset switch" 10118c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "Hard reset" 10128c2ecf20Sopenharmony_ci * VBLM[6:4] "Blooming voltage selection" 10138c2ecf20Sopenharmony_ci * = 5 (0x05) .101.... 10148c2ecf20Sopenharmony_ci * VBLM[3:0] "Sensor current control" 10158c2ecf20Sopenharmony_ci * = 10 (0x0A) ....1010 10168c2ecf20Sopenharmony_ci */ 10178c2ecf20Sopenharmony_ci { 0x34, 0x5a }, 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci /* 10208c2ecf20Sopenharmony_ci * 3B FREFB "Internal Reference Adjustment" 10218c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 10228c2ecf20Sopenharmony_ci * FREFB[7:0] "Range" 10238c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 10248c2ecf20Sopenharmony_ci */ 10258c2ecf20Sopenharmony_ci { 0x3b, 0x00 }, 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /* 10288c2ecf20Sopenharmony_ci * 33 CHLF "Current Control" 10298c2ecf20Sopenharmony_ci * = 9 (0x09) 00001001 10308c2ecf20Sopenharmony_ci * CHLF[7:6] "Sensor current control" 10318c2ecf20Sopenharmony_ci * = 0 (0x00) 00...... 10328c2ecf20Sopenharmony_ci * CHLF[5] "Sensor current range control" 10338c2ecf20Sopenharmony_ci * = 0 (0x00) ..0..... "normal range" 10348c2ecf20Sopenharmony_ci * CHLF[4] "Sensor current" 10358c2ecf20Sopenharmony_ci * = 0 (0x00) ...0.... "normal current" 10368c2ecf20Sopenharmony_ci * CHLF[3] "Sensor buffer current control" 10378c2ecf20Sopenharmony_ci * = 1 (0x01) ....1... "half current" 10388c2ecf20Sopenharmony_ci * CHLF[2] "Column buffer current control" 10398c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "normal current" 10408c2ecf20Sopenharmony_ci * CHLF[1] "Analog DSP current control" 10418c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 10428c2ecf20Sopenharmony_ci * CHLF[1] "ADC current control" 10438c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "normal current" 10448c2ecf20Sopenharmony_ci */ 10458c2ecf20Sopenharmony_ci { 0x33, 0x09 }, 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci /* 10488c2ecf20Sopenharmony_ci * 34 VBLM "Blooming Control" 10498c2ecf20Sopenharmony_ci * = 80 (0x50) 01010000 10508c2ecf20Sopenharmony_ci * VBLM[7] "Hard soft reset switch" 10518c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "Hard reset" 10528c2ecf20Sopenharmony_ci * VBLM[6:4] "Blooming voltage selection" 10538c2ecf20Sopenharmony_ci * = 5 (0x05) .101.... 10548c2ecf20Sopenharmony_ci * VBLM[3:0] "Sensor current control" 10558c2ecf20Sopenharmony_ci * = 0 (0x00) ....0000 10568c2ecf20Sopenharmony_ci */ 10578c2ecf20Sopenharmony_ci { 0x34, 0x50 }, 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci /* 10608c2ecf20Sopenharmony_ci * 12 COMH "Common Control H" 10618c2ecf20Sopenharmony_ci * = 64 (0x40) 01000000 10628c2ecf20Sopenharmony_ci * COMH[7] "SRST" 10638c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "No-op" 10648c2ecf20Sopenharmony_ci * COMH[6:4] "Resolution selection" 10658c2ecf20Sopenharmony_ci * = 4 (0x04) .100.... "XGA" 10668c2ecf20Sopenharmony_ci * COMH[3] "Master slave selection" 10678c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... "Master mode" 10688c2ecf20Sopenharmony_ci * COMH[2] "Internal B/R channel option" 10698c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "B/R use same channel" 10708c2ecf20Sopenharmony_ci * COMH[1] "Color bar test pattern" 10718c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "Off" 10728c2ecf20Sopenharmony_ci * COMH[0] "Reserved" 10738c2ecf20Sopenharmony_ci * = 0 (0x00) .......0 10748c2ecf20Sopenharmony_ci */ 10758c2ecf20Sopenharmony_ci { 0x12, 0x40 }, 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci /* 10788c2ecf20Sopenharmony_ci * 17 HREFST "Horizontal window start" 10798c2ecf20Sopenharmony_ci * = 31 (0x1F) 00011111 10808c2ecf20Sopenharmony_ci * HREFST[7:0] "Horizontal window start, 8 MSBs" 10818c2ecf20Sopenharmony_ci * = 31 (0x1F) 00011111 10828c2ecf20Sopenharmony_ci */ 10838c2ecf20Sopenharmony_ci { 0x17, 0x1f }, 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci /* 10868c2ecf20Sopenharmony_ci * 18 HREFEND "Horizontal window end" 10878c2ecf20Sopenharmony_ci * = 95 (0x5F) 01011111 10888c2ecf20Sopenharmony_ci * HREFEND[7:0] "Horizontal Window End, 8 MSBs" 10898c2ecf20Sopenharmony_ci * = 95 (0x5F) 01011111 10908c2ecf20Sopenharmony_ci */ 10918c2ecf20Sopenharmony_ci { 0x18, 0x5f }, 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci /* 10948c2ecf20Sopenharmony_ci * 19 VSTRT "Vertical window start" 10958c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 10968c2ecf20Sopenharmony_ci * VSTRT[7:0] "Vertical Window Start, 8 MSBs" 10978c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 10988c2ecf20Sopenharmony_ci */ 10998c2ecf20Sopenharmony_ci { 0x19, 0x00 }, 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci /* 11028c2ecf20Sopenharmony_ci * 1A VEND "Vertical window end" 11038c2ecf20Sopenharmony_ci * = 96 (0x60) 01100000 11048c2ecf20Sopenharmony_ci * VEND[7:0] "Vertical Window End, 8 MSBs" 11058c2ecf20Sopenharmony_ci * = 96 (0x60) 01100000 11068c2ecf20Sopenharmony_ci */ 11078c2ecf20Sopenharmony_ci { 0x1a, 0x60 }, 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci /* 11108c2ecf20Sopenharmony_ci * 32 COMM "Common Control M" 11118c2ecf20Sopenharmony_ci * = 18 (0x12) 00010010 11128c2ecf20Sopenharmony_ci * COMM[7:6] "Pixel clock divide option" 11138c2ecf20Sopenharmony_ci * = 0 (0x00) 00...... "/1" 11148c2ecf20Sopenharmony_ci * COMM[5:3] "Horizontal window end position, 3 LSBs" 11158c2ecf20Sopenharmony_ci * = 2 (0x02) ..010... 11168c2ecf20Sopenharmony_ci * COMM[2:0] "Horizontal window start position, 3 LSBs" 11178c2ecf20Sopenharmony_ci * = 2 (0x02) .....010 11188c2ecf20Sopenharmony_ci */ 11198c2ecf20Sopenharmony_ci { 0x32, 0x12 }, 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci /* 11228c2ecf20Sopenharmony_ci * 03 COMA "Common Control A" 11238c2ecf20Sopenharmony_ci * = 74 (0x4A) 01001010 11248c2ecf20Sopenharmony_ci * COMA[7:4] "AWB Update Threshold" 11258c2ecf20Sopenharmony_ci * = 4 (0x04) 0100.... 11268c2ecf20Sopenharmony_ci * COMA[3:2] "Vertical window end line control 2 LSBs" 11278c2ecf20Sopenharmony_ci * = 2 (0x02) ....10.. 11288c2ecf20Sopenharmony_ci * COMA[1:0] "Vertical window start line control 2 LSBs" 11298c2ecf20Sopenharmony_ci * = 2 (0x02) ......10 11308c2ecf20Sopenharmony_ci */ 11318c2ecf20Sopenharmony_ci { 0x03, 0x4a }, 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci /* 11348c2ecf20Sopenharmony_ci * 11 CLKRC "Clock Rate Control" 11358c2ecf20Sopenharmony_ci * = 128 (0x80) 10000000 11368c2ecf20Sopenharmony_ci * CLKRC[7] "Internal frequency doublers on off seclection" 11378c2ecf20Sopenharmony_ci * = 1 (0x01) 1....... "On" 11388c2ecf20Sopenharmony_ci * CLKRC[6] "Digital video master slave selection" 11398c2ecf20Sopenharmony_ci * = 0 (0x00) .0...... "Master mode, sensor 11408c2ecf20Sopenharmony_ci * provides PCLK" 11418c2ecf20Sopenharmony_ci * CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }" 11428c2ecf20Sopenharmony_ci * = 0 (0x00) ..000000 11438c2ecf20Sopenharmony_ci */ 11448c2ecf20Sopenharmony_ci { 0x11, 0x80 }, 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci /* 11478c2ecf20Sopenharmony_ci * 12 COMH "Common Control H" 11488c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 11498c2ecf20Sopenharmony_ci * COMH[7] "SRST" 11508c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "No-op" 11518c2ecf20Sopenharmony_ci * COMH[6:4] "Resolution selection" 11528c2ecf20Sopenharmony_ci * = 0 (0x00) .000.... "QXGA" 11538c2ecf20Sopenharmony_ci * COMH[3] "Master slave selection" 11548c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... "Master mode" 11558c2ecf20Sopenharmony_ci * COMH[2] "Internal B/R channel option" 11568c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "B/R use same channel" 11578c2ecf20Sopenharmony_ci * COMH[1] "Color bar test pattern" 11588c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "Off" 11598c2ecf20Sopenharmony_ci * COMH[0] "Reserved" 11608c2ecf20Sopenharmony_ci * = 0 (0x00) .......0 11618c2ecf20Sopenharmony_ci */ 11628c2ecf20Sopenharmony_ci { 0x12, 0x00 }, 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci /* 11658c2ecf20Sopenharmony_ci * 12 COMH "Common Control H" 11668c2ecf20Sopenharmony_ci * = 64 (0x40) 01000000 11678c2ecf20Sopenharmony_ci * COMH[7] "SRST" 11688c2ecf20Sopenharmony_ci * = 0 (0x00) 0....... "No-op" 11698c2ecf20Sopenharmony_ci * COMH[6:4] "Resolution selection" 11708c2ecf20Sopenharmony_ci * = 4 (0x04) .100.... "XGA" 11718c2ecf20Sopenharmony_ci * COMH[3] "Master slave selection" 11728c2ecf20Sopenharmony_ci * = 0 (0x00) ....0... "Master mode" 11738c2ecf20Sopenharmony_ci * COMH[2] "Internal B/R channel option" 11748c2ecf20Sopenharmony_ci * = 0 (0x00) .....0.. "B/R use same channel" 11758c2ecf20Sopenharmony_ci * COMH[1] "Color bar test pattern" 11768c2ecf20Sopenharmony_ci * = 0 (0x00) ......0. "Off" 11778c2ecf20Sopenharmony_ci * COMH[0] "Reserved" 11788c2ecf20Sopenharmony_ci * = 0 (0x00) .......0 11798c2ecf20Sopenharmony_ci */ 11808c2ecf20Sopenharmony_ci { 0x12, 0x40 }, 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci /* 11838c2ecf20Sopenharmony_ci * 17 HREFST "Horizontal window start" 11848c2ecf20Sopenharmony_ci * = 31 (0x1F) 00011111 11858c2ecf20Sopenharmony_ci * HREFST[7:0] "Horizontal window start, 8 MSBs" 11868c2ecf20Sopenharmony_ci * = 31 (0x1F) 00011111 11878c2ecf20Sopenharmony_ci */ 11888c2ecf20Sopenharmony_ci { 0x17, 0x1f }, 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci /* 11918c2ecf20Sopenharmony_ci * 18 HREFEND "Horizontal window end" 11928c2ecf20Sopenharmony_ci * = 95 (0x5F) 01011111 11938c2ecf20Sopenharmony_ci * HREFEND[7:0] "Horizontal Window End, 8 MSBs" 11948c2ecf20Sopenharmony_ci * = 95 (0x5F) 01011111 11958c2ecf20Sopenharmony_ci */ 11968c2ecf20Sopenharmony_ci { 0x18, 0x5f }, 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci /* 11998c2ecf20Sopenharmony_ci * 19 VSTRT "Vertical window start" 12008c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 12018c2ecf20Sopenharmony_ci * VSTRT[7:0] "Vertical Window Start, 8 MSBs" 12028c2ecf20Sopenharmony_ci * = 0 (0x00) 00000000 12038c2ecf20Sopenharmony_ci */ 12048c2ecf20Sopenharmony_ci { 0x19, 0x00 }, 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci /* 12078c2ecf20Sopenharmony_ci * 1A VEND "Vertical window end" 12088c2ecf20Sopenharmony_ci * = 96 (0x60) 01100000 12098c2ecf20Sopenharmony_ci * VEND[7:0] "Vertical Window End, 8 MSBs" 12108c2ecf20Sopenharmony_ci * = 96 (0x60) 01100000 12118c2ecf20Sopenharmony_ci */ 12128c2ecf20Sopenharmony_ci { 0x1a, 0x60 }, 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci /* 12158c2ecf20Sopenharmony_ci * 32 COMM "Common Control M" 12168c2ecf20Sopenharmony_ci * = 18 (0x12) 00010010 12178c2ecf20Sopenharmony_ci * COMM[7:6] "Pixel clock divide option" 12188c2ecf20Sopenharmony_ci * = 0 (0x00) 00...... "/1" 12198c2ecf20Sopenharmony_ci * COMM[5:3] "Horizontal window end position, 3 LSBs" 12208c2ecf20Sopenharmony_ci * = 2 (0x02) ..010... 12218c2ecf20Sopenharmony_ci * COMM[2:0] "Horizontal window start position, 3 LSBs" 12228c2ecf20Sopenharmony_ci * = 2 (0x02) .....010 12238c2ecf20Sopenharmony_ci */ 12248c2ecf20Sopenharmony_ci { 0x32, 0x12 }, 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci /* 12278c2ecf20Sopenharmony_ci * 03 COMA "Common Control A" 12288c2ecf20Sopenharmony_ci * = 74 (0x4A) 01001010 12298c2ecf20Sopenharmony_ci * COMA[7:4] "AWB Update Threshold" 12308c2ecf20Sopenharmony_ci * = 4 (0x04) 0100.... 12318c2ecf20Sopenharmony_ci * COMA[3:2] "Vertical window end line control 2 LSBs" 12328c2ecf20Sopenharmony_ci * = 2 (0x02) ....10.. 12338c2ecf20Sopenharmony_ci * COMA[1:0] "Vertical window start line control 2 LSBs" 12348c2ecf20Sopenharmony_ci * = 2 (0x02) ......10 12358c2ecf20Sopenharmony_ci */ 12368c2ecf20Sopenharmony_ci { 0x03, 0x4a }, 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci /* 12398c2ecf20Sopenharmony_ci * 02 RED "Red Gain Control" 12408c2ecf20Sopenharmony_ci * = 175 (0xAF) 10101111 12418c2ecf20Sopenharmony_ci * RED[7] "Action" 12428c2ecf20Sopenharmony_ci * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" 12438c2ecf20Sopenharmony_ci * RED[6:0] "Value" 12448c2ecf20Sopenharmony_ci * = 47 (0x2F) .0101111 12458c2ecf20Sopenharmony_ci */ 12468c2ecf20Sopenharmony_ci { 0x02, 0xaf }, 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci /* 12498c2ecf20Sopenharmony_ci * 2D ADDVSL "VSYNC Pulse Width" 12508c2ecf20Sopenharmony_ci * = 210 (0xD2) 11010010 12518c2ecf20Sopenharmony_ci * ADDVSL[7:0] "VSYNC pulse width, LSB" 12528c2ecf20Sopenharmony_ci * = 210 (0xD2) 11010010 12538c2ecf20Sopenharmony_ci */ 12548c2ecf20Sopenharmony_ci { 0x2d, 0xd2 }, 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci /* 12578c2ecf20Sopenharmony_ci * 00 GAIN = 24 (0x18) 00011000 12588c2ecf20Sopenharmony_ci * GAIN[7:6] "Reserved" 12598c2ecf20Sopenharmony_ci * = 0 (0x00) 00...... 12608c2ecf20Sopenharmony_ci * GAIN[5] "Double" 12618c2ecf20Sopenharmony_ci * = 0 (0x00) ..0..... "False" 12628c2ecf20Sopenharmony_ci * GAIN[4] "Double" 12638c2ecf20Sopenharmony_ci * = 1 (0x01) ...1.... "True" 12648c2ecf20Sopenharmony_ci * GAIN[3:0] "Range" 12658c2ecf20Sopenharmony_ci * = 8 (0x08) ....1000 12668c2ecf20Sopenharmony_ci */ 12678c2ecf20Sopenharmony_ci { 0x00, 0x18 }, 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci /* 12708c2ecf20Sopenharmony_ci * 01 BLUE "Blue Gain Control" 12718c2ecf20Sopenharmony_ci * = 240 (0xF0) 11110000 12728c2ecf20Sopenharmony_ci * BLUE[7] "Action" 12738c2ecf20Sopenharmony_ci * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" 12748c2ecf20Sopenharmony_ci * BLUE[6:0] "Value" 12758c2ecf20Sopenharmony_ci * = 112 (0x70) .1110000 12768c2ecf20Sopenharmony_ci */ 12778c2ecf20Sopenharmony_ci { 0x01, 0xf0 }, 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci /* 12808c2ecf20Sopenharmony_ci * 10 AEC "Automatic Exposure Control" 12818c2ecf20Sopenharmony_ci * = 10 (0x0A) 00001010 12828c2ecf20Sopenharmony_ci * AEC[7:0] "Automatic Exposure Control, 8 MSBs" 12838c2ecf20Sopenharmony_ci * = 10 (0x0A) 00001010 12848c2ecf20Sopenharmony_ci */ 12858c2ecf20Sopenharmony_ci { 0x10, 0x0a }, 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci { 0xe1, 0x67 }, 12888c2ecf20Sopenharmony_ci { 0xe3, 0x03 }, 12898c2ecf20Sopenharmony_ci { 0xe4, 0x26 }, 12908c2ecf20Sopenharmony_ci { 0xe5, 0x3e }, 12918c2ecf20Sopenharmony_ci { 0xf8, 0x01 }, 12928c2ecf20Sopenharmony_ci { 0xff, 0x01 }, 12938c2ecf20Sopenharmony_ci}; 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_6x20[] = { 12968c2ecf20Sopenharmony_ci { 0x12, 0x80 }, /* reset */ 12978c2ecf20Sopenharmony_ci { 0x11, 0x01 }, 12988c2ecf20Sopenharmony_ci { 0x03, 0x60 }, 12998c2ecf20Sopenharmony_ci { 0x05, 0x7f }, /* For when autoadjust is off */ 13008c2ecf20Sopenharmony_ci { 0x07, 0xa8 }, 13018c2ecf20Sopenharmony_ci /* The ratio of 0x0c and 0x0d controls the white point */ 13028c2ecf20Sopenharmony_ci { 0x0c, 0x24 }, 13038c2ecf20Sopenharmony_ci { 0x0d, 0x24 }, 13048c2ecf20Sopenharmony_ci { 0x0f, 0x15 }, /* COMS */ 13058c2ecf20Sopenharmony_ci { 0x10, 0x75 }, /* AEC Exposure time */ 13068c2ecf20Sopenharmony_ci { 0x12, 0x24 }, /* Enable AGC */ 13078c2ecf20Sopenharmony_ci { 0x14, 0x04 }, 13088c2ecf20Sopenharmony_ci /* 0x16: 0x06 helps frame stability with moving objects */ 13098c2ecf20Sopenharmony_ci { 0x16, 0x06 }, 13108c2ecf20Sopenharmony_ci/* { 0x20, 0x30 }, * Aperture correction enable */ 13118c2ecf20Sopenharmony_ci { 0x26, 0xb2 }, /* BLC enable */ 13128c2ecf20Sopenharmony_ci /* 0x28: 0x05 Selects RGB format if RGB on */ 13138c2ecf20Sopenharmony_ci { 0x28, 0x05 }, 13148c2ecf20Sopenharmony_ci { 0x2a, 0x04 }, /* Disable framerate adjust */ 13158c2ecf20Sopenharmony_ci/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */ 13168c2ecf20Sopenharmony_ci { 0x2d, 0x85 }, 13178c2ecf20Sopenharmony_ci { 0x33, 0xa0 }, /* Color Processing Parameter */ 13188c2ecf20Sopenharmony_ci { 0x34, 0xd2 }, /* Max A/D range */ 13198c2ecf20Sopenharmony_ci { 0x38, 0x8b }, 13208c2ecf20Sopenharmony_ci { 0x39, 0x40 }, 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci { 0x3c, 0x39 }, /* Enable AEC mode changing */ 13238c2ecf20Sopenharmony_ci { 0x3c, 0x3c }, /* Change AEC mode */ 13248c2ecf20Sopenharmony_ci { 0x3c, 0x24 }, /* Disable AEC mode changing */ 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci { 0x3d, 0x80 }, 13278c2ecf20Sopenharmony_ci /* These next two registers (0x4a, 0x4b) are undocumented. 13288c2ecf20Sopenharmony_ci * They control the color balance */ 13298c2ecf20Sopenharmony_ci { 0x4a, 0x80 }, 13308c2ecf20Sopenharmony_ci { 0x4b, 0x80 }, 13318c2ecf20Sopenharmony_ci { 0x4d, 0xd2 }, /* This reduces noise a bit */ 13328c2ecf20Sopenharmony_ci { 0x4e, 0xc1 }, 13338c2ecf20Sopenharmony_ci { 0x4f, 0x04 }, 13348c2ecf20Sopenharmony_ci/* Do 50-53 have any effect? */ 13358c2ecf20Sopenharmony_ci/* Toggle 0x12[2] off and on here? */ 13368c2ecf20Sopenharmony_ci}; 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_6x30[] = { 13398c2ecf20Sopenharmony_ci { 0x12, 0x80 }, /* Reset */ 13408c2ecf20Sopenharmony_ci { 0x00, 0x1f }, /* Gain */ 13418c2ecf20Sopenharmony_ci { 0x01, 0x99 }, /* Blue gain */ 13428c2ecf20Sopenharmony_ci { 0x02, 0x7c }, /* Red gain */ 13438c2ecf20Sopenharmony_ci { 0x03, 0xc0 }, /* Saturation */ 13448c2ecf20Sopenharmony_ci { 0x05, 0x0a }, /* Contrast */ 13458c2ecf20Sopenharmony_ci { 0x06, 0x95 }, /* Brightness */ 13468c2ecf20Sopenharmony_ci { 0x07, 0x2d }, /* Sharpness */ 13478c2ecf20Sopenharmony_ci { 0x0c, 0x20 }, 13488c2ecf20Sopenharmony_ci { 0x0d, 0x20 }, 13498c2ecf20Sopenharmony_ci { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */ 13508c2ecf20Sopenharmony_ci { 0x0f, 0x05 }, 13518c2ecf20Sopenharmony_ci { 0x10, 0x9a }, 13528c2ecf20Sopenharmony_ci { 0x11, 0x00 }, /* Pixel clock = fastest */ 13538c2ecf20Sopenharmony_ci { 0x12, 0x24 }, /* Enable AGC and AWB */ 13548c2ecf20Sopenharmony_ci { 0x13, 0x21 }, 13558c2ecf20Sopenharmony_ci { 0x14, 0x80 }, 13568c2ecf20Sopenharmony_ci { 0x15, 0x01 }, 13578c2ecf20Sopenharmony_ci { 0x16, 0x03 }, 13588c2ecf20Sopenharmony_ci { 0x17, 0x38 }, 13598c2ecf20Sopenharmony_ci { 0x18, 0xea }, 13608c2ecf20Sopenharmony_ci { 0x19, 0x04 }, 13618c2ecf20Sopenharmony_ci { 0x1a, 0x93 }, 13628c2ecf20Sopenharmony_ci { 0x1b, 0x00 }, 13638c2ecf20Sopenharmony_ci { 0x1e, 0xc4 }, 13648c2ecf20Sopenharmony_ci { 0x1f, 0x04 }, 13658c2ecf20Sopenharmony_ci { 0x20, 0x20 }, 13668c2ecf20Sopenharmony_ci { 0x21, 0x10 }, 13678c2ecf20Sopenharmony_ci { 0x22, 0x88 }, 13688c2ecf20Sopenharmony_ci { 0x23, 0xc0 }, /* Crystal circuit power level */ 13698c2ecf20Sopenharmony_ci { 0x25, 0x9a }, /* Increase AEC black ratio */ 13708c2ecf20Sopenharmony_ci { 0x26, 0xb2 }, /* BLC enable */ 13718c2ecf20Sopenharmony_ci { 0x27, 0xa2 }, 13728c2ecf20Sopenharmony_ci { 0x28, 0x00 }, 13738c2ecf20Sopenharmony_ci { 0x29, 0x00 }, 13748c2ecf20Sopenharmony_ci { 0x2a, 0x84 }, /* 60 Hz power */ 13758c2ecf20Sopenharmony_ci { 0x2b, 0xa8 }, /* 60 Hz power */ 13768c2ecf20Sopenharmony_ci { 0x2c, 0xa0 }, 13778c2ecf20Sopenharmony_ci { 0x2d, 0x95 }, /* Enable auto-brightness */ 13788c2ecf20Sopenharmony_ci { 0x2e, 0x88 }, 13798c2ecf20Sopenharmony_ci { 0x33, 0x26 }, 13808c2ecf20Sopenharmony_ci { 0x34, 0x03 }, 13818c2ecf20Sopenharmony_ci { 0x36, 0x8f }, 13828c2ecf20Sopenharmony_ci { 0x37, 0x80 }, 13838c2ecf20Sopenharmony_ci { 0x38, 0x83 }, 13848c2ecf20Sopenharmony_ci { 0x39, 0x80 }, 13858c2ecf20Sopenharmony_ci { 0x3a, 0x0f }, 13868c2ecf20Sopenharmony_ci { 0x3b, 0x3c }, 13878c2ecf20Sopenharmony_ci { 0x3c, 0x1a }, 13888c2ecf20Sopenharmony_ci { 0x3d, 0x80 }, 13898c2ecf20Sopenharmony_ci { 0x3e, 0x80 }, 13908c2ecf20Sopenharmony_ci { 0x3f, 0x0e }, 13918c2ecf20Sopenharmony_ci { 0x40, 0x00 }, /* White bal */ 13928c2ecf20Sopenharmony_ci { 0x41, 0x00 }, /* White bal */ 13938c2ecf20Sopenharmony_ci { 0x42, 0x80 }, 13948c2ecf20Sopenharmony_ci { 0x43, 0x3f }, /* White bal */ 13958c2ecf20Sopenharmony_ci { 0x44, 0x80 }, 13968c2ecf20Sopenharmony_ci { 0x45, 0x20 }, 13978c2ecf20Sopenharmony_ci { 0x46, 0x20 }, 13988c2ecf20Sopenharmony_ci { 0x47, 0x80 }, 13998c2ecf20Sopenharmony_ci { 0x48, 0x7f }, 14008c2ecf20Sopenharmony_ci { 0x49, 0x00 }, 14018c2ecf20Sopenharmony_ci { 0x4a, 0x00 }, 14028c2ecf20Sopenharmony_ci { 0x4b, 0x80 }, 14038c2ecf20Sopenharmony_ci { 0x4c, 0xd0 }, 14048c2ecf20Sopenharmony_ci { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ 14058c2ecf20Sopenharmony_ci { 0x4e, 0x40 }, 14068c2ecf20Sopenharmony_ci { 0x4f, 0x07 }, /* UV avg., col. killer: max */ 14078c2ecf20Sopenharmony_ci { 0x50, 0xff }, 14088c2ecf20Sopenharmony_ci { 0x54, 0x23 }, /* Max AGC gain: 18dB */ 14098c2ecf20Sopenharmony_ci { 0x55, 0xff }, 14108c2ecf20Sopenharmony_ci { 0x56, 0x12 }, 14118c2ecf20Sopenharmony_ci { 0x57, 0x81 }, 14128c2ecf20Sopenharmony_ci { 0x58, 0x75 }, 14138c2ecf20Sopenharmony_ci { 0x59, 0x01 }, /* AGC dark current comp.: +1 */ 14148c2ecf20Sopenharmony_ci { 0x5a, 0x2c }, 14158c2ecf20Sopenharmony_ci { 0x5b, 0x0f }, /* AWB chrominance levels */ 14168c2ecf20Sopenharmony_ci { 0x5c, 0x10 }, 14178c2ecf20Sopenharmony_ci { 0x3d, 0x80 }, 14188c2ecf20Sopenharmony_ci { 0x27, 0xa6 }, 14198c2ecf20Sopenharmony_ci { 0x12, 0x20 }, /* Toggle AWB */ 14208c2ecf20Sopenharmony_ci { 0x12, 0x24 }, 14218c2ecf20Sopenharmony_ci}; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci/* Lawrence Glaister <lg@jfm.bc.ca> reports: 14248c2ecf20Sopenharmony_ci * 14258c2ecf20Sopenharmony_ci * Register 0x0f in the 7610 has the following effects: 14268c2ecf20Sopenharmony_ci * 14278c2ecf20Sopenharmony_ci * 0x85 (AEC method 1): Best overall, good contrast range 14288c2ecf20Sopenharmony_ci * 0x45 (AEC method 2): Very overexposed 14298c2ecf20Sopenharmony_ci * 0xa5 (spec sheet default): Ok, but the black level is 14308c2ecf20Sopenharmony_ci * shifted resulting in loss of contrast 14318c2ecf20Sopenharmony_ci * 0x05 (old driver setting): very overexposed, too much 14328c2ecf20Sopenharmony_ci * contrast 14338c2ecf20Sopenharmony_ci */ 14348c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_7610[] = { 14358c2ecf20Sopenharmony_ci { 0x10, 0xff }, 14368c2ecf20Sopenharmony_ci { 0x16, 0x06 }, 14378c2ecf20Sopenharmony_ci { 0x28, 0x24 }, 14388c2ecf20Sopenharmony_ci { 0x2b, 0xac }, 14398c2ecf20Sopenharmony_ci { 0x12, 0x00 }, 14408c2ecf20Sopenharmony_ci { 0x38, 0x81 }, 14418c2ecf20Sopenharmony_ci { 0x28, 0x24 }, /* 0c */ 14428c2ecf20Sopenharmony_ci { 0x0f, 0x85 }, /* lg's setting */ 14438c2ecf20Sopenharmony_ci { 0x15, 0x01 }, 14448c2ecf20Sopenharmony_ci { 0x20, 0x1c }, 14458c2ecf20Sopenharmony_ci { 0x23, 0x2a }, 14468c2ecf20Sopenharmony_ci { 0x24, 0x10 }, 14478c2ecf20Sopenharmony_ci { 0x25, 0x8a }, 14488c2ecf20Sopenharmony_ci { 0x26, 0xa2 }, 14498c2ecf20Sopenharmony_ci { 0x27, 0xc2 }, 14508c2ecf20Sopenharmony_ci { 0x2a, 0x04 }, 14518c2ecf20Sopenharmony_ci { 0x2c, 0xfe }, 14528c2ecf20Sopenharmony_ci { 0x2d, 0x93 }, 14538c2ecf20Sopenharmony_ci { 0x30, 0x71 }, 14548c2ecf20Sopenharmony_ci { 0x31, 0x60 }, 14558c2ecf20Sopenharmony_ci { 0x32, 0x26 }, 14568c2ecf20Sopenharmony_ci { 0x33, 0x20 }, 14578c2ecf20Sopenharmony_ci { 0x34, 0x48 }, 14588c2ecf20Sopenharmony_ci { 0x12, 0x24 }, 14598c2ecf20Sopenharmony_ci { 0x11, 0x01 }, 14608c2ecf20Sopenharmony_ci { 0x0c, 0x24 }, 14618c2ecf20Sopenharmony_ci { 0x0d, 0x24 }, 14628c2ecf20Sopenharmony_ci}; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_7620[] = { 14658c2ecf20Sopenharmony_ci { 0x12, 0x80 }, /* reset */ 14668c2ecf20Sopenharmony_ci { 0x00, 0x00 }, /* gain */ 14678c2ecf20Sopenharmony_ci { 0x01, 0x80 }, /* blue gain */ 14688c2ecf20Sopenharmony_ci { 0x02, 0x80 }, /* red gain */ 14698c2ecf20Sopenharmony_ci { 0x03, 0xc0 }, /* OV7670_R03_VREF */ 14708c2ecf20Sopenharmony_ci { 0x06, 0x60 }, 14718c2ecf20Sopenharmony_ci { 0x07, 0x00 }, 14728c2ecf20Sopenharmony_ci { 0x0c, 0x24 }, 14738c2ecf20Sopenharmony_ci { 0x0c, 0x24 }, 14748c2ecf20Sopenharmony_ci { 0x0d, 0x24 }, 14758c2ecf20Sopenharmony_ci { 0x11, 0x01 }, 14768c2ecf20Sopenharmony_ci { 0x12, 0x24 }, 14778c2ecf20Sopenharmony_ci { 0x13, 0x01 }, 14788c2ecf20Sopenharmony_ci { 0x14, 0x84 }, 14798c2ecf20Sopenharmony_ci { 0x15, 0x01 }, 14808c2ecf20Sopenharmony_ci { 0x16, 0x03 }, 14818c2ecf20Sopenharmony_ci { 0x17, 0x2f }, 14828c2ecf20Sopenharmony_ci { 0x18, 0xcf }, 14838c2ecf20Sopenharmony_ci { 0x19, 0x06 }, 14848c2ecf20Sopenharmony_ci { 0x1a, 0xf5 }, 14858c2ecf20Sopenharmony_ci { 0x1b, 0x00 }, 14868c2ecf20Sopenharmony_ci { 0x20, 0x18 }, 14878c2ecf20Sopenharmony_ci { 0x21, 0x80 }, 14888c2ecf20Sopenharmony_ci { 0x22, 0x80 }, 14898c2ecf20Sopenharmony_ci { 0x23, 0x00 }, 14908c2ecf20Sopenharmony_ci { 0x26, 0xa2 }, 14918c2ecf20Sopenharmony_ci { 0x27, 0xea }, 14928c2ecf20Sopenharmony_ci { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */ 14938c2ecf20Sopenharmony_ci { 0x29, 0x00 }, 14948c2ecf20Sopenharmony_ci { 0x2a, 0x10 }, 14958c2ecf20Sopenharmony_ci { 0x2b, 0x00 }, 14968c2ecf20Sopenharmony_ci { 0x2c, 0x88 }, 14978c2ecf20Sopenharmony_ci { 0x2d, 0x91 }, 14988c2ecf20Sopenharmony_ci { 0x2e, 0x80 }, 14998c2ecf20Sopenharmony_ci { 0x2f, 0x44 }, 15008c2ecf20Sopenharmony_ci { 0x60, 0x27 }, 15018c2ecf20Sopenharmony_ci { 0x61, 0x02 }, 15028c2ecf20Sopenharmony_ci { 0x62, 0x5f }, 15038c2ecf20Sopenharmony_ci { 0x63, 0xd5 }, 15048c2ecf20Sopenharmony_ci { 0x64, 0x57 }, 15058c2ecf20Sopenharmony_ci { 0x65, 0x83 }, 15068c2ecf20Sopenharmony_ci { 0x66, 0x55 }, 15078c2ecf20Sopenharmony_ci { 0x67, 0x92 }, 15088c2ecf20Sopenharmony_ci { 0x68, 0xcf }, 15098c2ecf20Sopenharmony_ci { 0x69, 0x76 }, 15108c2ecf20Sopenharmony_ci { 0x6a, 0x22 }, 15118c2ecf20Sopenharmony_ci { 0x6b, 0x00 }, 15128c2ecf20Sopenharmony_ci { 0x6c, 0x02 }, 15138c2ecf20Sopenharmony_ci { 0x6d, 0x44 }, 15148c2ecf20Sopenharmony_ci { 0x6e, 0x80 }, 15158c2ecf20Sopenharmony_ci { 0x6f, 0x1d }, 15168c2ecf20Sopenharmony_ci { 0x70, 0x8b }, 15178c2ecf20Sopenharmony_ci { 0x71, 0x00 }, 15188c2ecf20Sopenharmony_ci { 0x72, 0x14 }, 15198c2ecf20Sopenharmony_ci { 0x73, 0x54 }, 15208c2ecf20Sopenharmony_ci { 0x74, 0x00 }, 15218c2ecf20Sopenharmony_ci { 0x75, 0x8e }, 15228c2ecf20Sopenharmony_ci { 0x76, 0x00 }, 15238c2ecf20Sopenharmony_ci { 0x77, 0xff }, 15248c2ecf20Sopenharmony_ci { 0x78, 0x80 }, 15258c2ecf20Sopenharmony_ci { 0x79, 0x80 }, 15268c2ecf20Sopenharmony_ci { 0x7a, 0x80 }, 15278c2ecf20Sopenharmony_ci { 0x7b, 0xe2 }, 15288c2ecf20Sopenharmony_ci { 0x7c, 0x00 }, 15298c2ecf20Sopenharmony_ci}; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci/* 7640 and 7648. The defaults should be OK for most registers. */ 15328c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_7640[] = { 15338c2ecf20Sopenharmony_ci { 0x12, 0x80 }, 15348c2ecf20Sopenharmony_ci { 0x12, 0x14 }, 15358c2ecf20Sopenharmony_ci}; 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_cistatic const struct ov_regvals init_519_ov7660[] = { 15388c2ecf20Sopenharmony_ci { 0x5d, 0x03 }, /* Turn off suspend mode */ 15398c2ecf20Sopenharmony_ci { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */ 15408c2ecf20Sopenharmony_ci { 0x54, 0x0f }, /* bit2 (jpeg enable) */ 15418c2ecf20Sopenharmony_ci { 0xa2, 0x20 }, /* a2-a5 are undocumented */ 15428c2ecf20Sopenharmony_ci { 0xa3, 0x18 }, 15438c2ecf20Sopenharmony_ci { 0xa4, 0x04 }, 15448c2ecf20Sopenharmony_ci { 0xa5, 0x28 }, 15458c2ecf20Sopenharmony_ci { 0x37, 0x00 }, /* SetUsbInit */ 15468c2ecf20Sopenharmony_ci { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ 15478c2ecf20Sopenharmony_ci /* Enable both fields, YUV Input, disable defect comp (why?) */ 15488c2ecf20Sopenharmony_ci { 0x20, 0x0c }, /* 0x0d does U <-> V swap */ 15498c2ecf20Sopenharmony_ci { 0x21, 0x38 }, 15508c2ecf20Sopenharmony_ci { 0x22, 0x1d }, 15518c2ecf20Sopenharmony_ci { 0x17, 0x50 }, /* undocumented */ 15528c2ecf20Sopenharmony_ci { 0x37, 0x00 }, /* undocumented */ 15538c2ecf20Sopenharmony_ci { 0x40, 0xff }, /* I2C timeout counter */ 15548c2ecf20Sopenharmony_ci { 0x46, 0x00 }, /* I2C clock prescaler */ 15558c2ecf20Sopenharmony_ci}; 15568c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_7660[] = { 15578c2ecf20Sopenharmony_ci {OV7670_R12_COM7, OV7670_COM7_RESET}, 15588c2ecf20Sopenharmony_ci {OV7670_R11_CLKRC, 0x81}, 15598c2ecf20Sopenharmony_ci {0x92, 0x00}, /* DM_LNL */ 15608c2ecf20Sopenharmony_ci {0x93, 0x00}, /* DM_LNH */ 15618c2ecf20Sopenharmony_ci {0x9d, 0x4c}, /* BD50ST */ 15628c2ecf20Sopenharmony_ci {0x9e, 0x3f}, /* BD60ST */ 15638c2ecf20Sopenharmony_ci {OV7670_R3B_COM11, 0x02}, 15648c2ecf20Sopenharmony_ci {OV7670_R13_COM8, 0xf5}, 15658c2ecf20Sopenharmony_ci {OV7670_R10_AECH, 0x00}, 15668c2ecf20Sopenharmony_ci {OV7670_R00_GAIN, 0x00}, 15678c2ecf20Sopenharmony_ci {OV7670_R01_BLUE, 0x7c}, 15688c2ecf20Sopenharmony_ci {OV7670_R02_RED, 0x9d}, 15698c2ecf20Sopenharmony_ci {OV7670_R12_COM7, 0x00}, 15708c2ecf20Sopenharmony_ci {OV7670_R04_COM1, 00}, 15718c2ecf20Sopenharmony_ci {OV7670_R18_HSTOP, 0x01}, 15728c2ecf20Sopenharmony_ci {OV7670_R17_HSTART, 0x13}, 15738c2ecf20Sopenharmony_ci {OV7670_R32_HREF, 0x92}, 15748c2ecf20Sopenharmony_ci {OV7670_R19_VSTART, 0x02}, 15758c2ecf20Sopenharmony_ci {OV7670_R1A_VSTOP, 0x7a}, 15768c2ecf20Sopenharmony_ci {OV7670_R03_VREF, 0x00}, 15778c2ecf20Sopenharmony_ci {OV7670_R0E_COM5, 0x04}, 15788c2ecf20Sopenharmony_ci {OV7670_R0F_COM6, 0x62}, 15798c2ecf20Sopenharmony_ci {OV7670_R15_COM10, 0x00}, 15808c2ecf20Sopenharmony_ci {0x16, 0x02}, /* RSVD */ 15818c2ecf20Sopenharmony_ci {0x1b, 0x00}, /* PSHFT */ 15828c2ecf20Sopenharmony_ci {OV7670_R1E_MVFP, 0x01}, 15838c2ecf20Sopenharmony_ci {0x29, 0x3c}, /* RSVD */ 15848c2ecf20Sopenharmony_ci {0x33, 0x00}, /* CHLF */ 15858c2ecf20Sopenharmony_ci {0x34, 0x07}, /* ARBLM */ 15868c2ecf20Sopenharmony_ci {0x35, 0x84}, /* RSVD */ 15878c2ecf20Sopenharmony_ci {0x36, 0x00}, /* RSVD */ 15888c2ecf20Sopenharmony_ci {0x37, 0x04}, /* ADC */ 15898c2ecf20Sopenharmony_ci {0x39, 0x43}, /* OFON */ 15908c2ecf20Sopenharmony_ci {OV7670_R3A_TSLB, 0x00}, 15918c2ecf20Sopenharmony_ci {OV7670_R3C_COM12, 0x6c}, 15928c2ecf20Sopenharmony_ci {OV7670_R3D_COM13, 0x98}, 15938c2ecf20Sopenharmony_ci {OV7670_R3F_EDGE, 0x23}, 15948c2ecf20Sopenharmony_ci {OV7670_R40_COM15, 0xc1}, 15958c2ecf20Sopenharmony_ci {OV7670_R41_COM16, 0x22}, 15968c2ecf20Sopenharmony_ci {0x6b, 0x0a}, /* DBLV */ 15978c2ecf20Sopenharmony_ci {0xa1, 0x08}, /* RSVD */ 15988c2ecf20Sopenharmony_ci {0x69, 0x80}, /* HV */ 15998c2ecf20Sopenharmony_ci {0x43, 0xf0}, /* RSVD.. */ 16008c2ecf20Sopenharmony_ci {0x44, 0x10}, 16018c2ecf20Sopenharmony_ci {0x45, 0x78}, 16028c2ecf20Sopenharmony_ci {0x46, 0xa8}, 16038c2ecf20Sopenharmony_ci {0x47, 0x60}, 16048c2ecf20Sopenharmony_ci {0x48, 0x80}, 16058c2ecf20Sopenharmony_ci {0x59, 0xba}, 16068c2ecf20Sopenharmony_ci {0x5a, 0x9a}, 16078c2ecf20Sopenharmony_ci {0x5b, 0x22}, 16088c2ecf20Sopenharmony_ci {0x5c, 0xb9}, 16098c2ecf20Sopenharmony_ci {0x5d, 0x9b}, 16108c2ecf20Sopenharmony_ci {0x5e, 0x10}, 16118c2ecf20Sopenharmony_ci {0x5f, 0xe0}, 16128c2ecf20Sopenharmony_ci {0x60, 0x85}, 16138c2ecf20Sopenharmony_ci {0x61, 0x60}, 16148c2ecf20Sopenharmony_ci {0x9f, 0x9d}, /* RSVD */ 16158c2ecf20Sopenharmony_ci {0xa0, 0xa0}, /* DSPC2 */ 16168c2ecf20Sopenharmony_ci {0x4f, 0x60}, /* matrix */ 16178c2ecf20Sopenharmony_ci {0x50, 0x64}, 16188c2ecf20Sopenharmony_ci {0x51, 0x04}, 16198c2ecf20Sopenharmony_ci {0x52, 0x18}, 16208c2ecf20Sopenharmony_ci {0x53, 0x3c}, 16218c2ecf20Sopenharmony_ci {0x54, 0x54}, 16228c2ecf20Sopenharmony_ci {0x55, 0x40}, 16238c2ecf20Sopenharmony_ci {0x56, 0x40}, 16248c2ecf20Sopenharmony_ci {0x57, 0x40}, 16258c2ecf20Sopenharmony_ci {0x58, 0x0d}, /* matrix sign */ 16268c2ecf20Sopenharmony_ci {0x8b, 0xcc}, /* RSVD */ 16278c2ecf20Sopenharmony_ci {0x8c, 0xcc}, 16288c2ecf20Sopenharmony_ci {0x8d, 0xcf}, 16298c2ecf20Sopenharmony_ci {0x6c, 0x40}, /* gamma curve */ 16308c2ecf20Sopenharmony_ci {0x6d, 0xe0}, 16318c2ecf20Sopenharmony_ci {0x6e, 0xa0}, 16328c2ecf20Sopenharmony_ci {0x6f, 0x80}, 16338c2ecf20Sopenharmony_ci {0x70, 0x70}, 16348c2ecf20Sopenharmony_ci {0x71, 0x80}, 16358c2ecf20Sopenharmony_ci {0x72, 0x60}, 16368c2ecf20Sopenharmony_ci {0x73, 0x60}, 16378c2ecf20Sopenharmony_ci {0x74, 0x50}, 16388c2ecf20Sopenharmony_ci {0x75, 0x40}, 16398c2ecf20Sopenharmony_ci {0x76, 0x38}, 16408c2ecf20Sopenharmony_ci {0x77, 0x3c}, 16418c2ecf20Sopenharmony_ci {0x78, 0x32}, 16428c2ecf20Sopenharmony_ci {0x79, 0x1a}, 16438c2ecf20Sopenharmony_ci {0x7a, 0x28}, 16448c2ecf20Sopenharmony_ci {0x7b, 0x24}, 16458c2ecf20Sopenharmony_ci {0x7c, 0x04}, /* gamma curve */ 16468c2ecf20Sopenharmony_ci {0x7d, 0x12}, 16478c2ecf20Sopenharmony_ci {0x7e, 0x26}, 16488c2ecf20Sopenharmony_ci {0x7f, 0x46}, 16498c2ecf20Sopenharmony_ci {0x80, 0x54}, 16508c2ecf20Sopenharmony_ci {0x81, 0x64}, 16518c2ecf20Sopenharmony_ci {0x82, 0x70}, 16528c2ecf20Sopenharmony_ci {0x83, 0x7c}, 16538c2ecf20Sopenharmony_ci {0x84, 0x86}, 16548c2ecf20Sopenharmony_ci {0x85, 0x8e}, 16558c2ecf20Sopenharmony_ci {0x86, 0x9c}, 16568c2ecf20Sopenharmony_ci {0x87, 0xab}, 16578c2ecf20Sopenharmony_ci {0x88, 0xc4}, 16588c2ecf20Sopenharmony_ci {0x89, 0xd1}, 16598c2ecf20Sopenharmony_ci {0x8a, 0xe5}, 16608c2ecf20Sopenharmony_ci {OV7670_R14_COM9, 0x1e}, 16618c2ecf20Sopenharmony_ci {OV7670_R24_AEW, 0x80}, 16628c2ecf20Sopenharmony_ci {OV7670_R25_AEB, 0x72}, 16638c2ecf20Sopenharmony_ci {OV7670_R26_VPT, 0xb3}, 16648c2ecf20Sopenharmony_ci {0x62, 0x80}, /* LCC1 */ 16658c2ecf20Sopenharmony_ci {0x63, 0x80}, /* LCC2 */ 16668c2ecf20Sopenharmony_ci {0x64, 0x06}, /* LCC3 */ 16678c2ecf20Sopenharmony_ci {0x65, 0x00}, /* LCC4 */ 16688c2ecf20Sopenharmony_ci {0x66, 0x01}, /* LCC5 */ 16698c2ecf20Sopenharmony_ci {0x94, 0x0e}, /* RSVD.. */ 16708c2ecf20Sopenharmony_ci {0x95, 0x14}, 16718c2ecf20Sopenharmony_ci {OV7670_R13_COM8, OV7670_COM8_FASTAEC 16728c2ecf20Sopenharmony_ci | OV7670_COM8_AECSTEP 16738c2ecf20Sopenharmony_ci | OV7670_COM8_BFILT 16748c2ecf20Sopenharmony_ci | 0x10 16758c2ecf20Sopenharmony_ci | OV7670_COM8_AGC 16768c2ecf20Sopenharmony_ci | OV7670_COM8_AWB 16778c2ecf20Sopenharmony_ci | OV7670_COM8_AEC}, 16788c2ecf20Sopenharmony_ci {0xa1, 0xc8} 16798c2ecf20Sopenharmony_ci}; 16808c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_9600[] = { 16818c2ecf20Sopenharmony_ci {0x12, 0x80}, 16828c2ecf20Sopenharmony_ci {0x0c, 0x28}, 16838c2ecf20Sopenharmony_ci {0x11, 0x80}, 16848c2ecf20Sopenharmony_ci {0x13, 0xb5}, 16858c2ecf20Sopenharmony_ci {0x14, 0x3e}, 16868c2ecf20Sopenharmony_ci {0x1b, 0x04}, 16878c2ecf20Sopenharmony_ci {0x24, 0xb0}, 16888c2ecf20Sopenharmony_ci {0x25, 0x90}, 16898c2ecf20Sopenharmony_ci {0x26, 0x94}, 16908c2ecf20Sopenharmony_ci {0x35, 0x90}, 16918c2ecf20Sopenharmony_ci {0x37, 0x07}, 16928c2ecf20Sopenharmony_ci {0x38, 0x08}, 16938c2ecf20Sopenharmony_ci {0x01, 0x8e}, 16948c2ecf20Sopenharmony_ci {0x02, 0x85} 16958c2ecf20Sopenharmony_ci}; 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci/* 7670. Defaults taken from OmniVision provided data, 16988c2ecf20Sopenharmony_ci* as provided by Jonathan Corbet of OLPC */ 16998c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_7670[] = { 17008c2ecf20Sopenharmony_ci { OV7670_R12_COM7, OV7670_COM7_RESET }, 17018c2ecf20Sopenharmony_ci { OV7670_R3A_TSLB, 0x04 }, /* OV */ 17028c2ecf20Sopenharmony_ci { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ 17038c2ecf20Sopenharmony_ci { OV7670_R11_CLKRC, 0x01 }, 17048c2ecf20Sopenharmony_ci/* 17058c2ecf20Sopenharmony_ci * Set the hardware window. These values from OV don't entirely 17068c2ecf20Sopenharmony_ci * make sense - hstop is less than hstart. But they work... 17078c2ecf20Sopenharmony_ci */ 17088c2ecf20Sopenharmony_ci { OV7670_R17_HSTART, 0x13 }, 17098c2ecf20Sopenharmony_ci { OV7670_R18_HSTOP, 0x01 }, 17108c2ecf20Sopenharmony_ci { OV7670_R32_HREF, 0xb6 }, 17118c2ecf20Sopenharmony_ci { OV7670_R19_VSTART, 0x02 }, 17128c2ecf20Sopenharmony_ci { OV7670_R1A_VSTOP, 0x7a }, 17138c2ecf20Sopenharmony_ci { OV7670_R03_VREF, 0x0a }, 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci { OV7670_R0C_COM3, 0x00 }, 17168c2ecf20Sopenharmony_ci { OV7670_R3E_COM14, 0x00 }, 17178c2ecf20Sopenharmony_ci/* Mystery scaling numbers */ 17188c2ecf20Sopenharmony_ci { 0x70, 0x3a }, 17198c2ecf20Sopenharmony_ci { 0x71, 0x35 }, 17208c2ecf20Sopenharmony_ci { 0x72, 0x11 }, 17218c2ecf20Sopenharmony_ci { 0x73, 0xf0 }, 17228c2ecf20Sopenharmony_ci { 0xa2, 0x02 }, 17238c2ecf20Sopenharmony_ci/* { OV7670_R15_COM10, 0x0 }, */ 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci/* Gamma curve values */ 17268c2ecf20Sopenharmony_ci { 0x7a, 0x20 }, 17278c2ecf20Sopenharmony_ci { 0x7b, 0x10 }, 17288c2ecf20Sopenharmony_ci { 0x7c, 0x1e }, 17298c2ecf20Sopenharmony_ci { 0x7d, 0x35 }, 17308c2ecf20Sopenharmony_ci { 0x7e, 0x5a }, 17318c2ecf20Sopenharmony_ci { 0x7f, 0x69 }, 17328c2ecf20Sopenharmony_ci { 0x80, 0x76 }, 17338c2ecf20Sopenharmony_ci { 0x81, 0x80 }, 17348c2ecf20Sopenharmony_ci { 0x82, 0x88 }, 17358c2ecf20Sopenharmony_ci { 0x83, 0x8f }, 17368c2ecf20Sopenharmony_ci { 0x84, 0x96 }, 17378c2ecf20Sopenharmony_ci { 0x85, 0xa3 }, 17388c2ecf20Sopenharmony_ci { 0x86, 0xaf }, 17398c2ecf20Sopenharmony_ci { 0x87, 0xc4 }, 17408c2ecf20Sopenharmony_ci { 0x88, 0xd7 }, 17418c2ecf20Sopenharmony_ci { 0x89, 0xe8 }, 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci/* AGC and AEC parameters. Note we start by disabling those features, 17448c2ecf20Sopenharmony_ci then turn them only after tweaking the values. */ 17458c2ecf20Sopenharmony_ci { OV7670_R13_COM8, OV7670_COM8_FASTAEC 17468c2ecf20Sopenharmony_ci | OV7670_COM8_AECSTEP 17478c2ecf20Sopenharmony_ci | OV7670_COM8_BFILT }, 17488c2ecf20Sopenharmony_ci { OV7670_R00_GAIN, 0x00 }, 17498c2ecf20Sopenharmony_ci { OV7670_R10_AECH, 0x00 }, 17508c2ecf20Sopenharmony_ci { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */ 17518c2ecf20Sopenharmony_ci { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ 17528c2ecf20Sopenharmony_ci { OV7670_RA5_BD50MAX, 0x05 }, 17538c2ecf20Sopenharmony_ci { OV7670_RAB_BD60MAX, 0x07 }, 17548c2ecf20Sopenharmony_ci { OV7670_R24_AEW, 0x95 }, 17558c2ecf20Sopenharmony_ci { OV7670_R25_AEB, 0x33 }, 17568c2ecf20Sopenharmony_ci { OV7670_R26_VPT, 0xe3 }, 17578c2ecf20Sopenharmony_ci { OV7670_R9F_HAECC1, 0x78 }, 17588c2ecf20Sopenharmony_ci { OV7670_RA0_HAECC2, 0x68 }, 17598c2ecf20Sopenharmony_ci { 0xa1, 0x03 }, /* magic */ 17608c2ecf20Sopenharmony_ci { OV7670_RA6_HAECC3, 0xd8 }, 17618c2ecf20Sopenharmony_ci { OV7670_RA7_HAECC4, 0xd8 }, 17628c2ecf20Sopenharmony_ci { OV7670_RA8_HAECC5, 0xf0 }, 17638c2ecf20Sopenharmony_ci { OV7670_RA9_HAECC6, 0x90 }, 17648c2ecf20Sopenharmony_ci { OV7670_RAA_HAECC7, 0x94 }, 17658c2ecf20Sopenharmony_ci { OV7670_R13_COM8, OV7670_COM8_FASTAEC 17668c2ecf20Sopenharmony_ci | OV7670_COM8_AECSTEP 17678c2ecf20Sopenharmony_ci | OV7670_COM8_BFILT 17688c2ecf20Sopenharmony_ci | OV7670_COM8_AGC 17698c2ecf20Sopenharmony_ci | OV7670_COM8_AEC }, 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci/* Almost all of these are magic "reserved" values. */ 17728c2ecf20Sopenharmony_ci { OV7670_R0E_COM5, 0x61 }, 17738c2ecf20Sopenharmony_ci { OV7670_R0F_COM6, 0x4b }, 17748c2ecf20Sopenharmony_ci { 0x16, 0x02 }, 17758c2ecf20Sopenharmony_ci { OV7670_R1E_MVFP, 0x07 }, 17768c2ecf20Sopenharmony_ci { 0x21, 0x02 }, 17778c2ecf20Sopenharmony_ci { 0x22, 0x91 }, 17788c2ecf20Sopenharmony_ci { 0x29, 0x07 }, 17798c2ecf20Sopenharmony_ci { 0x33, 0x0b }, 17808c2ecf20Sopenharmony_ci { 0x35, 0x0b }, 17818c2ecf20Sopenharmony_ci { 0x37, 0x1d }, 17828c2ecf20Sopenharmony_ci { 0x38, 0x71 }, 17838c2ecf20Sopenharmony_ci { 0x39, 0x2a }, 17848c2ecf20Sopenharmony_ci { OV7670_R3C_COM12, 0x78 }, 17858c2ecf20Sopenharmony_ci { 0x4d, 0x40 }, 17868c2ecf20Sopenharmony_ci { 0x4e, 0x20 }, 17878c2ecf20Sopenharmony_ci { OV7670_R69_GFIX, 0x00 }, 17888c2ecf20Sopenharmony_ci { 0x6b, 0x4a }, 17898c2ecf20Sopenharmony_ci { 0x74, 0x10 }, 17908c2ecf20Sopenharmony_ci { 0x8d, 0x4f }, 17918c2ecf20Sopenharmony_ci { 0x8e, 0x00 }, 17928c2ecf20Sopenharmony_ci { 0x8f, 0x00 }, 17938c2ecf20Sopenharmony_ci { 0x90, 0x00 }, 17948c2ecf20Sopenharmony_ci { 0x91, 0x00 }, 17958c2ecf20Sopenharmony_ci { 0x96, 0x00 }, 17968c2ecf20Sopenharmony_ci { 0x9a, 0x00 }, 17978c2ecf20Sopenharmony_ci { 0xb0, 0x84 }, 17988c2ecf20Sopenharmony_ci { 0xb1, 0x0c }, 17998c2ecf20Sopenharmony_ci { 0xb2, 0x0e }, 18008c2ecf20Sopenharmony_ci { 0xb3, 0x82 }, 18018c2ecf20Sopenharmony_ci { 0xb8, 0x0a }, 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci/* More reserved magic, some of which tweaks white balance */ 18048c2ecf20Sopenharmony_ci { 0x43, 0x0a }, 18058c2ecf20Sopenharmony_ci { 0x44, 0xf0 }, 18068c2ecf20Sopenharmony_ci { 0x45, 0x34 }, 18078c2ecf20Sopenharmony_ci { 0x46, 0x58 }, 18088c2ecf20Sopenharmony_ci { 0x47, 0x28 }, 18098c2ecf20Sopenharmony_ci { 0x48, 0x3a }, 18108c2ecf20Sopenharmony_ci { 0x59, 0x88 }, 18118c2ecf20Sopenharmony_ci { 0x5a, 0x88 }, 18128c2ecf20Sopenharmony_ci { 0x5b, 0x44 }, 18138c2ecf20Sopenharmony_ci { 0x5c, 0x67 }, 18148c2ecf20Sopenharmony_ci { 0x5d, 0x49 }, 18158c2ecf20Sopenharmony_ci { 0x5e, 0x0e }, 18168c2ecf20Sopenharmony_ci { 0x6c, 0x0a }, 18178c2ecf20Sopenharmony_ci { 0x6d, 0x55 }, 18188c2ecf20Sopenharmony_ci { 0x6e, 0x11 }, 18198c2ecf20Sopenharmony_ci { 0x6f, 0x9f }, /* "9e for advance AWB" */ 18208c2ecf20Sopenharmony_ci { 0x6a, 0x40 }, 18218c2ecf20Sopenharmony_ci { OV7670_R01_BLUE, 0x40 }, 18228c2ecf20Sopenharmony_ci { OV7670_R02_RED, 0x60 }, 18238c2ecf20Sopenharmony_ci { OV7670_R13_COM8, OV7670_COM8_FASTAEC 18248c2ecf20Sopenharmony_ci | OV7670_COM8_AECSTEP 18258c2ecf20Sopenharmony_ci | OV7670_COM8_BFILT 18268c2ecf20Sopenharmony_ci | OV7670_COM8_AGC 18278c2ecf20Sopenharmony_ci | OV7670_COM8_AEC 18288c2ecf20Sopenharmony_ci | OV7670_COM8_AWB }, 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci/* Matrix coefficients */ 18318c2ecf20Sopenharmony_ci { 0x4f, 0x80 }, 18328c2ecf20Sopenharmony_ci { 0x50, 0x80 }, 18338c2ecf20Sopenharmony_ci { 0x51, 0x00 }, 18348c2ecf20Sopenharmony_ci { 0x52, 0x22 }, 18358c2ecf20Sopenharmony_ci { 0x53, 0x5e }, 18368c2ecf20Sopenharmony_ci { 0x54, 0x80 }, 18378c2ecf20Sopenharmony_ci { 0x58, 0x9e }, 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci { OV7670_R41_COM16, OV7670_COM16_AWBGAIN }, 18408c2ecf20Sopenharmony_ci { OV7670_R3F_EDGE, 0x00 }, 18418c2ecf20Sopenharmony_ci { 0x75, 0x05 }, 18428c2ecf20Sopenharmony_ci { 0x76, 0xe1 }, 18438c2ecf20Sopenharmony_ci { 0x4c, 0x00 }, 18448c2ecf20Sopenharmony_ci { 0x77, 0x01 }, 18458c2ecf20Sopenharmony_ci { OV7670_R3D_COM13, OV7670_COM13_GAMMA 18468c2ecf20Sopenharmony_ci | OV7670_COM13_UVSAT 18478c2ecf20Sopenharmony_ci | 2}, /* was 3 */ 18488c2ecf20Sopenharmony_ci { 0x4b, 0x09 }, 18498c2ecf20Sopenharmony_ci { 0xc9, 0x60 }, 18508c2ecf20Sopenharmony_ci { OV7670_R41_COM16, 0x38 }, 18518c2ecf20Sopenharmony_ci { 0x56, 0x40 }, 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci { 0x34, 0x11 }, 18548c2ecf20Sopenharmony_ci { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, 18558c2ecf20Sopenharmony_ci { 0xa4, 0x88 }, 18568c2ecf20Sopenharmony_ci { 0x96, 0x00 }, 18578c2ecf20Sopenharmony_ci { 0x97, 0x30 }, 18588c2ecf20Sopenharmony_ci { 0x98, 0x20 }, 18598c2ecf20Sopenharmony_ci { 0x99, 0x30 }, 18608c2ecf20Sopenharmony_ci { 0x9a, 0x84 }, 18618c2ecf20Sopenharmony_ci { 0x9b, 0x29 }, 18628c2ecf20Sopenharmony_ci { 0x9c, 0x03 }, 18638c2ecf20Sopenharmony_ci { 0x9d, 0x4c }, 18648c2ecf20Sopenharmony_ci { 0x9e, 0x3f }, 18658c2ecf20Sopenharmony_ci { 0x78, 0x04 }, 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci/* Extra-weird stuff. Some sort of multiplexor register */ 18688c2ecf20Sopenharmony_ci { 0x79, 0x01 }, 18698c2ecf20Sopenharmony_ci { 0xc8, 0xf0 }, 18708c2ecf20Sopenharmony_ci { 0x79, 0x0f }, 18718c2ecf20Sopenharmony_ci { 0xc8, 0x00 }, 18728c2ecf20Sopenharmony_ci { 0x79, 0x10 }, 18738c2ecf20Sopenharmony_ci { 0xc8, 0x7e }, 18748c2ecf20Sopenharmony_ci { 0x79, 0x0a }, 18758c2ecf20Sopenharmony_ci { 0xc8, 0x80 }, 18768c2ecf20Sopenharmony_ci { 0x79, 0x0b }, 18778c2ecf20Sopenharmony_ci { 0xc8, 0x01 }, 18788c2ecf20Sopenharmony_ci { 0x79, 0x0c }, 18798c2ecf20Sopenharmony_ci { 0xc8, 0x0f }, 18808c2ecf20Sopenharmony_ci { 0x79, 0x0d }, 18818c2ecf20Sopenharmony_ci { 0xc8, 0x20 }, 18828c2ecf20Sopenharmony_ci { 0x79, 0x09 }, 18838c2ecf20Sopenharmony_ci { 0xc8, 0x80 }, 18848c2ecf20Sopenharmony_ci { 0x79, 0x02 }, 18858c2ecf20Sopenharmony_ci { 0xc8, 0xc0 }, 18868c2ecf20Sopenharmony_ci { 0x79, 0x03 }, 18878c2ecf20Sopenharmony_ci { 0xc8, 0x40 }, 18888c2ecf20Sopenharmony_ci { 0x79, 0x05 }, 18898c2ecf20Sopenharmony_ci { 0xc8, 0x30 }, 18908c2ecf20Sopenharmony_ci { 0x79, 0x26 }, 18918c2ecf20Sopenharmony_ci}; 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_cistatic const struct ov_i2c_regvals norm_8610[] = { 18948c2ecf20Sopenharmony_ci { 0x12, 0x80 }, 18958c2ecf20Sopenharmony_ci { 0x00, 0x00 }, 18968c2ecf20Sopenharmony_ci { 0x01, 0x80 }, 18978c2ecf20Sopenharmony_ci { 0x02, 0x80 }, 18988c2ecf20Sopenharmony_ci { 0x03, 0xc0 }, 18998c2ecf20Sopenharmony_ci { 0x04, 0x30 }, 19008c2ecf20Sopenharmony_ci { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */ 19018c2ecf20Sopenharmony_ci { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */ 19028c2ecf20Sopenharmony_ci { 0x0a, 0x86 }, 19038c2ecf20Sopenharmony_ci { 0x0b, 0xb0 }, 19048c2ecf20Sopenharmony_ci { 0x0c, 0x20 }, 19058c2ecf20Sopenharmony_ci { 0x0d, 0x20 }, 19068c2ecf20Sopenharmony_ci { 0x11, 0x01 }, 19078c2ecf20Sopenharmony_ci { 0x12, 0x25 }, 19088c2ecf20Sopenharmony_ci { 0x13, 0x01 }, 19098c2ecf20Sopenharmony_ci { 0x14, 0x04 }, 19108c2ecf20Sopenharmony_ci { 0x15, 0x01 }, /* Lin and Win think different about UV order */ 19118c2ecf20Sopenharmony_ci { 0x16, 0x03 }, 19128c2ecf20Sopenharmony_ci { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */ 19138c2ecf20Sopenharmony_ci { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */ 19148c2ecf20Sopenharmony_ci { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */ 19158c2ecf20Sopenharmony_ci { 0x1a, 0xf5 }, 19168c2ecf20Sopenharmony_ci { 0x1b, 0x00 }, 19178c2ecf20Sopenharmony_ci { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */ 19188c2ecf20Sopenharmony_ci { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */ 19198c2ecf20Sopenharmony_ci { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */ 19208c2ecf20Sopenharmony_ci { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */ 19218c2ecf20Sopenharmony_ci { 0x26, 0xa2 }, 19228c2ecf20Sopenharmony_ci { 0x27, 0xea }, 19238c2ecf20Sopenharmony_ci { 0x28, 0x00 }, 19248c2ecf20Sopenharmony_ci { 0x29, 0x00 }, 19258c2ecf20Sopenharmony_ci { 0x2a, 0x80 }, 19268c2ecf20Sopenharmony_ci { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */ 19278c2ecf20Sopenharmony_ci { 0x2c, 0xac }, 19288c2ecf20Sopenharmony_ci { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */ 19298c2ecf20Sopenharmony_ci { 0x2e, 0x80 }, 19308c2ecf20Sopenharmony_ci { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */ 19318c2ecf20Sopenharmony_ci { 0x4c, 0x00 }, 19328c2ecf20Sopenharmony_ci { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */ 19338c2ecf20Sopenharmony_ci { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */ 19348c2ecf20Sopenharmony_ci { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */ 19358c2ecf20Sopenharmony_ci { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */ 19368c2ecf20Sopenharmony_ci { 0x63, 0xff }, 19378c2ecf20Sopenharmony_ci { 0x64, 0x53 }, /* new windrv 090403 says 0x57, 19388c2ecf20Sopenharmony_ci * maybe that's wrong */ 19398c2ecf20Sopenharmony_ci { 0x65, 0x00 }, 19408c2ecf20Sopenharmony_ci { 0x66, 0x55 }, 19418c2ecf20Sopenharmony_ci { 0x67, 0xb0 }, 19428c2ecf20Sopenharmony_ci { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */ 19438c2ecf20Sopenharmony_ci { 0x69, 0x02 }, 19448c2ecf20Sopenharmony_ci { 0x6a, 0x22 }, 19458c2ecf20Sopenharmony_ci { 0x6b, 0x00 }, 19468c2ecf20Sopenharmony_ci { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but 19478c2ecf20Sopenharmony_ci * deleting bit7 colors the first images red */ 19488c2ecf20Sopenharmony_ci { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */ 19498c2ecf20Sopenharmony_ci { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */ 19508c2ecf20Sopenharmony_ci { 0x6f, 0x01 }, 19518c2ecf20Sopenharmony_ci { 0x70, 0x8b }, 19528c2ecf20Sopenharmony_ci { 0x71, 0x00 }, 19538c2ecf20Sopenharmony_ci { 0x72, 0x14 }, 19548c2ecf20Sopenharmony_ci { 0x73, 0x54 }, 19558c2ecf20Sopenharmony_ci { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */ 19568c2ecf20Sopenharmony_ci { 0x75, 0x0e }, 19578c2ecf20Sopenharmony_ci { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */ 19588c2ecf20Sopenharmony_ci { 0x77, 0xff }, 19598c2ecf20Sopenharmony_ci { 0x78, 0x80 }, 19608c2ecf20Sopenharmony_ci { 0x79, 0x80 }, 19618c2ecf20Sopenharmony_ci { 0x7a, 0x80 }, 19628c2ecf20Sopenharmony_ci { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */ 19638c2ecf20Sopenharmony_ci { 0x7c, 0x00 }, 19648c2ecf20Sopenharmony_ci { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */ 19658c2ecf20Sopenharmony_ci { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */ 19668c2ecf20Sopenharmony_ci { 0x7f, 0xfb }, 19678c2ecf20Sopenharmony_ci { 0x80, 0x28 }, 19688c2ecf20Sopenharmony_ci { 0x81, 0x00 }, 19698c2ecf20Sopenharmony_ci { 0x82, 0x23 }, 19708c2ecf20Sopenharmony_ci { 0x83, 0x0b }, 19718c2ecf20Sopenharmony_ci { 0x84, 0x00 }, 19728c2ecf20Sopenharmony_ci { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */ 19738c2ecf20Sopenharmony_ci { 0x86, 0xc9 }, 19748c2ecf20Sopenharmony_ci { 0x87, 0x00 }, 19758c2ecf20Sopenharmony_ci { 0x88, 0x00 }, 19768c2ecf20Sopenharmony_ci { 0x89, 0x01 }, 19778c2ecf20Sopenharmony_ci { 0x12, 0x20 }, 19788c2ecf20Sopenharmony_ci { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */ 19798c2ecf20Sopenharmony_ci}; 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_cistatic unsigned char ov7670_abs_to_sm(unsigned char v) 19828c2ecf20Sopenharmony_ci{ 19838c2ecf20Sopenharmony_ci if (v > 127) 19848c2ecf20Sopenharmony_ci return v & 0x7f; 19858c2ecf20Sopenharmony_ci return (128 - v) | 0x80; 19868c2ecf20Sopenharmony_ci} 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci/* Write a OV519 register */ 19898c2ecf20Sopenharmony_cistatic void reg_w(struct sd *sd, u16 index, u16 value) 19908c2ecf20Sopenharmony_ci{ 19918c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 19928c2ecf20Sopenharmony_ci int ret, req = 0; 19938c2ecf20Sopenharmony_ci 19948c2ecf20Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 19958c2ecf20Sopenharmony_ci return; 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 19988c2ecf20Sopenharmony_ci udelay(150); 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci switch (sd->bridge) { 20018c2ecf20Sopenharmony_ci case BRIDGE_OV511: 20028c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 20038c2ecf20Sopenharmony_ci req = 2; 20048c2ecf20Sopenharmony_ci break; 20058c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 20068c2ecf20Sopenharmony_ci req = 0x0a; 20078c2ecf20Sopenharmony_ci fallthrough; 20088c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 20098c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "SET %02x %04x %04x\n", 20108c2ecf20Sopenharmony_ci req, value, index); 20118c2ecf20Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 20128c2ecf20Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 20138c2ecf20Sopenharmony_ci req, 20148c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 20158c2ecf20Sopenharmony_ci value, index, NULL, 0, 500); 20168c2ecf20Sopenharmony_ci goto leave; 20178c2ecf20Sopenharmony_ci default: 20188c2ecf20Sopenharmony_ci req = 1; 20198c2ecf20Sopenharmony_ci } 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "SET %02x 0000 %04x %02x\n", 20228c2ecf20Sopenharmony_ci req, index, value); 20238c2ecf20Sopenharmony_ci sd->gspca_dev.usb_buf[0] = value; 20248c2ecf20Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 20258c2ecf20Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 20268c2ecf20Sopenharmony_ci req, 20278c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 20288c2ecf20Sopenharmony_ci 0, index, 20298c2ecf20Sopenharmony_ci sd->gspca_dev.usb_buf, 1, 500); 20308c2ecf20Sopenharmony_cileave: 20318c2ecf20Sopenharmony_ci if (ret < 0) { 20328c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_w %02x failed %d\n", index, ret); 20338c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = ret; 20348c2ecf20Sopenharmony_ci return; 20358c2ecf20Sopenharmony_ci } 20368c2ecf20Sopenharmony_ci} 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci/* Read from a OV519 register, note not valid for the w9968cf!! */ 20398c2ecf20Sopenharmony_ci/* returns: negative is error, pos or zero is data */ 20408c2ecf20Sopenharmony_cistatic int reg_r(struct sd *sd, u16 index) 20418c2ecf20Sopenharmony_ci{ 20428c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 20438c2ecf20Sopenharmony_ci int ret; 20448c2ecf20Sopenharmony_ci int req; 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 20478c2ecf20Sopenharmony_ci return -1; 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci switch (sd->bridge) { 20508c2ecf20Sopenharmony_ci case BRIDGE_OV511: 20518c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 20528c2ecf20Sopenharmony_ci req = 3; 20538c2ecf20Sopenharmony_ci break; 20548c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 20558c2ecf20Sopenharmony_ci req = 0x0b; 20568c2ecf20Sopenharmony_ci break; 20578c2ecf20Sopenharmony_ci default: 20588c2ecf20Sopenharmony_ci req = 1; 20598c2ecf20Sopenharmony_ci } 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 20628c2ecf20Sopenharmony_ci udelay(150); 20638c2ecf20Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 20648c2ecf20Sopenharmony_ci usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 20658c2ecf20Sopenharmony_ci req, 20668c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 20678c2ecf20Sopenharmony_ci 0, index, sd->gspca_dev.usb_buf, 1, 500); 20688c2ecf20Sopenharmony_ci 20698c2ecf20Sopenharmony_ci if (ret >= 0) { 20708c2ecf20Sopenharmony_ci ret = sd->gspca_dev.usb_buf[0]; 20718c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "GET %02x 0000 %04x %02x\n", 20728c2ecf20Sopenharmony_ci req, index, ret); 20738c2ecf20Sopenharmony_ci } else { 20748c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_r %02x failed %d\n", index, ret); 20758c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = ret; 20768c2ecf20Sopenharmony_ci /* 20778c2ecf20Sopenharmony_ci * Make sure the result is zeroed to avoid uninitialized 20788c2ecf20Sopenharmony_ci * values. 20798c2ecf20Sopenharmony_ci */ 20808c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0] = 0; 20818c2ecf20Sopenharmony_ci } 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci return ret; 20848c2ecf20Sopenharmony_ci} 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci/* Read 8 values from a OV519 register */ 20878c2ecf20Sopenharmony_cistatic int reg_r8(struct sd *sd, 20888c2ecf20Sopenharmony_ci u16 index) 20898c2ecf20Sopenharmony_ci{ 20908c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 20918c2ecf20Sopenharmony_ci int ret; 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 20948c2ecf20Sopenharmony_ci return -1; 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 20978c2ecf20Sopenharmony_ci udelay(150); 20988c2ecf20Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 20998c2ecf20Sopenharmony_ci usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 21008c2ecf20Sopenharmony_ci 1, /* REQ_IO */ 21018c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 21028c2ecf20Sopenharmony_ci 0, index, sd->gspca_dev.usb_buf, 8, 500); 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci if (ret >= 0) { 21058c2ecf20Sopenharmony_ci ret = sd->gspca_dev.usb_buf[0]; 21068c2ecf20Sopenharmony_ci } else { 21078c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_r8 %02x failed %d\n", index, ret); 21088c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = ret; 21098c2ecf20Sopenharmony_ci /* 21108c2ecf20Sopenharmony_ci * Make sure the buffer is zeroed to avoid uninitialized 21118c2ecf20Sopenharmony_ci * values. 21128c2ecf20Sopenharmony_ci */ 21138c2ecf20Sopenharmony_ci memset(gspca_dev->usb_buf, 0, 8); 21148c2ecf20Sopenharmony_ci } 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ci return ret; 21178c2ecf20Sopenharmony_ci} 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci/* 21208c2ecf20Sopenharmony_ci * Writes bits at positions specified by mask to an OV51x reg. Bits that are in 21218c2ecf20Sopenharmony_ci * the same position as 1's in "mask" are cleared and set to "value". Bits 21228c2ecf20Sopenharmony_ci * that are in the same position as 0's in "mask" are preserved, regardless 21238c2ecf20Sopenharmony_ci * of their respective state in "value". 21248c2ecf20Sopenharmony_ci */ 21258c2ecf20Sopenharmony_cistatic void reg_w_mask(struct sd *sd, 21268c2ecf20Sopenharmony_ci u16 index, 21278c2ecf20Sopenharmony_ci u8 value, 21288c2ecf20Sopenharmony_ci u8 mask) 21298c2ecf20Sopenharmony_ci{ 21308c2ecf20Sopenharmony_ci int ret; 21318c2ecf20Sopenharmony_ci u8 oldval; 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci if (mask != 0xff) { 21348c2ecf20Sopenharmony_ci value &= mask; /* Enforce mask on value */ 21358c2ecf20Sopenharmony_ci ret = reg_r(sd, index); 21368c2ecf20Sopenharmony_ci if (ret < 0) 21378c2ecf20Sopenharmony_ci return; 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci oldval = ret & ~mask; /* Clear the masked bits */ 21408c2ecf20Sopenharmony_ci value |= oldval; /* Set the desired bits */ 21418c2ecf20Sopenharmony_ci } 21428c2ecf20Sopenharmony_ci reg_w(sd, index, value); 21438c2ecf20Sopenharmony_ci} 21448c2ecf20Sopenharmony_ci 21458c2ecf20Sopenharmony_ci/* 21468c2ecf20Sopenharmony_ci * Writes multiple (n) byte value to a single register. Only valid with certain 21478c2ecf20Sopenharmony_ci * registers (0x30 and 0xc4 - 0xce). 21488c2ecf20Sopenharmony_ci */ 21498c2ecf20Sopenharmony_cistatic void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) 21508c2ecf20Sopenharmony_ci{ 21518c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 21528c2ecf20Sopenharmony_ci int ret; 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 21558c2ecf20Sopenharmony_ci return; 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 21608c2ecf20Sopenharmony_ci udelay(150); 21618c2ecf20Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 21628c2ecf20Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 21638c2ecf20Sopenharmony_ci 1 /* REG_IO */, 21648c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 21658c2ecf20Sopenharmony_ci 0, index, 21668c2ecf20Sopenharmony_ci sd->gspca_dev.usb_buf, n, 500); 21678c2ecf20Sopenharmony_ci if (ret < 0) { 21688c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_w32 %02x failed %d\n", index, ret); 21698c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = ret; 21708c2ecf20Sopenharmony_ci } 21718c2ecf20Sopenharmony_ci} 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_cistatic void ov511_i2c_w(struct sd *sd, u8 reg, u8 value) 21748c2ecf20Sopenharmony_ci{ 21758c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 21768c2ecf20Sopenharmony_ci int rc, retries; 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "ov511_i2c_w %02x %02x\n", reg, value); 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci /* Three byte write cycle */ 21818c2ecf20Sopenharmony_ci for (retries = 6; ; ) { 21828c2ecf20Sopenharmony_ci /* Select camera register */ 21838c2ecf20Sopenharmony_ci reg_w(sd, R51x_I2C_SADDR_3, reg); 21848c2ecf20Sopenharmony_ci 21858c2ecf20Sopenharmony_ci /* Write "value" to I2C data port of OV511 */ 21868c2ecf20Sopenharmony_ci reg_w(sd, R51x_I2C_DATA, value); 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_ci /* Initiate 3-byte write cycle */ 21898c2ecf20Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x01); 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci do { 21928c2ecf20Sopenharmony_ci rc = reg_r(sd, R511_I2C_CTL); 21938c2ecf20Sopenharmony_ci } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci if (rc < 0) 21968c2ecf20Sopenharmony_ci return; 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci if ((rc & 2) == 0) /* Ack? */ 21998c2ecf20Sopenharmony_ci break; 22008c2ecf20Sopenharmony_ci if (--retries < 0) { 22018c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "i2c write retries exhausted\n"); 22028c2ecf20Sopenharmony_ci return; 22038c2ecf20Sopenharmony_ci } 22048c2ecf20Sopenharmony_ci } 22058c2ecf20Sopenharmony_ci} 22068c2ecf20Sopenharmony_ci 22078c2ecf20Sopenharmony_cistatic int ov511_i2c_r(struct sd *sd, u8 reg) 22088c2ecf20Sopenharmony_ci{ 22098c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 22108c2ecf20Sopenharmony_ci int rc, value, retries; 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_ci /* Two byte write cycle */ 22138c2ecf20Sopenharmony_ci for (retries = 6; ; ) { 22148c2ecf20Sopenharmony_ci /* Select camera register */ 22158c2ecf20Sopenharmony_ci reg_w(sd, R51x_I2C_SADDR_2, reg); 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci /* Initiate 2-byte write cycle */ 22188c2ecf20Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x03); 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_ci do { 22218c2ecf20Sopenharmony_ci rc = reg_r(sd, R511_I2C_CTL); 22228c2ecf20Sopenharmony_ci } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci if (rc < 0) 22258c2ecf20Sopenharmony_ci return rc; 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_ci if ((rc & 2) == 0) /* Ack? */ 22288c2ecf20Sopenharmony_ci break; 22298c2ecf20Sopenharmony_ci 22308c2ecf20Sopenharmony_ci /* I2C abort */ 22318c2ecf20Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x10); 22328c2ecf20Sopenharmony_ci 22338c2ecf20Sopenharmony_ci if (--retries < 0) { 22348c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "i2c write retries exhausted\n"); 22358c2ecf20Sopenharmony_ci return -1; 22368c2ecf20Sopenharmony_ci } 22378c2ecf20Sopenharmony_ci } 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci /* Two byte read cycle */ 22408c2ecf20Sopenharmony_ci for (retries = 6; ; ) { 22418c2ecf20Sopenharmony_ci /* Initiate 2-byte read cycle */ 22428c2ecf20Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x05); 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci do { 22458c2ecf20Sopenharmony_ci rc = reg_r(sd, R511_I2C_CTL); 22468c2ecf20Sopenharmony_ci } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci if (rc < 0) 22498c2ecf20Sopenharmony_ci return rc; 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_ci if ((rc & 2) == 0) /* Ack? */ 22528c2ecf20Sopenharmony_ci break; 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_ci /* I2C abort */ 22558c2ecf20Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x10); 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci if (--retries < 0) { 22588c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "i2c read retries exhausted\n"); 22598c2ecf20Sopenharmony_ci return -1; 22608c2ecf20Sopenharmony_ci } 22618c2ecf20Sopenharmony_ci } 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_ci value = reg_r(sd, R51x_I2C_DATA); 22648c2ecf20Sopenharmony_ci 22658c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "ov511_i2c_r %02x %02x\n", reg, value); 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci /* This is needed to make i2c_w() work */ 22688c2ecf20Sopenharmony_ci reg_w(sd, R511_I2C_CTL, 0x05); 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_ci return value; 22718c2ecf20Sopenharmony_ci} 22728c2ecf20Sopenharmony_ci 22738c2ecf20Sopenharmony_ci/* 22748c2ecf20Sopenharmony_ci * The OV518 I2C I/O procedure is different, hence, this function. 22758c2ecf20Sopenharmony_ci * This is normally only called from i2c_w(). Note that this function 22768c2ecf20Sopenharmony_ci * always succeeds regardless of whether the sensor is present and working. 22778c2ecf20Sopenharmony_ci */ 22788c2ecf20Sopenharmony_cistatic void ov518_i2c_w(struct sd *sd, 22798c2ecf20Sopenharmony_ci u8 reg, 22808c2ecf20Sopenharmony_ci u8 value) 22818c2ecf20Sopenharmony_ci{ 22828c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "ov518_i2c_w %02x %02x\n", reg, value); 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_ci /* Select camera register */ 22878c2ecf20Sopenharmony_ci reg_w(sd, R51x_I2C_SADDR_3, reg); 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_ci /* Write "value" to I2C data port of OV511 */ 22908c2ecf20Sopenharmony_ci reg_w(sd, R51x_I2C_DATA, value); 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci /* Initiate 3-byte write cycle */ 22938c2ecf20Sopenharmony_ci reg_w(sd, R518_I2C_CTL, 0x01); 22948c2ecf20Sopenharmony_ci 22958c2ecf20Sopenharmony_ci /* wait for write complete */ 22968c2ecf20Sopenharmony_ci msleep(4); 22978c2ecf20Sopenharmony_ci reg_r8(sd, R518_I2C_CTL); 22988c2ecf20Sopenharmony_ci} 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci/* 23018c2ecf20Sopenharmony_ci * returns: negative is error, pos or zero is data 23028c2ecf20Sopenharmony_ci * 23038c2ecf20Sopenharmony_ci * The OV518 I2C I/O procedure is different, hence, this function. 23048c2ecf20Sopenharmony_ci * This is normally only called from i2c_r(). Note that this function 23058c2ecf20Sopenharmony_ci * always succeeds regardless of whether the sensor is present and working. 23068c2ecf20Sopenharmony_ci */ 23078c2ecf20Sopenharmony_cistatic int ov518_i2c_r(struct sd *sd, u8 reg) 23088c2ecf20Sopenharmony_ci{ 23098c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 23108c2ecf20Sopenharmony_ci int value; 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_ci /* Select camera register */ 23138c2ecf20Sopenharmony_ci reg_w(sd, R51x_I2C_SADDR_2, reg); 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci /* Initiate 2-byte write cycle */ 23168c2ecf20Sopenharmony_ci reg_w(sd, R518_I2C_CTL, 0x03); 23178c2ecf20Sopenharmony_ci reg_r8(sd, R518_I2C_CTL); 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci /* Initiate 2-byte read cycle */ 23208c2ecf20Sopenharmony_ci reg_w(sd, R518_I2C_CTL, 0x05); 23218c2ecf20Sopenharmony_ci reg_r8(sd, R518_I2C_CTL); 23228c2ecf20Sopenharmony_ci 23238c2ecf20Sopenharmony_ci value = reg_r(sd, R51x_I2C_DATA); 23248c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "ov518_i2c_r %02x %02x\n", reg, value); 23258c2ecf20Sopenharmony_ci return value; 23268c2ecf20Sopenharmony_ci} 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_cistatic void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) 23298c2ecf20Sopenharmony_ci{ 23308c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 23318c2ecf20Sopenharmony_ci int ret; 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 23348c2ecf20Sopenharmony_ci return; 23358c2ecf20Sopenharmony_ci 23368c2ecf20Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 23378c2ecf20Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 23388c2ecf20Sopenharmony_ci 0x02, 23398c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 23408c2ecf20Sopenharmony_ci (u16) value, (u16) reg, NULL, 0, 500); 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci if (ret < 0) { 23438c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "ovfx2_i2c_w %02x failed %d\n", reg, ret); 23448c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = ret; 23458c2ecf20Sopenharmony_ci } 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "ovfx2_i2c_w %02x %02x\n", reg, value); 23488c2ecf20Sopenharmony_ci} 23498c2ecf20Sopenharmony_ci 23508c2ecf20Sopenharmony_cistatic int ovfx2_i2c_r(struct sd *sd, u8 reg) 23518c2ecf20Sopenharmony_ci{ 23528c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 23538c2ecf20Sopenharmony_ci int ret; 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 23568c2ecf20Sopenharmony_ci return -1; 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 23598c2ecf20Sopenharmony_ci usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 23608c2ecf20Sopenharmony_ci 0x03, 23618c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 23628c2ecf20Sopenharmony_ci 0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500); 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci if (ret >= 0) { 23658c2ecf20Sopenharmony_ci ret = sd->gspca_dev.usb_buf[0]; 23668c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "ovfx2_i2c_r %02x %02x\n", 23678c2ecf20Sopenharmony_ci reg, ret); 23688c2ecf20Sopenharmony_ci } else { 23698c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "ovfx2_i2c_r %02x failed %d\n", reg, ret); 23708c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = ret; 23718c2ecf20Sopenharmony_ci } 23728c2ecf20Sopenharmony_ci 23738c2ecf20Sopenharmony_ci return ret; 23748c2ecf20Sopenharmony_ci} 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_cistatic void i2c_w(struct sd *sd, u8 reg, u8 value) 23778c2ecf20Sopenharmony_ci{ 23788c2ecf20Sopenharmony_ci if (sd->sensor_reg_cache[reg] == value) 23798c2ecf20Sopenharmony_ci return; 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci switch (sd->bridge) { 23828c2ecf20Sopenharmony_ci case BRIDGE_OV511: 23838c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 23848c2ecf20Sopenharmony_ci ov511_i2c_w(sd, reg, value); 23858c2ecf20Sopenharmony_ci break; 23868c2ecf20Sopenharmony_ci case BRIDGE_OV518: 23878c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 23888c2ecf20Sopenharmony_ci case BRIDGE_OV519: 23898c2ecf20Sopenharmony_ci ov518_i2c_w(sd, reg, value); 23908c2ecf20Sopenharmony_ci break; 23918c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 23928c2ecf20Sopenharmony_ci ovfx2_i2c_w(sd, reg, value); 23938c2ecf20Sopenharmony_ci break; 23948c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 23958c2ecf20Sopenharmony_ci w9968cf_i2c_w(sd, reg, value); 23968c2ecf20Sopenharmony_ci break; 23978c2ecf20Sopenharmony_ci } 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_ci if (sd->gspca_dev.usb_err >= 0) { 24008c2ecf20Sopenharmony_ci /* Up on sensor reset empty the register cache */ 24018c2ecf20Sopenharmony_ci if (reg == 0x12 && (value & 0x80)) 24028c2ecf20Sopenharmony_ci memset(sd->sensor_reg_cache, -1, 24038c2ecf20Sopenharmony_ci sizeof(sd->sensor_reg_cache)); 24048c2ecf20Sopenharmony_ci else 24058c2ecf20Sopenharmony_ci sd->sensor_reg_cache[reg] = value; 24068c2ecf20Sopenharmony_ci } 24078c2ecf20Sopenharmony_ci} 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_cistatic int i2c_r(struct sd *sd, u8 reg) 24108c2ecf20Sopenharmony_ci{ 24118c2ecf20Sopenharmony_ci int ret = -1; 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci if (sd->sensor_reg_cache[reg] != -1) 24148c2ecf20Sopenharmony_ci return sd->sensor_reg_cache[reg]; 24158c2ecf20Sopenharmony_ci 24168c2ecf20Sopenharmony_ci switch (sd->bridge) { 24178c2ecf20Sopenharmony_ci case BRIDGE_OV511: 24188c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 24198c2ecf20Sopenharmony_ci ret = ov511_i2c_r(sd, reg); 24208c2ecf20Sopenharmony_ci break; 24218c2ecf20Sopenharmony_ci case BRIDGE_OV518: 24228c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 24238c2ecf20Sopenharmony_ci case BRIDGE_OV519: 24248c2ecf20Sopenharmony_ci ret = ov518_i2c_r(sd, reg); 24258c2ecf20Sopenharmony_ci break; 24268c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 24278c2ecf20Sopenharmony_ci ret = ovfx2_i2c_r(sd, reg); 24288c2ecf20Sopenharmony_ci break; 24298c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 24308c2ecf20Sopenharmony_ci ret = w9968cf_i2c_r(sd, reg); 24318c2ecf20Sopenharmony_ci break; 24328c2ecf20Sopenharmony_ci } 24338c2ecf20Sopenharmony_ci 24348c2ecf20Sopenharmony_ci if (ret >= 0) 24358c2ecf20Sopenharmony_ci sd->sensor_reg_cache[reg] = ret; 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_ci return ret; 24388c2ecf20Sopenharmony_ci} 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci/* Writes bits at positions specified by mask to an I2C reg. Bits that are in 24418c2ecf20Sopenharmony_ci * the same position as 1's in "mask" are cleared and set to "value". Bits 24428c2ecf20Sopenharmony_ci * that are in the same position as 0's in "mask" are preserved, regardless 24438c2ecf20Sopenharmony_ci * of their respective state in "value". 24448c2ecf20Sopenharmony_ci */ 24458c2ecf20Sopenharmony_cistatic void i2c_w_mask(struct sd *sd, 24468c2ecf20Sopenharmony_ci u8 reg, 24478c2ecf20Sopenharmony_ci u8 value, 24488c2ecf20Sopenharmony_ci u8 mask) 24498c2ecf20Sopenharmony_ci{ 24508c2ecf20Sopenharmony_ci int rc; 24518c2ecf20Sopenharmony_ci u8 oldval; 24528c2ecf20Sopenharmony_ci 24538c2ecf20Sopenharmony_ci value &= mask; /* Enforce mask on value */ 24548c2ecf20Sopenharmony_ci rc = i2c_r(sd, reg); 24558c2ecf20Sopenharmony_ci if (rc < 0) 24568c2ecf20Sopenharmony_ci return; 24578c2ecf20Sopenharmony_ci oldval = rc & ~mask; /* Clear the masked bits */ 24588c2ecf20Sopenharmony_ci value |= oldval; /* Set the desired bits */ 24598c2ecf20Sopenharmony_ci i2c_w(sd, reg, value); 24608c2ecf20Sopenharmony_ci} 24618c2ecf20Sopenharmony_ci 24628c2ecf20Sopenharmony_ci/* Temporarily stops OV511 from functioning. Must do this before changing 24638c2ecf20Sopenharmony_ci * registers while the camera is streaming */ 24648c2ecf20Sopenharmony_cistatic inline void ov51x_stop(struct sd *sd) 24658c2ecf20Sopenharmony_ci{ 24668c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "stopping\n"); 24698c2ecf20Sopenharmony_ci sd->stopped = 1; 24708c2ecf20Sopenharmony_ci switch (sd->bridge) { 24718c2ecf20Sopenharmony_ci case BRIDGE_OV511: 24728c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 24738c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x3d); 24748c2ecf20Sopenharmony_ci break; 24758c2ecf20Sopenharmony_ci case BRIDGE_OV518: 24768c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 24778c2ecf20Sopenharmony_ci reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); 24788c2ecf20Sopenharmony_ci break; 24798c2ecf20Sopenharmony_ci case BRIDGE_OV519: 24808c2ecf20Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x0f); 24818c2ecf20Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x00); 24828c2ecf20Sopenharmony_ci reg_w(sd, 0x22, 0x00); /* FRAR */ 24838c2ecf20Sopenharmony_ci break; 24848c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 24858c2ecf20Sopenharmony_ci reg_w_mask(sd, 0x0f, 0x00, 0x02); 24868c2ecf20Sopenharmony_ci break; 24878c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 24888c2ecf20Sopenharmony_ci reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ 24898c2ecf20Sopenharmony_ci break; 24908c2ecf20Sopenharmony_ci } 24918c2ecf20Sopenharmony_ci} 24928c2ecf20Sopenharmony_ci 24938c2ecf20Sopenharmony_ci/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not 24948c2ecf20Sopenharmony_ci * actually stopped (for performance). */ 24958c2ecf20Sopenharmony_cistatic inline void ov51x_restart(struct sd *sd) 24968c2ecf20Sopenharmony_ci{ 24978c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "restarting\n"); 25008c2ecf20Sopenharmony_ci if (!sd->stopped) 25018c2ecf20Sopenharmony_ci return; 25028c2ecf20Sopenharmony_ci sd->stopped = 0; 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci /* Reinitialize the stream */ 25058c2ecf20Sopenharmony_ci switch (sd->bridge) { 25068c2ecf20Sopenharmony_ci case BRIDGE_OV511: 25078c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 25088c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x00); 25098c2ecf20Sopenharmony_ci break; 25108c2ecf20Sopenharmony_ci case BRIDGE_OV518: 25118c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 25128c2ecf20Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 25138c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x00); 25148c2ecf20Sopenharmony_ci break; 25158c2ecf20Sopenharmony_ci case BRIDGE_OV519: 25168c2ecf20Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x0f); 25178c2ecf20Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x00); 25188c2ecf20Sopenharmony_ci reg_w(sd, 0x22, 0x1d); /* FRAR */ 25198c2ecf20Sopenharmony_ci break; 25208c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 25218c2ecf20Sopenharmony_ci reg_w_mask(sd, 0x0f, 0x02, 0x02); 25228c2ecf20Sopenharmony_ci break; 25238c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 25248c2ecf20Sopenharmony_ci reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ 25258c2ecf20Sopenharmony_ci break; 25268c2ecf20Sopenharmony_ci } 25278c2ecf20Sopenharmony_ci} 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_cistatic void ov51x_set_slave_ids(struct sd *sd, u8 slave); 25308c2ecf20Sopenharmony_ci 25318c2ecf20Sopenharmony_ci/* This does an initial reset of an OmniVision sensor and ensures that I2C 25328c2ecf20Sopenharmony_ci * is synchronized. Returns <0 on failure. 25338c2ecf20Sopenharmony_ci */ 25348c2ecf20Sopenharmony_cistatic int init_ov_sensor(struct sd *sd, u8 slave) 25358c2ecf20Sopenharmony_ci{ 25368c2ecf20Sopenharmony_ci int i; 25378c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_ci ov51x_set_slave_ids(sd, slave); 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci /* Reset the sensor */ 25428c2ecf20Sopenharmony_ci i2c_w(sd, 0x12, 0x80); 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci /* Wait for it to initialize */ 25458c2ecf20Sopenharmony_ci msleep(150); 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci for (i = 0; i < i2c_detect_tries; i++) { 25488c2ecf20Sopenharmony_ci if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f && 25498c2ecf20Sopenharmony_ci i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) { 25508c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "I2C synced in %d attempt(s)\n", 25518c2ecf20Sopenharmony_ci i); 25528c2ecf20Sopenharmony_ci return 0; 25538c2ecf20Sopenharmony_ci } 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_ci /* Reset the sensor */ 25568c2ecf20Sopenharmony_ci i2c_w(sd, 0x12, 0x80); 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci /* Wait for it to initialize */ 25598c2ecf20Sopenharmony_ci msleep(150); 25608c2ecf20Sopenharmony_ci 25618c2ecf20Sopenharmony_ci /* Dummy read to sync I2C */ 25628c2ecf20Sopenharmony_ci if (i2c_r(sd, 0x00) < 0) 25638c2ecf20Sopenharmony_ci return -1; 25648c2ecf20Sopenharmony_ci } 25658c2ecf20Sopenharmony_ci return -1; 25668c2ecf20Sopenharmony_ci} 25678c2ecf20Sopenharmony_ci 25688c2ecf20Sopenharmony_ci/* Set the read and write slave IDs. The "slave" argument is the write slave, 25698c2ecf20Sopenharmony_ci * and the read slave will be set to (slave + 1). 25708c2ecf20Sopenharmony_ci * This should not be called from outside the i2c I/O functions. 25718c2ecf20Sopenharmony_ci * Sets I2C read and write slave IDs. Returns <0 for error 25728c2ecf20Sopenharmony_ci */ 25738c2ecf20Sopenharmony_cistatic void ov51x_set_slave_ids(struct sd *sd, 25748c2ecf20Sopenharmony_ci u8 slave) 25758c2ecf20Sopenharmony_ci{ 25768c2ecf20Sopenharmony_ci switch (sd->bridge) { 25778c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 25788c2ecf20Sopenharmony_ci reg_w(sd, OVFX2_I2C_ADDR, slave); 25798c2ecf20Sopenharmony_ci return; 25808c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 25818c2ecf20Sopenharmony_ci sd->sensor_addr = slave; 25828c2ecf20Sopenharmony_ci return; 25838c2ecf20Sopenharmony_ci } 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci reg_w(sd, R51x_I2C_W_SID, slave); 25868c2ecf20Sopenharmony_ci reg_w(sd, R51x_I2C_R_SID, slave + 1); 25878c2ecf20Sopenharmony_ci} 25888c2ecf20Sopenharmony_ci 25898c2ecf20Sopenharmony_cistatic void write_regvals(struct sd *sd, 25908c2ecf20Sopenharmony_ci const struct ov_regvals *regvals, 25918c2ecf20Sopenharmony_ci int n) 25928c2ecf20Sopenharmony_ci{ 25938c2ecf20Sopenharmony_ci while (--n >= 0) { 25948c2ecf20Sopenharmony_ci reg_w(sd, regvals->reg, regvals->val); 25958c2ecf20Sopenharmony_ci regvals++; 25968c2ecf20Sopenharmony_ci } 25978c2ecf20Sopenharmony_ci} 25988c2ecf20Sopenharmony_ci 25998c2ecf20Sopenharmony_cistatic void write_i2c_regvals(struct sd *sd, 26008c2ecf20Sopenharmony_ci const struct ov_i2c_regvals *regvals, 26018c2ecf20Sopenharmony_ci int n) 26028c2ecf20Sopenharmony_ci{ 26038c2ecf20Sopenharmony_ci while (--n >= 0) { 26048c2ecf20Sopenharmony_ci i2c_w(sd, regvals->reg, regvals->val); 26058c2ecf20Sopenharmony_ci regvals++; 26068c2ecf20Sopenharmony_ci } 26078c2ecf20Sopenharmony_ci} 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci/**************************************************************************** 26108c2ecf20Sopenharmony_ci * 26118c2ecf20Sopenharmony_ci * OV511 and sensor configuration 26128c2ecf20Sopenharmony_ci * 26138c2ecf20Sopenharmony_ci ***************************************************************************/ 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */ 26168c2ecf20Sopenharmony_cistatic void ov_hires_configure(struct sd *sd) 26178c2ecf20Sopenharmony_ci{ 26188c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 26198c2ecf20Sopenharmony_ci int high, low; 26208c2ecf20Sopenharmony_ci 26218c2ecf20Sopenharmony_ci if (sd->bridge != BRIDGE_OVFX2) { 26228c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "error hires sensors only supported with ovfx2\n"); 26238c2ecf20Sopenharmony_ci return; 26248c2ecf20Sopenharmony_ci } 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "starting ov hires configuration\n"); 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci /* Detect sensor (sub)type */ 26298c2ecf20Sopenharmony_ci high = i2c_r(sd, 0x0a); 26308c2ecf20Sopenharmony_ci low = i2c_r(sd, 0x0b); 26318c2ecf20Sopenharmony_ci /* info("%x, %x", high, low); */ 26328c2ecf20Sopenharmony_ci switch (high) { 26338c2ecf20Sopenharmony_ci case 0x96: 26348c2ecf20Sopenharmony_ci switch (low) { 26358c2ecf20Sopenharmony_ci case 0x40: 26368c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV2610\n"); 26378c2ecf20Sopenharmony_ci sd->sensor = SEN_OV2610; 26388c2ecf20Sopenharmony_ci return; 26398c2ecf20Sopenharmony_ci case 0x41: 26408c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV2610AE\n"); 26418c2ecf20Sopenharmony_ci sd->sensor = SEN_OV2610AE; 26428c2ecf20Sopenharmony_ci return; 26438c2ecf20Sopenharmony_ci case 0xb1: 26448c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV9600\n"); 26458c2ecf20Sopenharmony_ci sd->sensor = SEN_OV9600; 26468c2ecf20Sopenharmony_ci return; 26478c2ecf20Sopenharmony_ci } 26488c2ecf20Sopenharmony_ci break; 26498c2ecf20Sopenharmony_ci case 0x36: 26508c2ecf20Sopenharmony_ci if ((low & 0x0f) == 0x00) { 26518c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV3610\n"); 26528c2ecf20Sopenharmony_ci sd->sensor = SEN_OV3610; 26538c2ecf20Sopenharmony_ci return; 26548c2ecf20Sopenharmony_ci } 26558c2ecf20Sopenharmony_ci break; 26568c2ecf20Sopenharmony_ci } 26578c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Error unknown sensor type: %02x%02x\n", 26588c2ecf20Sopenharmony_ci high, low); 26598c2ecf20Sopenharmony_ci} 26608c2ecf20Sopenharmony_ci 26618c2ecf20Sopenharmony_ci/* This initializes the OV8110, OV8610 sensor. The OV8110 uses 26628c2ecf20Sopenharmony_ci * the same register settings as the OV8610, since they are very similar. 26638c2ecf20Sopenharmony_ci */ 26648c2ecf20Sopenharmony_cistatic void ov8xx0_configure(struct sd *sd) 26658c2ecf20Sopenharmony_ci{ 26668c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 26678c2ecf20Sopenharmony_ci int rc; 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "starting ov8xx0 configuration\n"); 26708c2ecf20Sopenharmony_ci 26718c2ecf20Sopenharmony_ci /* Detect sensor (sub)type */ 26728c2ecf20Sopenharmony_ci rc = i2c_r(sd, OV7610_REG_COM_I); 26738c2ecf20Sopenharmony_ci if (rc < 0) { 26748c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Error detecting sensor type\n"); 26758c2ecf20Sopenharmony_ci return; 26768c2ecf20Sopenharmony_ci } 26778c2ecf20Sopenharmony_ci if ((rc & 3) == 1) 26788c2ecf20Sopenharmony_ci sd->sensor = SEN_OV8610; 26798c2ecf20Sopenharmony_ci else 26808c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Unknown image sensor version: %d\n", 26818c2ecf20Sopenharmony_ci rc & 3); 26828c2ecf20Sopenharmony_ci} 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_ci/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses 26858c2ecf20Sopenharmony_ci * the same register settings as the OV7610, since they are very similar. 26868c2ecf20Sopenharmony_ci */ 26878c2ecf20Sopenharmony_cistatic void ov7xx0_configure(struct sd *sd) 26888c2ecf20Sopenharmony_ci{ 26898c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 26908c2ecf20Sopenharmony_ci int rc, high, low; 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "starting OV7xx0 configuration\n"); 26938c2ecf20Sopenharmony_ci 26948c2ecf20Sopenharmony_ci /* Detect sensor (sub)type */ 26958c2ecf20Sopenharmony_ci rc = i2c_r(sd, OV7610_REG_COM_I); 26968c2ecf20Sopenharmony_ci 26978c2ecf20Sopenharmony_ci /* add OV7670 here 26988c2ecf20Sopenharmony_ci * it appears to be wrongly detected as a 7610 by default */ 26998c2ecf20Sopenharmony_ci if (rc < 0) { 27008c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Error detecting sensor type\n"); 27018c2ecf20Sopenharmony_ci return; 27028c2ecf20Sopenharmony_ci } 27038c2ecf20Sopenharmony_ci if ((rc & 3) == 3) { 27048c2ecf20Sopenharmony_ci /* quick hack to make OV7670s work */ 27058c2ecf20Sopenharmony_ci high = i2c_r(sd, 0x0a); 27068c2ecf20Sopenharmony_ci low = i2c_r(sd, 0x0b); 27078c2ecf20Sopenharmony_ci /* info("%x, %x", high, low); */ 27088c2ecf20Sopenharmony_ci if (high == 0x76 && (low & 0xf0) == 0x70) { 27098c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV76%02x\n", 27108c2ecf20Sopenharmony_ci low); 27118c2ecf20Sopenharmony_ci sd->sensor = SEN_OV7670; 27128c2ecf20Sopenharmony_ci } else { 27138c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7610\n"); 27148c2ecf20Sopenharmony_ci sd->sensor = SEN_OV7610; 27158c2ecf20Sopenharmony_ci } 27168c2ecf20Sopenharmony_ci } else if ((rc & 3) == 1) { 27178c2ecf20Sopenharmony_ci /* I don't know what's different about the 76BE yet. */ 27188c2ecf20Sopenharmony_ci if (i2c_r(sd, 0x15) & 1) { 27198c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7620AE\n"); 27208c2ecf20Sopenharmony_ci sd->sensor = SEN_OV7620AE; 27218c2ecf20Sopenharmony_ci } else { 27228c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV76BE\n"); 27238c2ecf20Sopenharmony_ci sd->sensor = SEN_OV76BE; 27248c2ecf20Sopenharmony_ci } 27258c2ecf20Sopenharmony_ci } else if ((rc & 3) == 0) { 27268c2ecf20Sopenharmony_ci /* try to read product id registers */ 27278c2ecf20Sopenharmony_ci high = i2c_r(sd, 0x0a); 27288c2ecf20Sopenharmony_ci if (high < 0) { 27298c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Error detecting camera chip PID\n"); 27308c2ecf20Sopenharmony_ci return; 27318c2ecf20Sopenharmony_ci } 27328c2ecf20Sopenharmony_ci low = i2c_r(sd, 0x0b); 27338c2ecf20Sopenharmony_ci if (low < 0) { 27348c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Error detecting camera chip VER\n"); 27358c2ecf20Sopenharmony_ci return; 27368c2ecf20Sopenharmony_ci } 27378c2ecf20Sopenharmony_ci if (high == 0x76) { 27388c2ecf20Sopenharmony_ci switch (low) { 27398c2ecf20Sopenharmony_ci case 0x30: 27408c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Sensor is an OV7630/OV7635\n"); 27418c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "7630 is not supported by this driver\n"); 27428c2ecf20Sopenharmony_ci return; 27438c2ecf20Sopenharmony_ci case 0x40: 27448c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7645\n"); 27458c2ecf20Sopenharmony_ci sd->sensor = SEN_OV7640; /* FIXME */ 27468c2ecf20Sopenharmony_ci break; 27478c2ecf20Sopenharmony_ci case 0x45: 27488c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7645B\n"); 27498c2ecf20Sopenharmony_ci sd->sensor = SEN_OV7640; /* FIXME */ 27508c2ecf20Sopenharmony_ci break; 27518c2ecf20Sopenharmony_ci case 0x48: 27528c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7648\n"); 27538c2ecf20Sopenharmony_ci sd->sensor = SEN_OV7648; 27548c2ecf20Sopenharmony_ci break; 27558c2ecf20Sopenharmony_ci case 0x60: 27568c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV7660\n"); 27578c2ecf20Sopenharmony_ci sd->sensor = SEN_OV7660; 27588c2ecf20Sopenharmony_ci break; 27598c2ecf20Sopenharmony_ci default: 27608c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Unknown sensor: 0x76%02x\n", 27618c2ecf20Sopenharmony_ci low); 27628c2ecf20Sopenharmony_ci return; 27638c2ecf20Sopenharmony_ci } 27648c2ecf20Sopenharmony_ci } else { 27658c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7620\n"); 27668c2ecf20Sopenharmony_ci sd->sensor = SEN_OV7620; 27678c2ecf20Sopenharmony_ci } 27688c2ecf20Sopenharmony_ci } else { 27698c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Unknown image sensor version: %d\n", 27708c2ecf20Sopenharmony_ci rc & 3); 27718c2ecf20Sopenharmony_ci } 27728c2ecf20Sopenharmony_ci} 27738c2ecf20Sopenharmony_ci 27748c2ecf20Sopenharmony_ci/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ 27758c2ecf20Sopenharmony_cistatic void ov6xx0_configure(struct sd *sd) 27768c2ecf20Sopenharmony_ci{ 27778c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 27788c2ecf20Sopenharmony_ci int rc; 27798c2ecf20Sopenharmony_ci 27808c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "starting OV6xx0 configuration\n"); 27818c2ecf20Sopenharmony_ci 27828c2ecf20Sopenharmony_ci /* Detect sensor (sub)type */ 27838c2ecf20Sopenharmony_ci rc = i2c_r(sd, OV7610_REG_COM_I); 27848c2ecf20Sopenharmony_ci if (rc < 0) { 27858c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Error detecting sensor type\n"); 27868c2ecf20Sopenharmony_ci return; 27878c2ecf20Sopenharmony_ci } 27888c2ecf20Sopenharmony_ci 27898c2ecf20Sopenharmony_ci /* Ugh. The first two bits are the version bits, but 27908c2ecf20Sopenharmony_ci * the entire register value must be used. I guess OVT 27918c2ecf20Sopenharmony_ci * underestimated how many variants they would make. */ 27928c2ecf20Sopenharmony_ci switch (rc) { 27938c2ecf20Sopenharmony_ci case 0x00: 27948c2ecf20Sopenharmony_ci sd->sensor = SEN_OV6630; 27958c2ecf20Sopenharmony_ci pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n"); 27968c2ecf20Sopenharmony_ci break; 27978c2ecf20Sopenharmony_ci case 0x01: 27988c2ecf20Sopenharmony_ci sd->sensor = SEN_OV6620; 27998c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV6620\n"); 28008c2ecf20Sopenharmony_ci break; 28018c2ecf20Sopenharmony_ci case 0x02: 28028c2ecf20Sopenharmony_ci sd->sensor = SEN_OV6630; 28038c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV66308AE\n"); 28048c2ecf20Sopenharmony_ci break; 28058c2ecf20Sopenharmony_ci case 0x03: 28068c2ecf20Sopenharmony_ci sd->sensor = SEN_OV66308AF; 28078c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV66308AF\n"); 28088c2ecf20Sopenharmony_ci break; 28098c2ecf20Sopenharmony_ci case 0x90: 28108c2ecf20Sopenharmony_ci sd->sensor = SEN_OV6630; 28118c2ecf20Sopenharmony_ci pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n"); 28128c2ecf20Sopenharmony_ci break; 28138c2ecf20Sopenharmony_ci default: 28148c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "FATAL: Unknown sensor version: 0x%02x\n", 28158c2ecf20Sopenharmony_ci rc); 28168c2ecf20Sopenharmony_ci return; 28178c2ecf20Sopenharmony_ci } 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci /* Set sensor-specific vars */ 28208c2ecf20Sopenharmony_ci sd->sif = 1; 28218c2ecf20Sopenharmony_ci} 28228c2ecf20Sopenharmony_ci 28238c2ecf20Sopenharmony_ci/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ 28248c2ecf20Sopenharmony_cistatic void ov51x_led_control(struct sd *sd, int on) 28258c2ecf20Sopenharmony_ci{ 28268c2ecf20Sopenharmony_ci if (sd->invert_led) 28278c2ecf20Sopenharmony_ci on = !on; 28288c2ecf20Sopenharmony_ci 28298c2ecf20Sopenharmony_ci switch (sd->bridge) { 28308c2ecf20Sopenharmony_ci /* OV511 has no LED control */ 28318c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 28328c2ecf20Sopenharmony_ci reg_w(sd, R511_SYS_LED_CTL, on); 28338c2ecf20Sopenharmony_ci break; 28348c2ecf20Sopenharmony_ci case BRIDGE_OV518: 28358c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 28368c2ecf20Sopenharmony_ci reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02); 28378c2ecf20Sopenharmony_ci break; 28388c2ecf20Sopenharmony_ci case BRIDGE_OV519: 28398c2ecf20Sopenharmony_ci reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1); 28408c2ecf20Sopenharmony_ci break; 28418c2ecf20Sopenharmony_ci } 28428c2ecf20Sopenharmony_ci} 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_cistatic void sd_reset_snapshot(struct gspca_dev *gspca_dev) 28458c2ecf20Sopenharmony_ci{ 28468c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_ci if (!sd->snapshot_needs_reset) 28498c2ecf20Sopenharmony_ci return; 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ci /* Note it is important that we clear sd->snapshot_needs_reset, 28528c2ecf20Sopenharmony_ci before actually clearing the snapshot state in the bridge 28538c2ecf20Sopenharmony_ci otherwise we might race with the pkt_scan interrupt handler */ 28548c2ecf20Sopenharmony_ci sd->snapshot_needs_reset = 0; 28558c2ecf20Sopenharmony_ci 28568c2ecf20Sopenharmony_ci switch (sd->bridge) { 28578c2ecf20Sopenharmony_ci case BRIDGE_OV511: 28588c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 28598c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_SNAP, 0x02); 28608c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_SNAP, 0x00); 28618c2ecf20Sopenharmony_ci break; 28628c2ecf20Sopenharmony_ci case BRIDGE_OV518: 28638c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 28648c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */ 28658c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */ 28668c2ecf20Sopenharmony_ci break; 28678c2ecf20Sopenharmony_ci case BRIDGE_OV519: 28688c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x40); 28698c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0x00); 28708c2ecf20Sopenharmony_ci break; 28718c2ecf20Sopenharmony_ci } 28728c2ecf20Sopenharmony_ci} 28738c2ecf20Sopenharmony_ci 28748c2ecf20Sopenharmony_cistatic void ov51x_upload_quan_tables(struct sd *sd) 28758c2ecf20Sopenharmony_ci{ 28768c2ecf20Sopenharmony_ci static const unsigned char yQuanTable511[] = { 28778c2ecf20Sopenharmony_ci 0, 1, 1, 2, 2, 3, 3, 4, 28788c2ecf20Sopenharmony_ci 1, 1, 1, 2, 2, 3, 4, 4, 28798c2ecf20Sopenharmony_ci 1, 1, 2, 2, 3, 4, 4, 4, 28808c2ecf20Sopenharmony_ci 2, 2, 2, 3, 4, 4, 4, 4, 28818c2ecf20Sopenharmony_ci 2, 2, 3, 4, 4, 5, 5, 5, 28828c2ecf20Sopenharmony_ci 3, 3, 4, 4, 5, 5, 5, 5, 28838c2ecf20Sopenharmony_ci 3, 4, 4, 4, 5, 5, 5, 5, 28848c2ecf20Sopenharmony_ci 4, 4, 4, 4, 5, 5, 5, 5 28858c2ecf20Sopenharmony_ci }; 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci static const unsigned char uvQuanTable511[] = { 28888c2ecf20Sopenharmony_ci 0, 2, 2, 3, 4, 4, 4, 4, 28898c2ecf20Sopenharmony_ci 2, 2, 2, 4, 4, 4, 4, 4, 28908c2ecf20Sopenharmony_ci 2, 2, 3, 4, 4, 4, 4, 4, 28918c2ecf20Sopenharmony_ci 3, 4, 4, 4, 4, 4, 4, 4, 28928c2ecf20Sopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 28938c2ecf20Sopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 28948c2ecf20Sopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 28958c2ecf20Sopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4 28968c2ecf20Sopenharmony_ci }; 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_ci /* OV518 quantization tables are 8x4 (instead of 8x8) */ 28998c2ecf20Sopenharmony_ci static const unsigned char yQuanTable518[] = { 29008c2ecf20Sopenharmony_ci 5, 4, 5, 6, 6, 7, 7, 7, 29018c2ecf20Sopenharmony_ci 5, 5, 5, 5, 6, 7, 7, 7, 29028c2ecf20Sopenharmony_ci 6, 6, 6, 6, 7, 7, 7, 8, 29038c2ecf20Sopenharmony_ci 7, 7, 6, 7, 7, 7, 8, 8 29048c2ecf20Sopenharmony_ci }; 29058c2ecf20Sopenharmony_ci static const unsigned char uvQuanTable518[] = { 29068c2ecf20Sopenharmony_ci 6, 6, 6, 7, 7, 7, 7, 7, 29078c2ecf20Sopenharmony_ci 6, 6, 6, 7, 7, 7, 7, 7, 29088c2ecf20Sopenharmony_ci 6, 6, 6, 7, 7, 7, 7, 8, 29098c2ecf20Sopenharmony_ci 7, 7, 7, 7, 7, 7, 8, 8 29108c2ecf20Sopenharmony_ci }; 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 29138c2ecf20Sopenharmony_ci const unsigned char *pYTable, *pUVTable; 29148c2ecf20Sopenharmony_ci unsigned char val0, val1; 29158c2ecf20Sopenharmony_ci int i, size, reg = R51x_COMP_LUT_BEGIN; 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Uploading quantization tables\n"); 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { 29208c2ecf20Sopenharmony_ci pYTable = yQuanTable511; 29218c2ecf20Sopenharmony_ci pUVTable = uvQuanTable511; 29228c2ecf20Sopenharmony_ci size = 32; 29238c2ecf20Sopenharmony_ci } else { 29248c2ecf20Sopenharmony_ci pYTable = yQuanTable518; 29258c2ecf20Sopenharmony_ci pUVTable = uvQuanTable518; 29268c2ecf20Sopenharmony_ci size = 16; 29278c2ecf20Sopenharmony_ci } 29288c2ecf20Sopenharmony_ci 29298c2ecf20Sopenharmony_ci for (i = 0; i < size; i++) { 29308c2ecf20Sopenharmony_ci val0 = *pYTable++; 29318c2ecf20Sopenharmony_ci val1 = *pYTable++; 29328c2ecf20Sopenharmony_ci val0 &= 0x0f; 29338c2ecf20Sopenharmony_ci val1 &= 0x0f; 29348c2ecf20Sopenharmony_ci val0 |= val1 << 4; 29358c2ecf20Sopenharmony_ci reg_w(sd, reg, val0); 29368c2ecf20Sopenharmony_ci 29378c2ecf20Sopenharmony_ci val0 = *pUVTable++; 29388c2ecf20Sopenharmony_ci val1 = *pUVTable++; 29398c2ecf20Sopenharmony_ci val0 &= 0x0f; 29408c2ecf20Sopenharmony_ci val1 &= 0x0f; 29418c2ecf20Sopenharmony_ci val0 |= val1 << 4; 29428c2ecf20Sopenharmony_ci reg_w(sd, reg + size, val0); 29438c2ecf20Sopenharmony_ci 29448c2ecf20Sopenharmony_ci reg++; 29458c2ecf20Sopenharmony_ci } 29468c2ecf20Sopenharmony_ci} 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_ci/* This initializes the OV511/OV511+ and the sensor */ 29498c2ecf20Sopenharmony_cistatic void ov511_configure(struct gspca_dev *gspca_dev) 29508c2ecf20Sopenharmony_ci{ 29518c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci /* For 511 and 511+ */ 29548c2ecf20Sopenharmony_ci static const struct ov_regvals init_511[] = { 29558c2ecf20Sopenharmony_ci { R51x_SYS_RESET, 0x7f }, 29568c2ecf20Sopenharmony_ci { R51x_SYS_INIT, 0x01 }, 29578c2ecf20Sopenharmony_ci { R51x_SYS_RESET, 0x7f }, 29588c2ecf20Sopenharmony_ci { R51x_SYS_INIT, 0x01 }, 29598c2ecf20Sopenharmony_ci { R51x_SYS_RESET, 0x3f }, 29608c2ecf20Sopenharmony_ci { R51x_SYS_INIT, 0x01 }, 29618c2ecf20Sopenharmony_ci { R51x_SYS_RESET, 0x3d }, 29628c2ecf20Sopenharmony_ci }; 29638c2ecf20Sopenharmony_ci 29648c2ecf20Sopenharmony_ci static const struct ov_regvals norm_511[] = { 29658c2ecf20Sopenharmony_ci { R511_DRAM_FLOW_CTL, 0x01 }, 29668c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x00 }, 29678c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x02 }, 29688c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x00 }, 29698c2ecf20Sopenharmony_ci { R511_FIFO_OPTS, 0x1f }, 29708c2ecf20Sopenharmony_ci { R511_COMP_EN, 0x00 }, 29718c2ecf20Sopenharmony_ci { R511_COMP_LUT_EN, 0x03 }, 29728c2ecf20Sopenharmony_ci }; 29738c2ecf20Sopenharmony_ci 29748c2ecf20Sopenharmony_ci static const struct ov_regvals norm_511_p[] = { 29758c2ecf20Sopenharmony_ci { R511_DRAM_FLOW_CTL, 0xff }, 29768c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x00 }, 29778c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x02 }, 29788c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x00 }, 29798c2ecf20Sopenharmony_ci { R511_FIFO_OPTS, 0xff }, 29808c2ecf20Sopenharmony_ci { R511_COMP_EN, 0x00 }, 29818c2ecf20Sopenharmony_ci { R511_COMP_LUT_EN, 0x03 }, 29828c2ecf20Sopenharmony_ci }; 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ci static const struct ov_regvals compress_511[] = { 29858c2ecf20Sopenharmony_ci { 0x70, 0x1f }, 29868c2ecf20Sopenharmony_ci { 0x71, 0x05 }, 29878c2ecf20Sopenharmony_ci { 0x72, 0x06 }, 29888c2ecf20Sopenharmony_ci { 0x73, 0x06 }, 29898c2ecf20Sopenharmony_ci { 0x74, 0x14 }, 29908c2ecf20Sopenharmony_ci { 0x75, 0x03 }, 29918c2ecf20Sopenharmony_ci { 0x76, 0x04 }, 29928c2ecf20Sopenharmony_ci { 0x77, 0x04 }, 29938c2ecf20Sopenharmony_ci }; 29948c2ecf20Sopenharmony_ci 29958c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Device custom id %x\n", 29968c2ecf20Sopenharmony_ci reg_r(sd, R51x_SYS_CUST_ID)); 29978c2ecf20Sopenharmony_ci 29988c2ecf20Sopenharmony_ci write_regvals(sd, init_511, ARRAY_SIZE(init_511)); 29998c2ecf20Sopenharmony_ci 30008c2ecf20Sopenharmony_ci switch (sd->bridge) { 30018c2ecf20Sopenharmony_ci case BRIDGE_OV511: 30028c2ecf20Sopenharmony_ci write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); 30038c2ecf20Sopenharmony_ci break; 30048c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 30058c2ecf20Sopenharmony_ci write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); 30068c2ecf20Sopenharmony_ci break; 30078c2ecf20Sopenharmony_ci } 30088c2ecf20Sopenharmony_ci 30098c2ecf20Sopenharmony_ci /* Init compression */ 30108c2ecf20Sopenharmony_ci write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); 30118c2ecf20Sopenharmony_ci 30128c2ecf20Sopenharmony_ci ov51x_upload_quan_tables(sd); 30138c2ecf20Sopenharmony_ci} 30148c2ecf20Sopenharmony_ci 30158c2ecf20Sopenharmony_ci/* This initializes the OV518/OV518+ and the sensor */ 30168c2ecf20Sopenharmony_cistatic void ov518_configure(struct gspca_dev *gspca_dev) 30178c2ecf20Sopenharmony_ci{ 30188c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 30198c2ecf20Sopenharmony_ci 30208c2ecf20Sopenharmony_ci /* For 518 and 518+ */ 30218c2ecf20Sopenharmony_ci static const struct ov_regvals init_518[] = { 30228c2ecf20Sopenharmony_ci { R51x_SYS_RESET, 0x40 }, 30238c2ecf20Sopenharmony_ci { R51x_SYS_INIT, 0xe1 }, 30248c2ecf20Sopenharmony_ci { R51x_SYS_RESET, 0x3e }, 30258c2ecf20Sopenharmony_ci { R51x_SYS_INIT, 0xe1 }, 30268c2ecf20Sopenharmony_ci { R51x_SYS_RESET, 0x00 }, 30278c2ecf20Sopenharmony_ci { R51x_SYS_INIT, 0xe1 }, 30288c2ecf20Sopenharmony_ci { 0x46, 0x00 }, 30298c2ecf20Sopenharmony_ci { 0x5d, 0x03 }, 30308c2ecf20Sopenharmony_ci }; 30318c2ecf20Sopenharmony_ci 30328c2ecf20Sopenharmony_ci static const struct ov_regvals norm_518[] = { 30338c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x02 }, /* Reset */ 30348c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x01 }, /* Enable */ 30358c2ecf20Sopenharmony_ci { 0x31, 0x0f }, 30368c2ecf20Sopenharmony_ci { 0x5d, 0x03 }, 30378c2ecf20Sopenharmony_ci { 0x24, 0x9f }, 30388c2ecf20Sopenharmony_ci { 0x25, 0x90 }, 30398c2ecf20Sopenharmony_ci { 0x20, 0x00 }, 30408c2ecf20Sopenharmony_ci { 0x51, 0x04 }, 30418c2ecf20Sopenharmony_ci { 0x71, 0x19 }, 30428c2ecf20Sopenharmony_ci { 0x2f, 0x80 }, 30438c2ecf20Sopenharmony_ci }; 30448c2ecf20Sopenharmony_ci 30458c2ecf20Sopenharmony_ci static const struct ov_regvals norm_518_p[] = { 30468c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x02 }, /* Reset */ 30478c2ecf20Sopenharmony_ci { R51x_SYS_SNAP, 0x01 }, /* Enable */ 30488c2ecf20Sopenharmony_ci { 0x31, 0x0f }, 30498c2ecf20Sopenharmony_ci { 0x5d, 0x03 }, 30508c2ecf20Sopenharmony_ci { 0x24, 0x9f }, 30518c2ecf20Sopenharmony_ci { 0x25, 0x90 }, 30528c2ecf20Sopenharmony_ci { 0x20, 0x60 }, 30538c2ecf20Sopenharmony_ci { 0x51, 0x02 }, 30548c2ecf20Sopenharmony_ci { 0x71, 0x19 }, 30558c2ecf20Sopenharmony_ci { 0x40, 0xff }, 30568c2ecf20Sopenharmony_ci { 0x41, 0x42 }, 30578c2ecf20Sopenharmony_ci { 0x46, 0x00 }, 30588c2ecf20Sopenharmony_ci { 0x33, 0x04 }, 30598c2ecf20Sopenharmony_ci { 0x21, 0x19 }, 30608c2ecf20Sopenharmony_ci { 0x3f, 0x10 }, 30618c2ecf20Sopenharmony_ci { 0x2f, 0x80 }, 30628c2ecf20Sopenharmony_ci }; 30638c2ecf20Sopenharmony_ci 30648c2ecf20Sopenharmony_ci /* First 5 bits of custom ID reg are a revision ID on OV518 */ 30658c2ecf20Sopenharmony_ci sd->revision = reg_r(sd, R51x_SYS_CUST_ID) & 0x1f; 30668c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PROBE, "Device revision %d\n", sd->revision); 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_ci write_regvals(sd, init_518, ARRAY_SIZE(init_518)); 30698c2ecf20Sopenharmony_ci 30708c2ecf20Sopenharmony_ci /* Set LED GPIO pin to output mode */ 30718c2ecf20Sopenharmony_ci reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci switch (sd->bridge) { 30748c2ecf20Sopenharmony_ci case BRIDGE_OV518: 30758c2ecf20Sopenharmony_ci write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); 30768c2ecf20Sopenharmony_ci break; 30778c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 30788c2ecf20Sopenharmony_ci write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); 30798c2ecf20Sopenharmony_ci break; 30808c2ecf20Sopenharmony_ci } 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_ci ov51x_upload_quan_tables(sd); 30838c2ecf20Sopenharmony_ci 30848c2ecf20Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 30858c2ecf20Sopenharmony_ci} 30868c2ecf20Sopenharmony_ci 30878c2ecf20Sopenharmony_cistatic void ov519_configure(struct sd *sd) 30888c2ecf20Sopenharmony_ci{ 30898c2ecf20Sopenharmony_ci static const struct ov_regvals init_519[] = { 30908c2ecf20Sopenharmony_ci { 0x5a, 0x6d }, /* EnableSystem */ 30918c2ecf20Sopenharmony_ci { 0x53, 0x9b }, /* don't enable the microcontroller */ 30928c2ecf20Sopenharmony_ci { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */ 30938c2ecf20Sopenharmony_ci { 0x5d, 0x03 }, 30948c2ecf20Sopenharmony_ci { 0x49, 0x01 }, 30958c2ecf20Sopenharmony_ci { 0x48, 0x00 }, 30968c2ecf20Sopenharmony_ci /* Set LED pin to output mode. Bit 4 must be cleared or sensor 30978c2ecf20Sopenharmony_ci * detection will fail. This deserves further investigation. */ 30988c2ecf20Sopenharmony_ci { OV519_GPIO_IO_CTRL0, 0xee }, 30998c2ecf20Sopenharmony_ci { OV519_R51_RESET1, 0x0f }, 31008c2ecf20Sopenharmony_ci { OV519_R51_RESET1, 0x00 }, 31018c2ecf20Sopenharmony_ci { 0x22, 0x00 }, 31028c2ecf20Sopenharmony_ci /* windows reads 0x55 at this point*/ 31038c2ecf20Sopenharmony_ci }; 31048c2ecf20Sopenharmony_ci 31058c2ecf20Sopenharmony_ci write_regvals(sd, init_519, ARRAY_SIZE(init_519)); 31068c2ecf20Sopenharmony_ci} 31078c2ecf20Sopenharmony_ci 31088c2ecf20Sopenharmony_cistatic void ovfx2_configure(struct sd *sd) 31098c2ecf20Sopenharmony_ci{ 31108c2ecf20Sopenharmony_ci static const struct ov_regvals init_fx2[] = { 31118c2ecf20Sopenharmony_ci { 0x00, 0x60 }, 31128c2ecf20Sopenharmony_ci { 0x02, 0x01 }, 31138c2ecf20Sopenharmony_ci { 0x0f, 0x1d }, 31148c2ecf20Sopenharmony_ci { 0xe9, 0x82 }, 31158c2ecf20Sopenharmony_ci { 0xea, 0xc7 }, 31168c2ecf20Sopenharmony_ci { 0xeb, 0x10 }, 31178c2ecf20Sopenharmony_ci { 0xec, 0xf6 }, 31188c2ecf20Sopenharmony_ci }; 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_ci sd->stopped = 1; 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ci write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); 31238c2ecf20Sopenharmony_ci} 31248c2ecf20Sopenharmony_ci 31258c2ecf20Sopenharmony_ci/* set the mode */ 31268c2ecf20Sopenharmony_ci/* This function works for ov7660 only */ 31278c2ecf20Sopenharmony_cistatic void ov519_set_mode(struct sd *sd) 31288c2ecf20Sopenharmony_ci{ 31298c2ecf20Sopenharmony_ci static const struct ov_regvals bridge_ov7660[2][10] = { 31308c2ecf20Sopenharmony_ci {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00}, 31318c2ecf20Sopenharmony_ci {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, 31328c2ecf20Sopenharmony_ci {0x25, 0x01}, {0x26, 0x00}}, 31338c2ecf20Sopenharmony_ci {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00}, 31348c2ecf20Sopenharmony_ci {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, 31358c2ecf20Sopenharmony_ci {0x25, 0x03}, {0x26, 0x00}} 31368c2ecf20Sopenharmony_ci }; 31378c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals sensor_ov7660[2][3] = { 31388c2ecf20Sopenharmony_ci {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}}, 31398c2ecf20Sopenharmony_ci {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}} 31408c2ecf20Sopenharmony_ci }; 31418c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals sensor_ov7660_2[] = { 31428c2ecf20Sopenharmony_ci {OV7670_R17_HSTART, 0x13}, 31438c2ecf20Sopenharmony_ci {OV7670_R18_HSTOP, 0x01}, 31448c2ecf20Sopenharmony_ci {OV7670_R32_HREF, 0x92}, 31458c2ecf20Sopenharmony_ci {OV7670_R19_VSTART, 0x02}, 31468c2ecf20Sopenharmony_ci {OV7670_R1A_VSTOP, 0x7a}, 31478c2ecf20Sopenharmony_ci {OV7670_R03_VREF, 0x00}, 31488c2ecf20Sopenharmony_ci/* {0x33, 0x00}, */ 31498c2ecf20Sopenharmony_ci/* {0x34, 0x07}, */ 31508c2ecf20Sopenharmony_ci/* {0x36, 0x00}, */ 31518c2ecf20Sopenharmony_ci/* {0x6b, 0x0a}, */ 31528c2ecf20Sopenharmony_ci }; 31538c2ecf20Sopenharmony_ci 31548c2ecf20Sopenharmony_ci write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode], 31558c2ecf20Sopenharmony_ci ARRAY_SIZE(bridge_ov7660[0])); 31568c2ecf20Sopenharmony_ci write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode], 31578c2ecf20Sopenharmony_ci ARRAY_SIZE(sensor_ov7660[0])); 31588c2ecf20Sopenharmony_ci write_i2c_regvals(sd, sensor_ov7660_2, 31598c2ecf20Sopenharmony_ci ARRAY_SIZE(sensor_ov7660_2)); 31608c2ecf20Sopenharmony_ci} 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci/* set the frame rate */ 31638c2ecf20Sopenharmony_ci/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */ 31648c2ecf20Sopenharmony_cistatic void ov519_set_fr(struct sd *sd) 31658c2ecf20Sopenharmony_ci{ 31668c2ecf20Sopenharmony_ci int fr; 31678c2ecf20Sopenharmony_ci u8 clock; 31688c2ecf20Sopenharmony_ci /* frame rate table with indices: 31698c2ecf20Sopenharmony_ci * - mode = 0: 320x240, 1: 640x480 31708c2ecf20Sopenharmony_ci * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5 31718c2ecf20Sopenharmony_ci * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock) 31728c2ecf20Sopenharmony_ci */ 31738c2ecf20Sopenharmony_ci static const u8 fr_tb[2][6][3] = { 31748c2ecf20Sopenharmony_ci {{0x04, 0xff, 0x00}, 31758c2ecf20Sopenharmony_ci {0x04, 0x1f, 0x00}, 31768c2ecf20Sopenharmony_ci {0x04, 0x1b, 0x00}, 31778c2ecf20Sopenharmony_ci {0x04, 0x15, 0x00}, 31788c2ecf20Sopenharmony_ci {0x04, 0x09, 0x00}, 31798c2ecf20Sopenharmony_ci {0x04, 0x01, 0x00}}, 31808c2ecf20Sopenharmony_ci {{0x0c, 0xff, 0x00}, 31818c2ecf20Sopenharmony_ci {0x0c, 0x1f, 0x00}, 31828c2ecf20Sopenharmony_ci {0x0c, 0x1b, 0x00}, 31838c2ecf20Sopenharmony_ci {0x04, 0xff, 0x01}, 31848c2ecf20Sopenharmony_ci {0x04, 0x1f, 0x01}, 31858c2ecf20Sopenharmony_ci {0x04, 0x1b, 0x01}}, 31868c2ecf20Sopenharmony_ci }; 31878c2ecf20Sopenharmony_ci 31888c2ecf20Sopenharmony_ci if (frame_rate > 0) 31898c2ecf20Sopenharmony_ci sd->frame_rate = frame_rate; 31908c2ecf20Sopenharmony_ci if (sd->frame_rate >= 30) 31918c2ecf20Sopenharmony_ci fr = 0; 31928c2ecf20Sopenharmony_ci else if (sd->frame_rate >= 25) 31938c2ecf20Sopenharmony_ci fr = 1; 31948c2ecf20Sopenharmony_ci else if (sd->frame_rate >= 20) 31958c2ecf20Sopenharmony_ci fr = 2; 31968c2ecf20Sopenharmony_ci else if (sd->frame_rate >= 15) 31978c2ecf20Sopenharmony_ci fr = 3; 31988c2ecf20Sopenharmony_ci else if (sd->frame_rate >= 10) 31998c2ecf20Sopenharmony_ci fr = 4; 32008c2ecf20Sopenharmony_ci else 32018c2ecf20Sopenharmony_ci fr = 5; 32028c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]); 32038c2ecf20Sopenharmony_ci reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]); 32048c2ecf20Sopenharmony_ci clock = fr_tb[sd->gspca_dev.curr_mode][fr][2]; 32058c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV7660) 32068c2ecf20Sopenharmony_ci clock |= 0x80; /* enable double clock */ 32078c2ecf20Sopenharmony_ci ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); 32088c2ecf20Sopenharmony_ci} 32098c2ecf20Sopenharmony_ci 32108c2ecf20Sopenharmony_cistatic void setautogain(struct gspca_dev *gspca_dev, s32 val) 32118c2ecf20Sopenharmony_ci{ 32128c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 32138c2ecf20Sopenharmony_ci 32148c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, val ? 0x05 : 0x00, 0x05); 32158c2ecf20Sopenharmony_ci} 32168c2ecf20Sopenharmony_ci 32178c2ecf20Sopenharmony_ci/* this function is called at probe time */ 32188c2ecf20Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev, 32198c2ecf20Sopenharmony_ci const struct usb_device_id *id) 32208c2ecf20Sopenharmony_ci{ 32218c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 32228c2ecf20Sopenharmony_ci struct cam *cam = &gspca_dev->cam; 32238c2ecf20Sopenharmony_ci 32248c2ecf20Sopenharmony_ci sd->bridge = id->driver_info & BRIDGE_MASK; 32258c2ecf20Sopenharmony_ci sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0; 32268c2ecf20Sopenharmony_ci 32278c2ecf20Sopenharmony_ci switch (sd->bridge) { 32288c2ecf20Sopenharmony_ci case BRIDGE_OV511: 32298c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 32308c2ecf20Sopenharmony_ci cam->cam_mode = ov511_vga_mode; 32318c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov511_vga_mode); 32328c2ecf20Sopenharmony_ci break; 32338c2ecf20Sopenharmony_ci case BRIDGE_OV518: 32348c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 32358c2ecf20Sopenharmony_ci cam->cam_mode = ov518_vga_mode; 32368c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov518_vga_mode); 32378c2ecf20Sopenharmony_ci break; 32388c2ecf20Sopenharmony_ci case BRIDGE_OV519: 32398c2ecf20Sopenharmony_ci cam->cam_mode = ov519_vga_mode; 32408c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov519_vga_mode); 32418c2ecf20Sopenharmony_ci break; 32428c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 32438c2ecf20Sopenharmony_ci cam->cam_mode = ov519_vga_mode; 32448c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov519_vga_mode); 32458c2ecf20Sopenharmony_ci cam->bulk_size = OVFX2_BULK_SIZE; 32468c2ecf20Sopenharmony_ci cam->bulk_nurbs = MAX_NURBS; 32478c2ecf20Sopenharmony_ci cam->bulk = 1; 32488c2ecf20Sopenharmony_ci break; 32498c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 32508c2ecf20Sopenharmony_ci cam->cam_mode = w9968cf_vga_mode; 32518c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); 32528c2ecf20Sopenharmony_ci break; 32538c2ecf20Sopenharmony_ci } 32548c2ecf20Sopenharmony_ci 32558c2ecf20Sopenharmony_ci sd->frame_rate = 15; 32568c2ecf20Sopenharmony_ci 32578c2ecf20Sopenharmony_ci return 0; 32588c2ecf20Sopenharmony_ci} 32598c2ecf20Sopenharmony_ci 32608c2ecf20Sopenharmony_ci/* this function is called at probe and resume time */ 32618c2ecf20Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev) 32628c2ecf20Sopenharmony_ci{ 32638c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 32648c2ecf20Sopenharmony_ci struct cam *cam = &gspca_dev->cam; 32658c2ecf20Sopenharmony_ci 32668c2ecf20Sopenharmony_ci switch (sd->bridge) { 32678c2ecf20Sopenharmony_ci case BRIDGE_OV511: 32688c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 32698c2ecf20Sopenharmony_ci ov511_configure(gspca_dev); 32708c2ecf20Sopenharmony_ci break; 32718c2ecf20Sopenharmony_ci case BRIDGE_OV518: 32728c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 32738c2ecf20Sopenharmony_ci ov518_configure(gspca_dev); 32748c2ecf20Sopenharmony_ci break; 32758c2ecf20Sopenharmony_ci case BRIDGE_OV519: 32768c2ecf20Sopenharmony_ci ov519_configure(sd); 32778c2ecf20Sopenharmony_ci break; 32788c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 32798c2ecf20Sopenharmony_ci ovfx2_configure(sd); 32808c2ecf20Sopenharmony_ci break; 32818c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 32828c2ecf20Sopenharmony_ci w9968cf_configure(sd); 32838c2ecf20Sopenharmony_ci break; 32848c2ecf20Sopenharmony_ci } 32858c2ecf20Sopenharmony_ci 32868c2ecf20Sopenharmony_ci /* The OV519 must be more aggressive about sensor detection since 32878c2ecf20Sopenharmony_ci * I2C write will never fail if the sensor is not present. We have 32888c2ecf20Sopenharmony_ci * to try to initialize the sensor to detect its presence */ 32898c2ecf20Sopenharmony_ci sd->sensor = -1; 32908c2ecf20Sopenharmony_ci 32918c2ecf20Sopenharmony_ci /* Test for 76xx */ 32928c2ecf20Sopenharmony_ci if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { 32938c2ecf20Sopenharmony_ci ov7xx0_configure(sd); 32948c2ecf20Sopenharmony_ci 32958c2ecf20Sopenharmony_ci /* Test for 6xx0 */ 32968c2ecf20Sopenharmony_ci } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { 32978c2ecf20Sopenharmony_ci ov6xx0_configure(sd); 32988c2ecf20Sopenharmony_ci 32998c2ecf20Sopenharmony_ci /* Test for 8xx0 */ 33008c2ecf20Sopenharmony_ci } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { 33018c2ecf20Sopenharmony_ci ov8xx0_configure(sd); 33028c2ecf20Sopenharmony_ci 33038c2ecf20Sopenharmony_ci /* Test for 3xxx / 2xxx */ 33048c2ecf20Sopenharmony_ci } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { 33058c2ecf20Sopenharmony_ci ov_hires_configure(sd); 33068c2ecf20Sopenharmony_ci } else { 33078c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Can't determine sensor slave IDs\n"); 33088c2ecf20Sopenharmony_ci goto error; 33098c2ecf20Sopenharmony_ci } 33108c2ecf20Sopenharmony_ci 33118c2ecf20Sopenharmony_ci if (sd->sensor < 0) 33128c2ecf20Sopenharmony_ci goto error; 33138c2ecf20Sopenharmony_ci 33148c2ecf20Sopenharmony_ci ov51x_led_control(sd, 0); /* turn LED off */ 33158c2ecf20Sopenharmony_ci 33168c2ecf20Sopenharmony_ci switch (sd->bridge) { 33178c2ecf20Sopenharmony_ci case BRIDGE_OV511: 33188c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 33198c2ecf20Sopenharmony_ci if (sd->sif) { 33208c2ecf20Sopenharmony_ci cam->cam_mode = ov511_sif_mode; 33218c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov511_sif_mode); 33228c2ecf20Sopenharmony_ci } 33238c2ecf20Sopenharmony_ci break; 33248c2ecf20Sopenharmony_ci case BRIDGE_OV518: 33258c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 33268c2ecf20Sopenharmony_ci if (sd->sif) { 33278c2ecf20Sopenharmony_ci cam->cam_mode = ov518_sif_mode; 33288c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov518_sif_mode); 33298c2ecf20Sopenharmony_ci } 33308c2ecf20Sopenharmony_ci break; 33318c2ecf20Sopenharmony_ci case BRIDGE_OV519: 33328c2ecf20Sopenharmony_ci if (sd->sif) { 33338c2ecf20Sopenharmony_ci cam->cam_mode = ov519_sif_mode; 33348c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov519_sif_mode); 33358c2ecf20Sopenharmony_ci } 33368c2ecf20Sopenharmony_ci break; 33378c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 33388c2ecf20Sopenharmony_ci switch (sd->sensor) { 33398c2ecf20Sopenharmony_ci case SEN_OV2610: 33408c2ecf20Sopenharmony_ci case SEN_OV2610AE: 33418c2ecf20Sopenharmony_ci cam->cam_mode = ovfx2_ov2610_mode; 33428c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode); 33438c2ecf20Sopenharmony_ci break; 33448c2ecf20Sopenharmony_ci case SEN_OV3610: 33458c2ecf20Sopenharmony_ci cam->cam_mode = ovfx2_ov3610_mode; 33468c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode); 33478c2ecf20Sopenharmony_ci break; 33488c2ecf20Sopenharmony_ci case SEN_OV9600: 33498c2ecf20Sopenharmony_ci cam->cam_mode = ovfx2_ov9600_mode; 33508c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode); 33518c2ecf20Sopenharmony_ci break; 33528c2ecf20Sopenharmony_ci default: 33538c2ecf20Sopenharmony_ci if (sd->sif) { 33548c2ecf20Sopenharmony_ci cam->cam_mode = ov519_sif_mode; 33558c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(ov519_sif_mode); 33568c2ecf20Sopenharmony_ci } 33578c2ecf20Sopenharmony_ci break; 33588c2ecf20Sopenharmony_ci } 33598c2ecf20Sopenharmony_ci break; 33608c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 33618c2ecf20Sopenharmony_ci if (sd->sif) 33628c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1; 33638c2ecf20Sopenharmony_ci 33648c2ecf20Sopenharmony_ci /* w9968cf needs initialisation once the sensor is known */ 33658c2ecf20Sopenharmony_ci w9968cf_init(sd); 33668c2ecf20Sopenharmony_ci break; 33678c2ecf20Sopenharmony_ci } 33688c2ecf20Sopenharmony_ci 33698c2ecf20Sopenharmony_ci /* initialize the sensor */ 33708c2ecf20Sopenharmony_ci switch (sd->sensor) { 33718c2ecf20Sopenharmony_ci case SEN_OV2610: 33728c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610)); 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci /* Enable autogain, autoexpo, awb, bandfilter */ 33758c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x27, 0x27); 33768c2ecf20Sopenharmony_ci break; 33778c2ecf20Sopenharmony_ci case SEN_OV2610AE: 33788c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae)); 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_ci /* enable autoexpo */ 33818c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x05, 0x05); 33828c2ecf20Sopenharmony_ci break; 33838c2ecf20Sopenharmony_ci case SEN_OV3610: 33848c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b)); 33858c2ecf20Sopenharmony_ci 33868c2ecf20Sopenharmony_ci /* Enable autogain, autoexpo, awb, bandfilter */ 33878c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x27, 0x27); 33888c2ecf20Sopenharmony_ci break; 33898c2ecf20Sopenharmony_ci case SEN_OV6620: 33908c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)); 33918c2ecf20Sopenharmony_ci break; 33928c2ecf20Sopenharmony_ci case SEN_OV6630: 33938c2ecf20Sopenharmony_ci case SEN_OV66308AF: 33948c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)); 33958c2ecf20Sopenharmony_ci break; 33968c2ecf20Sopenharmony_ci default: 33978c2ecf20Sopenharmony_ci/* case SEN_OV7610: */ 33988c2ecf20Sopenharmony_ci/* case SEN_OV76BE: */ 33998c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)); 34008c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x0e, 0x00, 0x40); 34018c2ecf20Sopenharmony_ci break; 34028c2ecf20Sopenharmony_ci case SEN_OV7620: 34038c2ecf20Sopenharmony_ci case SEN_OV7620AE: 34048c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)); 34058c2ecf20Sopenharmony_ci break; 34068c2ecf20Sopenharmony_ci case SEN_OV7640: 34078c2ecf20Sopenharmony_ci case SEN_OV7648: 34088c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); 34098c2ecf20Sopenharmony_ci break; 34108c2ecf20Sopenharmony_ci case SEN_OV7660: 34118c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET); 34128c2ecf20Sopenharmony_ci msleep(14); 34138c2ecf20Sopenharmony_ci reg_w(sd, OV519_R57_SNAPSHOT, 0x23); 34148c2ecf20Sopenharmony_ci write_regvals(sd, init_519_ov7660, 34158c2ecf20Sopenharmony_ci ARRAY_SIZE(init_519_ov7660)); 34168c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660)); 34178c2ecf20Sopenharmony_ci sd->gspca_dev.curr_mode = 1; /* 640x480 */ 34188c2ecf20Sopenharmony_ci ov519_set_mode(sd); 34198c2ecf20Sopenharmony_ci ov519_set_fr(sd); 34208c2ecf20Sopenharmony_ci sd_reset_snapshot(gspca_dev); 34218c2ecf20Sopenharmony_ci ov51x_restart(sd); 34228c2ecf20Sopenharmony_ci ov51x_stop(sd); /* not in win traces */ 34238c2ecf20Sopenharmony_ci ov51x_led_control(sd, 0); 34248c2ecf20Sopenharmony_ci break; 34258c2ecf20Sopenharmony_ci case SEN_OV7670: 34268c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)); 34278c2ecf20Sopenharmony_ci break; 34288c2ecf20Sopenharmony_ci case SEN_OV8610: 34298c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)); 34308c2ecf20Sopenharmony_ci break; 34318c2ecf20Sopenharmony_ci case SEN_OV9600: 34328c2ecf20Sopenharmony_ci write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600)); 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci /* enable autoexpo */ 34358c2ecf20Sopenharmony_ci/* i2c_w_mask(sd, 0x13, 0x05, 0x05); */ 34368c2ecf20Sopenharmony_ci break; 34378c2ecf20Sopenharmony_ci } 34388c2ecf20Sopenharmony_ci return gspca_dev->usb_err; 34398c2ecf20Sopenharmony_cierror: 34408c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "OV519 Config failed\n"); 34418c2ecf20Sopenharmony_ci return -EINVAL; 34428c2ecf20Sopenharmony_ci} 34438c2ecf20Sopenharmony_ci 34448c2ecf20Sopenharmony_ci/* function called at start time before URB creation */ 34458c2ecf20Sopenharmony_cistatic int sd_isoc_init(struct gspca_dev *gspca_dev) 34468c2ecf20Sopenharmony_ci{ 34478c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 34488c2ecf20Sopenharmony_ci 34498c2ecf20Sopenharmony_ci switch (sd->bridge) { 34508c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 34518c2ecf20Sopenharmony_ci if (gspca_dev->pixfmt.width != 800) 34528c2ecf20Sopenharmony_ci gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE; 34538c2ecf20Sopenharmony_ci else 34548c2ecf20Sopenharmony_ci gspca_dev->cam.bulk_size = 7 * 4096; 34558c2ecf20Sopenharmony_ci break; 34568c2ecf20Sopenharmony_ci } 34578c2ecf20Sopenharmony_ci return 0; 34588c2ecf20Sopenharmony_ci} 34598c2ecf20Sopenharmony_ci 34608c2ecf20Sopenharmony_ci/* Set up the OV511/OV511+ with the given image parameters. 34618c2ecf20Sopenharmony_ci * 34628c2ecf20Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions) 34638c2ecf20Sopenharmony_ci */ 34648c2ecf20Sopenharmony_cistatic void ov511_mode_init_regs(struct sd *sd) 34658c2ecf20Sopenharmony_ci{ 34668c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 34678c2ecf20Sopenharmony_ci int hsegs, vsegs, packet_size, fps, needed; 34688c2ecf20Sopenharmony_ci int interlaced = 0; 34698c2ecf20Sopenharmony_ci struct usb_host_interface *alt; 34708c2ecf20Sopenharmony_ci struct usb_interface *intf; 34718c2ecf20Sopenharmony_ci 34728c2ecf20Sopenharmony_ci intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); 34738c2ecf20Sopenharmony_ci alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); 34748c2ecf20Sopenharmony_ci if (!alt) { 34758c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Couldn't get altsetting\n"); 34768c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = -EIO; 34778c2ecf20Sopenharmony_ci return; 34788c2ecf20Sopenharmony_ci } 34798c2ecf20Sopenharmony_ci 34808c2ecf20Sopenharmony_ci if (alt->desc.bNumEndpoints < 1) { 34818c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = -ENODEV; 34828c2ecf20Sopenharmony_ci return; 34838c2ecf20Sopenharmony_ci } 34848c2ecf20Sopenharmony_ci 34858c2ecf20Sopenharmony_ci packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); 34868c2ecf20Sopenharmony_ci reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); 34878c2ecf20Sopenharmony_ci 34888c2ecf20Sopenharmony_ci reg_w(sd, R511_CAM_UV_EN, 0x01); 34898c2ecf20Sopenharmony_ci reg_w(sd, R511_SNAP_UV_EN, 0x01); 34908c2ecf20Sopenharmony_ci reg_w(sd, R511_SNAP_OPTS, 0x03); 34918c2ecf20Sopenharmony_ci 34928c2ecf20Sopenharmony_ci /* Here I'm assuming that snapshot size == image size. 34938c2ecf20Sopenharmony_ci * I hope that's always true. --claudio 34948c2ecf20Sopenharmony_ci */ 34958c2ecf20Sopenharmony_ci hsegs = (sd->gspca_dev.pixfmt.width >> 3) - 1; 34968c2ecf20Sopenharmony_ci vsegs = (sd->gspca_dev.pixfmt.height >> 3) - 1; 34978c2ecf20Sopenharmony_ci 34988c2ecf20Sopenharmony_ci reg_w(sd, R511_CAM_PXCNT, hsegs); 34998c2ecf20Sopenharmony_ci reg_w(sd, R511_CAM_LNCNT, vsegs); 35008c2ecf20Sopenharmony_ci reg_w(sd, R511_CAM_PXDIV, 0x00); 35018c2ecf20Sopenharmony_ci reg_w(sd, R511_CAM_LNDIV, 0x00); 35028c2ecf20Sopenharmony_ci 35038c2ecf20Sopenharmony_ci /* YUV420, low pass filter on */ 35048c2ecf20Sopenharmony_ci reg_w(sd, R511_CAM_OPTS, 0x03); 35058c2ecf20Sopenharmony_ci 35068c2ecf20Sopenharmony_ci /* Snapshot additions */ 35078c2ecf20Sopenharmony_ci reg_w(sd, R511_SNAP_PXCNT, hsegs); 35088c2ecf20Sopenharmony_ci reg_w(sd, R511_SNAP_LNCNT, vsegs); 35098c2ecf20Sopenharmony_ci reg_w(sd, R511_SNAP_PXDIV, 0x00); 35108c2ecf20Sopenharmony_ci reg_w(sd, R511_SNAP_LNDIV, 0x00); 35118c2ecf20Sopenharmony_ci 35128c2ecf20Sopenharmony_ci /******** Set the framerate ********/ 35138c2ecf20Sopenharmony_ci if (frame_rate > 0) 35148c2ecf20Sopenharmony_ci sd->frame_rate = frame_rate; 35158c2ecf20Sopenharmony_ci 35168c2ecf20Sopenharmony_ci switch (sd->sensor) { 35178c2ecf20Sopenharmony_ci case SEN_OV6620: 35188c2ecf20Sopenharmony_ci /* No framerate control, doesn't like higher rates yet */ 35198c2ecf20Sopenharmony_ci sd->clockdiv = 3; 35208c2ecf20Sopenharmony_ci break; 35218c2ecf20Sopenharmony_ci 35228c2ecf20Sopenharmony_ci /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed 35238c2ecf20Sopenharmony_ci for more sensors we need to do this for them too */ 35248c2ecf20Sopenharmony_ci case SEN_OV7620: 35258c2ecf20Sopenharmony_ci case SEN_OV7620AE: 35268c2ecf20Sopenharmony_ci case SEN_OV7640: 35278c2ecf20Sopenharmony_ci case SEN_OV7648: 35288c2ecf20Sopenharmony_ci case SEN_OV76BE: 35298c2ecf20Sopenharmony_ci if (sd->gspca_dev.pixfmt.width == 320) 35308c2ecf20Sopenharmony_ci interlaced = 1; 35318c2ecf20Sopenharmony_ci fallthrough; 35328c2ecf20Sopenharmony_ci case SEN_OV6630: 35338c2ecf20Sopenharmony_ci case SEN_OV7610: 35348c2ecf20Sopenharmony_ci case SEN_OV7670: 35358c2ecf20Sopenharmony_ci switch (sd->frame_rate) { 35368c2ecf20Sopenharmony_ci case 30: 35378c2ecf20Sopenharmony_ci case 25: 35388c2ecf20Sopenharmony_ci /* Not enough bandwidth to do 640x480 @ 30 fps */ 35398c2ecf20Sopenharmony_ci if (sd->gspca_dev.pixfmt.width != 640) { 35408c2ecf20Sopenharmony_ci sd->clockdiv = 0; 35418c2ecf20Sopenharmony_ci break; 35428c2ecf20Sopenharmony_ci } 35438c2ecf20Sopenharmony_ci /* For 640x480 case */ 35448c2ecf20Sopenharmony_ci fallthrough; 35458c2ecf20Sopenharmony_ci default: 35468c2ecf20Sopenharmony_ci/* case 20: */ 35478c2ecf20Sopenharmony_ci/* case 15: */ 35488c2ecf20Sopenharmony_ci sd->clockdiv = 1; 35498c2ecf20Sopenharmony_ci break; 35508c2ecf20Sopenharmony_ci case 10: 35518c2ecf20Sopenharmony_ci sd->clockdiv = 2; 35528c2ecf20Sopenharmony_ci break; 35538c2ecf20Sopenharmony_ci case 5: 35548c2ecf20Sopenharmony_ci sd->clockdiv = 5; 35558c2ecf20Sopenharmony_ci break; 35568c2ecf20Sopenharmony_ci } 35578c2ecf20Sopenharmony_ci if (interlaced) { 35588c2ecf20Sopenharmony_ci sd->clockdiv = (sd->clockdiv + 1) * 2 - 1; 35598c2ecf20Sopenharmony_ci /* Higher then 10 does not work */ 35608c2ecf20Sopenharmony_ci if (sd->clockdiv > 10) 35618c2ecf20Sopenharmony_ci sd->clockdiv = 10; 35628c2ecf20Sopenharmony_ci } 35638c2ecf20Sopenharmony_ci break; 35648c2ecf20Sopenharmony_ci 35658c2ecf20Sopenharmony_ci case SEN_OV8610: 35668c2ecf20Sopenharmony_ci /* No framerate control ?? */ 35678c2ecf20Sopenharmony_ci sd->clockdiv = 0; 35688c2ecf20Sopenharmony_ci break; 35698c2ecf20Sopenharmony_ci } 35708c2ecf20Sopenharmony_ci 35718c2ecf20Sopenharmony_ci /* Check if we have enough bandwidth to disable compression */ 35728c2ecf20Sopenharmony_ci fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1; 35738c2ecf20Sopenharmony_ci needed = fps * sd->gspca_dev.pixfmt.width * 35748c2ecf20Sopenharmony_ci sd->gspca_dev.pixfmt.height * 3 / 2; 35758c2ecf20Sopenharmony_ci /* 1000 isoc packets/sec */ 35768c2ecf20Sopenharmony_ci if (needed > 1000 * packet_size) { 35778c2ecf20Sopenharmony_ci /* Enable Y and UV quantization and compression */ 35788c2ecf20Sopenharmony_ci reg_w(sd, R511_COMP_EN, 0x07); 35798c2ecf20Sopenharmony_ci reg_w(sd, R511_COMP_LUT_EN, 0x03); 35808c2ecf20Sopenharmony_ci } else { 35818c2ecf20Sopenharmony_ci reg_w(sd, R511_COMP_EN, 0x06); 35828c2ecf20Sopenharmony_ci reg_w(sd, R511_COMP_LUT_EN, 0x00); 35838c2ecf20Sopenharmony_ci } 35848c2ecf20Sopenharmony_ci 35858c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); 35868c2ecf20Sopenharmony_ci reg_w(sd, R51x_SYS_RESET, 0); 35878c2ecf20Sopenharmony_ci} 35888c2ecf20Sopenharmony_ci 35898c2ecf20Sopenharmony_ci/* Sets up the OV518/OV518+ with the given image parameters 35908c2ecf20Sopenharmony_ci * 35918c2ecf20Sopenharmony_ci * OV518 needs a completely different approach, until we can figure out what 35928c2ecf20Sopenharmony_ci * the individual registers do. Also, only 15 FPS is supported now. 35938c2ecf20Sopenharmony_ci * 35948c2ecf20Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions) 35958c2ecf20Sopenharmony_ci */ 35968c2ecf20Sopenharmony_cistatic void ov518_mode_init_regs(struct sd *sd) 35978c2ecf20Sopenharmony_ci{ 35988c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 35998c2ecf20Sopenharmony_ci int hsegs, vsegs, packet_size; 36008c2ecf20Sopenharmony_ci struct usb_host_interface *alt; 36018c2ecf20Sopenharmony_ci struct usb_interface *intf; 36028c2ecf20Sopenharmony_ci 36038c2ecf20Sopenharmony_ci intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); 36048c2ecf20Sopenharmony_ci alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); 36058c2ecf20Sopenharmony_ci if (!alt) { 36068c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Couldn't get altsetting\n"); 36078c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = -EIO; 36088c2ecf20Sopenharmony_ci return; 36098c2ecf20Sopenharmony_ci } 36108c2ecf20Sopenharmony_ci 36118c2ecf20Sopenharmony_ci if (alt->desc.bNumEndpoints < 1) { 36128c2ecf20Sopenharmony_ci sd->gspca_dev.usb_err = -ENODEV; 36138c2ecf20Sopenharmony_ci return; 36148c2ecf20Sopenharmony_ci } 36158c2ecf20Sopenharmony_ci 36168c2ecf20Sopenharmony_ci packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); 36178c2ecf20Sopenharmony_ci ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); 36188c2ecf20Sopenharmony_ci 36198c2ecf20Sopenharmony_ci /******** Set the mode ********/ 36208c2ecf20Sopenharmony_ci reg_w(sd, 0x2b, 0); 36218c2ecf20Sopenharmony_ci reg_w(sd, 0x2c, 0); 36228c2ecf20Sopenharmony_ci reg_w(sd, 0x2d, 0); 36238c2ecf20Sopenharmony_ci reg_w(sd, 0x2e, 0); 36248c2ecf20Sopenharmony_ci reg_w(sd, 0x3b, 0); 36258c2ecf20Sopenharmony_ci reg_w(sd, 0x3c, 0); 36268c2ecf20Sopenharmony_ci reg_w(sd, 0x3d, 0); 36278c2ecf20Sopenharmony_ci reg_w(sd, 0x3e, 0); 36288c2ecf20Sopenharmony_ci 36298c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_OV518) { 36308c2ecf20Sopenharmony_ci /* Set 8-bit (YVYU) input format */ 36318c2ecf20Sopenharmony_ci reg_w_mask(sd, 0x20, 0x08, 0x08); 36328c2ecf20Sopenharmony_ci 36338c2ecf20Sopenharmony_ci /* Set 12-bit (4:2:0) output format */ 36348c2ecf20Sopenharmony_ci reg_w_mask(sd, 0x28, 0x80, 0xf0); 36358c2ecf20Sopenharmony_ci reg_w_mask(sd, 0x38, 0x80, 0xf0); 36368c2ecf20Sopenharmony_ci } else { 36378c2ecf20Sopenharmony_ci reg_w(sd, 0x28, 0x80); 36388c2ecf20Sopenharmony_ci reg_w(sd, 0x38, 0x80); 36398c2ecf20Sopenharmony_ci } 36408c2ecf20Sopenharmony_ci 36418c2ecf20Sopenharmony_ci hsegs = sd->gspca_dev.pixfmt.width / 16; 36428c2ecf20Sopenharmony_ci vsegs = sd->gspca_dev.pixfmt.height / 4; 36438c2ecf20Sopenharmony_ci 36448c2ecf20Sopenharmony_ci reg_w(sd, 0x29, hsegs); 36458c2ecf20Sopenharmony_ci reg_w(sd, 0x2a, vsegs); 36468c2ecf20Sopenharmony_ci 36478c2ecf20Sopenharmony_ci reg_w(sd, 0x39, hsegs); 36488c2ecf20Sopenharmony_ci reg_w(sd, 0x3a, vsegs); 36498c2ecf20Sopenharmony_ci 36508c2ecf20Sopenharmony_ci /* Windows driver does this here; who knows why */ 36518c2ecf20Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 36528c2ecf20Sopenharmony_ci 36538c2ecf20Sopenharmony_ci /******** Set the framerate ********/ 36548c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_OV518PLUS && sd->revision == 0 && 36558c2ecf20Sopenharmony_ci sd->sensor == SEN_OV7620AE) 36568c2ecf20Sopenharmony_ci sd->clockdiv = 0; 36578c2ecf20Sopenharmony_ci else 36588c2ecf20Sopenharmony_ci sd->clockdiv = 1; 36598c2ecf20Sopenharmony_ci 36608c2ecf20Sopenharmony_ci /* Mode independent, but framerate dependent, regs */ 36618c2ecf20Sopenharmony_ci /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ 36628c2ecf20Sopenharmony_ci reg_w(sd, 0x51, 0x04); 36638c2ecf20Sopenharmony_ci reg_w(sd, 0x22, 0x18); 36648c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0xff); 36658c2ecf20Sopenharmony_ci 36668c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_OV518PLUS) { 36678c2ecf20Sopenharmony_ci switch (sd->sensor) { 36688c2ecf20Sopenharmony_ci case SEN_OV7620AE: 36698c2ecf20Sopenharmony_ci /* 36708c2ecf20Sopenharmony_ci * HdG: 640x480 needs special handling on device 36718c2ecf20Sopenharmony_ci * revision 2, we check for device revision > 0 to 36728c2ecf20Sopenharmony_ci * avoid regressions, as we don't know the correct 36738c2ecf20Sopenharmony_ci * thing todo for revision 1. 36748c2ecf20Sopenharmony_ci * 36758c2ecf20Sopenharmony_ci * Also this likely means we don't need to 36768c2ecf20Sopenharmony_ci * differentiate between the OV7620 and OV7620AE, 36778c2ecf20Sopenharmony_ci * earlier testing hitting this same problem likely 36788c2ecf20Sopenharmony_ci * happened to be with revision < 2 cams using an 36798c2ecf20Sopenharmony_ci * OV7620 and revision 2 cams using an OV7620AE. 36808c2ecf20Sopenharmony_ci */ 36818c2ecf20Sopenharmony_ci if (sd->revision > 0 && 36828c2ecf20Sopenharmony_ci sd->gspca_dev.pixfmt.width == 640) { 36838c2ecf20Sopenharmony_ci reg_w(sd, 0x20, 0x60); 36848c2ecf20Sopenharmony_ci reg_w(sd, 0x21, 0x1f); 36858c2ecf20Sopenharmony_ci } else { 36868c2ecf20Sopenharmony_ci reg_w(sd, 0x20, 0x00); 36878c2ecf20Sopenharmony_ci reg_w(sd, 0x21, 0x19); 36888c2ecf20Sopenharmony_ci } 36898c2ecf20Sopenharmony_ci break; 36908c2ecf20Sopenharmony_ci case SEN_OV7620: 36918c2ecf20Sopenharmony_ci reg_w(sd, 0x20, 0x00); 36928c2ecf20Sopenharmony_ci reg_w(sd, 0x21, 0x19); 36938c2ecf20Sopenharmony_ci break; 36948c2ecf20Sopenharmony_ci default: 36958c2ecf20Sopenharmony_ci reg_w(sd, 0x21, 0x19); 36968c2ecf20Sopenharmony_ci } 36978c2ecf20Sopenharmony_ci } else 36988c2ecf20Sopenharmony_ci reg_w(sd, 0x71, 0x17); /* Compression-related? */ 36998c2ecf20Sopenharmony_ci 37008c2ecf20Sopenharmony_ci /* FIXME: Sensor-specific */ 37018c2ecf20Sopenharmony_ci /* Bit 5 is what matters here. Of course, it is "reserved" */ 37028c2ecf20Sopenharmony_ci i2c_w(sd, 0x54, 0x23); 37038c2ecf20Sopenharmony_ci 37048c2ecf20Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 37058c2ecf20Sopenharmony_ci 37068c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_OV518PLUS) { 37078c2ecf20Sopenharmony_ci reg_w(sd, 0x24, 0x94); 37088c2ecf20Sopenharmony_ci reg_w(sd, 0x25, 0x90); 37098c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ 37108c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */ 37118c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */ 37128c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */ 37138c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */ 37148c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */ 37158c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */ 37168c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */ 37178c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */ 37188c2ecf20Sopenharmony_ci } else { 37198c2ecf20Sopenharmony_ci reg_w(sd, 0x24, 0x9f); 37208c2ecf20Sopenharmony_ci reg_w(sd, 0x25, 0x90); 37218c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ 37228c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */ 37238c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */ 37248c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */ 37258c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */ 37268c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */ 37278c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */ 37288c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */ 37298c2ecf20Sopenharmony_ci ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */ 37308c2ecf20Sopenharmony_ci } 37318c2ecf20Sopenharmony_ci 37328c2ecf20Sopenharmony_ci reg_w(sd, 0x2f, 0x80); 37338c2ecf20Sopenharmony_ci} 37348c2ecf20Sopenharmony_ci 37358c2ecf20Sopenharmony_ci/* Sets up the OV519 with the given image parameters 37368c2ecf20Sopenharmony_ci * 37378c2ecf20Sopenharmony_ci * OV519 needs a completely different approach, until we can figure out what 37388c2ecf20Sopenharmony_ci * the individual registers do. 37398c2ecf20Sopenharmony_ci * 37408c2ecf20Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions) 37418c2ecf20Sopenharmony_ci */ 37428c2ecf20Sopenharmony_cistatic void ov519_mode_init_regs(struct sd *sd) 37438c2ecf20Sopenharmony_ci{ 37448c2ecf20Sopenharmony_ci static const struct ov_regvals mode_init_519_ov7670[] = { 37458c2ecf20Sopenharmony_ci { 0x5d, 0x03 }, /* Turn off suspend mode */ 37468c2ecf20Sopenharmony_ci { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ 37478c2ecf20Sopenharmony_ci { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ 37488c2ecf20Sopenharmony_ci { 0xa2, 0x20 }, /* a2-a5 are undocumented */ 37498c2ecf20Sopenharmony_ci { 0xa3, 0x18 }, 37508c2ecf20Sopenharmony_ci { 0xa4, 0x04 }, 37518c2ecf20Sopenharmony_ci { 0xa5, 0x28 }, 37528c2ecf20Sopenharmony_ci { 0x37, 0x00 }, /* SetUsbInit */ 37538c2ecf20Sopenharmony_ci { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ 37548c2ecf20Sopenharmony_ci /* Enable both fields, YUV Input, disable defect comp (why?) */ 37558c2ecf20Sopenharmony_ci { 0x20, 0x0c }, 37568c2ecf20Sopenharmony_ci { 0x21, 0x38 }, 37578c2ecf20Sopenharmony_ci { 0x22, 0x1d }, 37588c2ecf20Sopenharmony_ci { 0x17, 0x50 }, /* undocumented */ 37598c2ecf20Sopenharmony_ci { 0x37, 0x00 }, /* undocumented */ 37608c2ecf20Sopenharmony_ci { 0x40, 0xff }, /* I2C timeout counter */ 37618c2ecf20Sopenharmony_ci { 0x46, 0x00 }, /* I2C clock prescaler */ 37628c2ecf20Sopenharmony_ci { 0x59, 0x04 }, /* new from windrv 090403 */ 37638c2ecf20Sopenharmony_ci { 0xff, 0x00 }, /* undocumented */ 37648c2ecf20Sopenharmony_ci /* windows reads 0x55 at this point, why? */ 37658c2ecf20Sopenharmony_ci }; 37668c2ecf20Sopenharmony_ci 37678c2ecf20Sopenharmony_ci static const struct ov_regvals mode_init_519[] = { 37688c2ecf20Sopenharmony_ci { 0x5d, 0x03 }, /* Turn off suspend mode */ 37698c2ecf20Sopenharmony_ci { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ 37708c2ecf20Sopenharmony_ci { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ 37718c2ecf20Sopenharmony_ci { 0xa2, 0x20 }, /* a2-a5 are undocumented */ 37728c2ecf20Sopenharmony_ci { 0xa3, 0x18 }, 37738c2ecf20Sopenharmony_ci { 0xa4, 0x04 }, 37748c2ecf20Sopenharmony_ci { 0xa5, 0x28 }, 37758c2ecf20Sopenharmony_ci { 0x37, 0x00 }, /* SetUsbInit */ 37768c2ecf20Sopenharmony_ci { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ 37778c2ecf20Sopenharmony_ci /* Enable both fields, YUV Input, disable defect comp (why?) */ 37788c2ecf20Sopenharmony_ci { 0x22, 0x1d }, 37798c2ecf20Sopenharmony_ci { 0x17, 0x50 }, /* undocumented */ 37808c2ecf20Sopenharmony_ci { 0x37, 0x00 }, /* undocumented */ 37818c2ecf20Sopenharmony_ci { 0x40, 0xff }, /* I2C timeout counter */ 37828c2ecf20Sopenharmony_ci { 0x46, 0x00 }, /* I2C clock prescaler */ 37838c2ecf20Sopenharmony_ci { 0x59, 0x04 }, /* new from windrv 090403 */ 37848c2ecf20Sopenharmony_ci { 0xff, 0x00 }, /* undocumented */ 37858c2ecf20Sopenharmony_ci /* windows reads 0x55 at this point, why? */ 37868c2ecf20Sopenharmony_ci }; 37878c2ecf20Sopenharmony_ci 37888c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 37898c2ecf20Sopenharmony_ci 37908c2ecf20Sopenharmony_ci /******** Set the mode ********/ 37918c2ecf20Sopenharmony_ci switch (sd->sensor) { 37928c2ecf20Sopenharmony_ci default: 37938c2ecf20Sopenharmony_ci write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); 37948c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV7640 || 37958c2ecf20Sopenharmony_ci sd->sensor == SEN_OV7648) { 37968c2ecf20Sopenharmony_ci /* Select 8-bit input mode */ 37978c2ecf20Sopenharmony_ci reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); 37988c2ecf20Sopenharmony_ci } 37998c2ecf20Sopenharmony_ci break; 38008c2ecf20Sopenharmony_ci case SEN_OV7660: 38018c2ecf20Sopenharmony_ci return; /* done by ov519_set_mode/fr() */ 38028c2ecf20Sopenharmony_ci case SEN_OV7670: 38038c2ecf20Sopenharmony_ci write_regvals(sd, mode_init_519_ov7670, 38048c2ecf20Sopenharmony_ci ARRAY_SIZE(mode_init_519_ov7670)); 38058c2ecf20Sopenharmony_ci break; 38068c2ecf20Sopenharmony_ci } 38078c2ecf20Sopenharmony_ci 38088c2ecf20Sopenharmony_ci reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.pixfmt.width >> 4); 38098c2ecf20Sopenharmony_ci reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.pixfmt.height >> 3); 38108c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV7670 && 38118c2ecf20Sopenharmony_ci sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) 38128c2ecf20Sopenharmony_ci reg_w(sd, OV519_R12_X_OFFSETL, 0x04); 38138c2ecf20Sopenharmony_ci else if (sd->sensor == SEN_OV7648 && 38148c2ecf20Sopenharmony_ci sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) 38158c2ecf20Sopenharmony_ci reg_w(sd, OV519_R12_X_OFFSETL, 0x01); 38168c2ecf20Sopenharmony_ci else 38178c2ecf20Sopenharmony_ci reg_w(sd, OV519_R12_X_OFFSETL, 0x00); 38188c2ecf20Sopenharmony_ci reg_w(sd, OV519_R13_X_OFFSETH, 0x00); 38198c2ecf20Sopenharmony_ci reg_w(sd, OV519_R14_Y_OFFSETL, 0x00); 38208c2ecf20Sopenharmony_ci reg_w(sd, OV519_R15_Y_OFFSETH, 0x00); 38218c2ecf20Sopenharmony_ci reg_w(sd, OV519_R16_DIVIDER, 0x00); 38228c2ecf20Sopenharmony_ci reg_w(sd, OV519_R25_FORMAT, 0x03); /* YUV422 */ 38238c2ecf20Sopenharmony_ci reg_w(sd, 0x26, 0x00); /* Undocumented */ 38248c2ecf20Sopenharmony_ci 38258c2ecf20Sopenharmony_ci /******** Set the framerate ********/ 38268c2ecf20Sopenharmony_ci if (frame_rate > 0) 38278c2ecf20Sopenharmony_ci sd->frame_rate = frame_rate; 38288c2ecf20Sopenharmony_ci 38298c2ecf20Sopenharmony_ci/* FIXME: These are only valid at the max resolution. */ 38308c2ecf20Sopenharmony_ci sd->clockdiv = 0; 38318c2ecf20Sopenharmony_ci switch (sd->sensor) { 38328c2ecf20Sopenharmony_ci case SEN_OV7640: 38338c2ecf20Sopenharmony_ci case SEN_OV7648: 38348c2ecf20Sopenharmony_ci switch (sd->frame_rate) { 38358c2ecf20Sopenharmony_ci default: 38368c2ecf20Sopenharmony_ci/* case 30: */ 38378c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x0c); 38388c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0xff); 38398c2ecf20Sopenharmony_ci break; 38408c2ecf20Sopenharmony_ci case 25: 38418c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x0c); 38428c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0x1f); 38438c2ecf20Sopenharmony_ci break; 38448c2ecf20Sopenharmony_ci case 20: 38458c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x0c); 38468c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0x1b); 38478c2ecf20Sopenharmony_ci break; 38488c2ecf20Sopenharmony_ci case 15: 38498c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x04); 38508c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0xff); 38518c2ecf20Sopenharmony_ci sd->clockdiv = 1; 38528c2ecf20Sopenharmony_ci break; 38538c2ecf20Sopenharmony_ci case 10: 38548c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x04); 38558c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0x1f); 38568c2ecf20Sopenharmony_ci sd->clockdiv = 1; 38578c2ecf20Sopenharmony_ci break; 38588c2ecf20Sopenharmony_ci case 5: 38598c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x04); 38608c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0x1b); 38618c2ecf20Sopenharmony_ci sd->clockdiv = 1; 38628c2ecf20Sopenharmony_ci break; 38638c2ecf20Sopenharmony_ci } 38648c2ecf20Sopenharmony_ci break; 38658c2ecf20Sopenharmony_ci case SEN_OV8610: 38668c2ecf20Sopenharmony_ci switch (sd->frame_rate) { 38678c2ecf20Sopenharmony_ci default: /* 15 fps */ 38688c2ecf20Sopenharmony_ci/* case 15: */ 38698c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x06); 38708c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0xff); 38718c2ecf20Sopenharmony_ci break; 38728c2ecf20Sopenharmony_ci case 10: 38738c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x06); 38748c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0x1f); 38758c2ecf20Sopenharmony_ci break; 38768c2ecf20Sopenharmony_ci case 5: 38778c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x06); 38788c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0x1b); 38798c2ecf20Sopenharmony_ci break; 38808c2ecf20Sopenharmony_ci } 38818c2ecf20Sopenharmony_ci break; 38828c2ecf20Sopenharmony_ci case SEN_OV7670: /* guesses, based on 7640 */ 38838c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Setting framerate to %d fps\n", 38848c2ecf20Sopenharmony_ci (sd->frame_rate == 0) ? 15 : sd->frame_rate); 38858c2ecf20Sopenharmony_ci reg_w(sd, 0xa4, 0x10); 38868c2ecf20Sopenharmony_ci switch (sd->frame_rate) { 38878c2ecf20Sopenharmony_ci case 30: 38888c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0xff); 38898c2ecf20Sopenharmony_ci break; 38908c2ecf20Sopenharmony_ci case 20: 38918c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0x1b); 38928c2ecf20Sopenharmony_ci break; 38938c2ecf20Sopenharmony_ci default: 38948c2ecf20Sopenharmony_ci/* case 15: */ 38958c2ecf20Sopenharmony_ci reg_w(sd, 0x23, 0xff); 38968c2ecf20Sopenharmony_ci sd->clockdiv = 1; 38978c2ecf20Sopenharmony_ci break; 38988c2ecf20Sopenharmony_ci } 38998c2ecf20Sopenharmony_ci break; 39008c2ecf20Sopenharmony_ci } 39018c2ecf20Sopenharmony_ci} 39028c2ecf20Sopenharmony_ci 39038c2ecf20Sopenharmony_cistatic void mode_init_ov_sensor_regs(struct sd *sd) 39048c2ecf20Sopenharmony_ci{ 39058c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 39068c2ecf20Sopenharmony_ci int qvga, xstart, xend, ystart, yend; 39078c2ecf20Sopenharmony_ci u8 v; 39088c2ecf20Sopenharmony_ci 39098c2ecf20Sopenharmony_ci qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; 39108c2ecf20Sopenharmony_ci 39118c2ecf20Sopenharmony_ci /******** Mode (VGA/QVGA) and sensor specific regs ********/ 39128c2ecf20Sopenharmony_ci switch (sd->sensor) { 39138c2ecf20Sopenharmony_ci case SEN_OV2610: 39148c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 39158c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); 39168c2ecf20Sopenharmony_ci i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); 39178c2ecf20Sopenharmony_ci i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); 39188c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); 39198c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); 39208c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); 39218c2ecf20Sopenharmony_ci return; 39228c2ecf20Sopenharmony_ci case SEN_OV2610AE: { 39238c2ecf20Sopenharmony_ci u8 v; 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_ci /* frame rates: 39268c2ecf20Sopenharmony_ci * 10fps / 5 fps for 1600x1200 39278c2ecf20Sopenharmony_ci * 40fps / 20fps for 800x600 39288c2ecf20Sopenharmony_ci */ 39298c2ecf20Sopenharmony_ci v = 80; 39308c2ecf20Sopenharmony_ci if (qvga) { 39318c2ecf20Sopenharmony_ci if (sd->frame_rate < 25) 39328c2ecf20Sopenharmony_ci v = 0x81; 39338c2ecf20Sopenharmony_ci } else { 39348c2ecf20Sopenharmony_ci if (sd->frame_rate < 10) 39358c2ecf20Sopenharmony_ci v = 0x81; 39368c2ecf20Sopenharmony_ci } 39378c2ecf20Sopenharmony_ci i2c_w(sd, 0x11, v); 39388c2ecf20Sopenharmony_ci i2c_w(sd, 0x12, qvga ? 0x60 : 0x20); 39398c2ecf20Sopenharmony_ci return; 39408c2ecf20Sopenharmony_ci } 39418c2ecf20Sopenharmony_ci case SEN_OV3610: 39428c2ecf20Sopenharmony_ci if (qvga) { 39438c2ecf20Sopenharmony_ci xstart = (1040 - gspca_dev->pixfmt.width) / 2 + 39448c2ecf20Sopenharmony_ci (0x1f << 4); 39458c2ecf20Sopenharmony_ci ystart = (776 - gspca_dev->pixfmt.height) / 2; 39468c2ecf20Sopenharmony_ci } else { 39478c2ecf20Sopenharmony_ci xstart = (2076 - gspca_dev->pixfmt.width) / 2 + 39488c2ecf20Sopenharmony_ci (0x10 << 4); 39498c2ecf20Sopenharmony_ci ystart = (1544 - gspca_dev->pixfmt.height) / 2; 39508c2ecf20Sopenharmony_ci } 39518c2ecf20Sopenharmony_ci xend = xstart + gspca_dev->pixfmt.width; 39528c2ecf20Sopenharmony_ci yend = ystart + gspca_dev->pixfmt.height; 39538c2ecf20Sopenharmony_ci /* Writing to the COMH register resets the other windowing regs 39548c2ecf20Sopenharmony_ci to their default values, so we must do this first. */ 39558c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0); 39568c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x32, 39578c2ecf20Sopenharmony_ci (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7), 39588c2ecf20Sopenharmony_ci 0x3f); 39598c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x03, 39608c2ecf20Sopenharmony_ci (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3), 39618c2ecf20Sopenharmony_ci 0x0f); 39628c2ecf20Sopenharmony_ci i2c_w(sd, 0x17, xstart >> 4); 39638c2ecf20Sopenharmony_ci i2c_w(sd, 0x18, xend >> 4); 39648c2ecf20Sopenharmony_ci i2c_w(sd, 0x19, ystart >> 3); 39658c2ecf20Sopenharmony_ci i2c_w(sd, 0x1a, yend >> 3); 39668c2ecf20Sopenharmony_ci return; 39678c2ecf20Sopenharmony_ci case SEN_OV8610: 39688c2ecf20Sopenharmony_ci /* For OV8610 qvga means qsvga */ 39698c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); 39708c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 39718c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 39728c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */ 39738c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */ 39748c2ecf20Sopenharmony_ci break; 39758c2ecf20Sopenharmony_ci case SEN_OV7610: 39768c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 39778c2ecf20Sopenharmony_ci i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); 39788c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 39798c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 39808c2ecf20Sopenharmony_ci break; 39818c2ecf20Sopenharmony_ci case SEN_OV7620: 39828c2ecf20Sopenharmony_ci case SEN_OV7620AE: 39838c2ecf20Sopenharmony_ci case SEN_OV76BE: 39848c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 39858c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); 39868c2ecf20Sopenharmony_ci i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); 39878c2ecf20Sopenharmony_ci i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); 39888c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); 39898c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); 39908c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); 39918c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 39928c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 39938c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV76BE) 39948c2ecf20Sopenharmony_ci i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); 39958c2ecf20Sopenharmony_ci break; 39968c2ecf20Sopenharmony_ci case SEN_OV7640: 39978c2ecf20Sopenharmony_ci case SEN_OV7648: 39988c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 39998c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); 40008c2ecf20Sopenharmony_ci /* Setting this undocumented bit in qvga mode removes a very 40018c2ecf20Sopenharmony_ci annoying vertical shaking of the image */ 40028c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); 40038c2ecf20Sopenharmony_ci /* Unknown */ 40048c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); 40058c2ecf20Sopenharmony_ci /* Allow higher automatic gain (to allow higher framerates) */ 40068c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); 40078c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ 40088c2ecf20Sopenharmony_ci break; 40098c2ecf20Sopenharmony_ci case SEN_OV7670: 40108c2ecf20Sopenharmony_ci /* set COM7_FMT_VGA or COM7_FMT_QVGA 40118c2ecf20Sopenharmony_ci * do we need to set anything else? 40128c2ecf20Sopenharmony_ci * HSTART etc are set in set_ov_sensor_window itself */ 40138c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R12_COM7, 40148c2ecf20Sopenharmony_ci qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, 40158c2ecf20Sopenharmony_ci OV7670_COM7_FMT_MASK); 40168c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 40178c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB, 40188c2ecf20Sopenharmony_ci OV7670_COM8_AWB); 40198c2ecf20Sopenharmony_ci if (qvga) { /* QVGA from ov7670.c by 40208c2ecf20Sopenharmony_ci * Jonathan Corbet */ 40218c2ecf20Sopenharmony_ci xstart = 164; 40228c2ecf20Sopenharmony_ci xend = 28; 40238c2ecf20Sopenharmony_ci ystart = 14; 40248c2ecf20Sopenharmony_ci yend = 494; 40258c2ecf20Sopenharmony_ci } else { /* VGA */ 40268c2ecf20Sopenharmony_ci xstart = 158; 40278c2ecf20Sopenharmony_ci xend = 14; 40288c2ecf20Sopenharmony_ci ystart = 10; 40298c2ecf20Sopenharmony_ci yend = 490; 40308c2ecf20Sopenharmony_ci } 40318c2ecf20Sopenharmony_ci /* OV7670 hardware window registers are split across 40328c2ecf20Sopenharmony_ci * multiple locations */ 40338c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R17_HSTART, xstart >> 3); 40348c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R18_HSTOP, xend >> 3); 40358c2ecf20Sopenharmony_ci v = i2c_r(sd, OV7670_R32_HREF); 40368c2ecf20Sopenharmony_ci v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); 40378c2ecf20Sopenharmony_ci msleep(10); /* need to sleep between read and write to 40388c2ecf20Sopenharmony_ci * same reg! */ 40398c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R32_HREF, v); 40408c2ecf20Sopenharmony_ci 40418c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R19_VSTART, ystart >> 2); 40428c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2); 40438c2ecf20Sopenharmony_ci v = i2c_r(sd, OV7670_R03_VREF); 40448c2ecf20Sopenharmony_ci v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); 40458c2ecf20Sopenharmony_ci msleep(10); /* need to sleep between read and write to 40468c2ecf20Sopenharmony_ci * same reg! */ 40478c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R03_VREF, v); 40488c2ecf20Sopenharmony_ci break; 40498c2ecf20Sopenharmony_ci case SEN_OV6620: 40508c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 40518c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ 40528c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 40538c2ecf20Sopenharmony_ci break; 40548c2ecf20Sopenharmony_ci case SEN_OV6630: 40558c2ecf20Sopenharmony_ci case SEN_OV66308AF: 40568c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); 40578c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ 40588c2ecf20Sopenharmony_ci break; 40598c2ecf20Sopenharmony_ci case SEN_OV9600: { 40608c2ecf20Sopenharmony_ci const struct ov_i2c_regvals *vals; 40618c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals sxga_15[] = { 40628c2ecf20Sopenharmony_ci {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75} 40638c2ecf20Sopenharmony_ci }; 40648c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals sxga_7_5[] = { 40658c2ecf20Sopenharmony_ci {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75} 40668c2ecf20Sopenharmony_ci }; 40678c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals vga_30[] = { 40688c2ecf20Sopenharmony_ci {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60} 40698c2ecf20Sopenharmony_ci }; 40708c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals vga_15[] = { 40718c2ecf20Sopenharmony_ci {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70} 40728c2ecf20Sopenharmony_ci }; 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci /* frame rates: 40758c2ecf20Sopenharmony_ci * 15fps / 7.5 fps for 1280x1024 40768c2ecf20Sopenharmony_ci * 30fps / 15fps for 640x480 40778c2ecf20Sopenharmony_ci */ 40788c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40); 40798c2ecf20Sopenharmony_ci if (qvga) 40808c2ecf20Sopenharmony_ci vals = sd->frame_rate < 30 ? vga_15 : vga_30; 40818c2ecf20Sopenharmony_ci else 40828c2ecf20Sopenharmony_ci vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15; 40838c2ecf20Sopenharmony_ci write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15)); 40848c2ecf20Sopenharmony_ci return; 40858c2ecf20Sopenharmony_ci } 40868c2ecf20Sopenharmony_ci default: 40878c2ecf20Sopenharmony_ci return; 40888c2ecf20Sopenharmony_ci } 40898c2ecf20Sopenharmony_ci 40908c2ecf20Sopenharmony_ci /******** Clock programming ********/ 40918c2ecf20Sopenharmony_ci i2c_w(sd, 0x11, sd->clockdiv); 40928c2ecf20Sopenharmony_ci} 40938c2ecf20Sopenharmony_ci 40948c2ecf20Sopenharmony_ci/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */ 40958c2ecf20Sopenharmony_cistatic void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) 40968c2ecf20Sopenharmony_ci{ 40978c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 40988c2ecf20Sopenharmony_ci 40998c2ecf20Sopenharmony_ci if (sd->gspca_dev.streaming) 41008c2ecf20Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x0f); /* block stream */ 41018c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R1E_MVFP, 41028c2ecf20Sopenharmony_ci OV7670_MVFP_MIRROR * hflip | OV7670_MVFP_VFLIP * vflip, 41038c2ecf20Sopenharmony_ci OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); 41048c2ecf20Sopenharmony_ci if (sd->gspca_dev.streaming) 41058c2ecf20Sopenharmony_ci reg_w(sd, OV519_R51_RESET1, 0x00); /* restart stream */ 41068c2ecf20Sopenharmony_ci} 41078c2ecf20Sopenharmony_ci 41088c2ecf20Sopenharmony_cistatic void set_ov_sensor_window(struct sd *sd) 41098c2ecf20Sopenharmony_ci{ 41108c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev; 41118c2ecf20Sopenharmony_ci int qvga, crop; 41128c2ecf20Sopenharmony_ci int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; 41138c2ecf20Sopenharmony_ci 41148c2ecf20Sopenharmony_ci /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ 41158c2ecf20Sopenharmony_ci switch (sd->sensor) { 41168c2ecf20Sopenharmony_ci case SEN_OV2610: 41178c2ecf20Sopenharmony_ci case SEN_OV2610AE: 41188c2ecf20Sopenharmony_ci case SEN_OV3610: 41198c2ecf20Sopenharmony_ci case SEN_OV7670: 41208c2ecf20Sopenharmony_ci case SEN_OV9600: 41218c2ecf20Sopenharmony_ci mode_init_ov_sensor_regs(sd); 41228c2ecf20Sopenharmony_ci return; 41238c2ecf20Sopenharmony_ci case SEN_OV7660: 41248c2ecf20Sopenharmony_ci ov519_set_mode(sd); 41258c2ecf20Sopenharmony_ci ov519_set_fr(sd); 41268c2ecf20Sopenharmony_ci return; 41278c2ecf20Sopenharmony_ci } 41288c2ecf20Sopenharmony_ci 41298c2ecf20Sopenharmony_ci gspca_dev = &sd->gspca_dev; 41308c2ecf20Sopenharmony_ci qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; 41318c2ecf20Sopenharmony_ci crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; 41328c2ecf20Sopenharmony_ci 41338c2ecf20Sopenharmony_ci /* The different sensor ICs handle setting up of window differently. 41348c2ecf20Sopenharmony_ci * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ 41358c2ecf20Sopenharmony_ci switch (sd->sensor) { 41368c2ecf20Sopenharmony_ci case SEN_OV8610: 41378c2ecf20Sopenharmony_ci hwsbase = 0x1e; 41388c2ecf20Sopenharmony_ci hwebase = 0x1e; 41398c2ecf20Sopenharmony_ci vwsbase = 0x02; 41408c2ecf20Sopenharmony_ci vwebase = 0x02; 41418c2ecf20Sopenharmony_ci break; 41428c2ecf20Sopenharmony_ci case SEN_OV7610: 41438c2ecf20Sopenharmony_ci case SEN_OV76BE: 41448c2ecf20Sopenharmony_ci hwsbase = 0x38; 41458c2ecf20Sopenharmony_ci hwebase = 0x3a; 41468c2ecf20Sopenharmony_ci vwsbase = vwebase = 0x05; 41478c2ecf20Sopenharmony_ci break; 41488c2ecf20Sopenharmony_ci case SEN_OV6620: 41498c2ecf20Sopenharmony_ci case SEN_OV6630: 41508c2ecf20Sopenharmony_ci case SEN_OV66308AF: 41518c2ecf20Sopenharmony_ci hwsbase = 0x38; 41528c2ecf20Sopenharmony_ci hwebase = 0x3a; 41538c2ecf20Sopenharmony_ci vwsbase = 0x05; 41548c2ecf20Sopenharmony_ci vwebase = 0x06; 41558c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV66308AF && qvga) 41568c2ecf20Sopenharmony_ci /* HDG: this fixes U and V getting swapped */ 41578c2ecf20Sopenharmony_ci hwsbase++; 41588c2ecf20Sopenharmony_ci if (crop) { 41598c2ecf20Sopenharmony_ci hwsbase += 8; 41608c2ecf20Sopenharmony_ci hwebase += 8; 41618c2ecf20Sopenharmony_ci vwsbase += 11; 41628c2ecf20Sopenharmony_ci vwebase += 11; 41638c2ecf20Sopenharmony_ci } 41648c2ecf20Sopenharmony_ci break; 41658c2ecf20Sopenharmony_ci case SEN_OV7620: 41668c2ecf20Sopenharmony_ci case SEN_OV7620AE: 41678c2ecf20Sopenharmony_ci hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ 41688c2ecf20Sopenharmony_ci hwebase = 0x2f; 41698c2ecf20Sopenharmony_ci vwsbase = vwebase = 0x05; 41708c2ecf20Sopenharmony_ci break; 41718c2ecf20Sopenharmony_ci case SEN_OV7640: 41728c2ecf20Sopenharmony_ci case SEN_OV7648: 41738c2ecf20Sopenharmony_ci hwsbase = 0x1a; 41748c2ecf20Sopenharmony_ci hwebase = 0x1a; 41758c2ecf20Sopenharmony_ci vwsbase = vwebase = 0x03; 41768c2ecf20Sopenharmony_ci break; 41778c2ecf20Sopenharmony_ci default: 41788c2ecf20Sopenharmony_ci return; 41798c2ecf20Sopenharmony_ci } 41808c2ecf20Sopenharmony_ci 41818c2ecf20Sopenharmony_ci switch (sd->sensor) { 41828c2ecf20Sopenharmony_ci case SEN_OV6620: 41838c2ecf20Sopenharmony_ci case SEN_OV6630: 41848c2ecf20Sopenharmony_ci case SEN_OV66308AF: 41858c2ecf20Sopenharmony_ci if (qvga) { /* QCIF */ 41868c2ecf20Sopenharmony_ci hwscale = 0; 41878c2ecf20Sopenharmony_ci vwscale = 0; 41888c2ecf20Sopenharmony_ci } else { /* CIF */ 41898c2ecf20Sopenharmony_ci hwscale = 1; 41908c2ecf20Sopenharmony_ci vwscale = 1; /* The datasheet says 0; 41918c2ecf20Sopenharmony_ci * it's wrong */ 41928c2ecf20Sopenharmony_ci } 41938c2ecf20Sopenharmony_ci break; 41948c2ecf20Sopenharmony_ci case SEN_OV8610: 41958c2ecf20Sopenharmony_ci if (qvga) { /* QSVGA */ 41968c2ecf20Sopenharmony_ci hwscale = 1; 41978c2ecf20Sopenharmony_ci vwscale = 1; 41988c2ecf20Sopenharmony_ci } else { /* SVGA */ 41998c2ecf20Sopenharmony_ci hwscale = 2; 42008c2ecf20Sopenharmony_ci vwscale = 2; 42018c2ecf20Sopenharmony_ci } 42028c2ecf20Sopenharmony_ci break; 42038c2ecf20Sopenharmony_ci default: /* SEN_OV7xx0 */ 42048c2ecf20Sopenharmony_ci if (qvga) { /* QVGA */ 42058c2ecf20Sopenharmony_ci hwscale = 1; 42068c2ecf20Sopenharmony_ci vwscale = 0; 42078c2ecf20Sopenharmony_ci } else { /* VGA */ 42088c2ecf20Sopenharmony_ci hwscale = 2; 42098c2ecf20Sopenharmony_ci vwscale = 1; 42108c2ecf20Sopenharmony_ci } 42118c2ecf20Sopenharmony_ci } 42128c2ecf20Sopenharmony_ci 42138c2ecf20Sopenharmony_ci mode_init_ov_sensor_regs(sd); 42148c2ecf20Sopenharmony_ci 42158c2ecf20Sopenharmony_ci i2c_w(sd, 0x17, hwsbase); 42168c2ecf20Sopenharmony_ci i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); 42178c2ecf20Sopenharmony_ci i2c_w(sd, 0x19, vwsbase); 42188c2ecf20Sopenharmony_ci i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); 42198c2ecf20Sopenharmony_ci} 42208c2ecf20Sopenharmony_ci 42218c2ecf20Sopenharmony_ci/* -- start the camera -- */ 42228c2ecf20Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev) 42238c2ecf20Sopenharmony_ci{ 42248c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 42258c2ecf20Sopenharmony_ci 42268c2ecf20Sopenharmony_ci /* Default for most bridges, allow bridge_mode_init_regs to override */ 42278c2ecf20Sopenharmony_ci sd->sensor_width = sd->gspca_dev.pixfmt.width; 42288c2ecf20Sopenharmony_ci sd->sensor_height = sd->gspca_dev.pixfmt.height; 42298c2ecf20Sopenharmony_ci 42308c2ecf20Sopenharmony_ci switch (sd->bridge) { 42318c2ecf20Sopenharmony_ci case BRIDGE_OV511: 42328c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 42338c2ecf20Sopenharmony_ci ov511_mode_init_regs(sd); 42348c2ecf20Sopenharmony_ci break; 42358c2ecf20Sopenharmony_ci case BRIDGE_OV518: 42368c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 42378c2ecf20Sopenharmony_ci ov518_mode_init_regs(sd); 42388c2ecf20Sopenharmony_ci break; 42398c2ecf20Sopenharmony_ci case BRIDGE_OV519: 42408c2ecf20Sopenharmony_ci ov519_mode_init_regs(sd); 42418c2ecf20Sopenharmony_ci break; 42428c2ecf20Sopenharmony_ci /* case BRIDGE_OVFX2: nothing to do */ 42438c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 42448c2ecf20Sopenharmony_ci w9968cf_mode_init_regs(sd); 42458c2ecf20Sopenharmony_ci break; 42468c2ecf20Sopenharmony_ci } 42478c2ecf20Sopenharmony_ci 42488c2ecf20Sopenharmony_ci set_ov_sensor_window(sd); 42498c2ecf20Sopenharmony_ci 42508c2ecf20Sopenharmony_ci /* Force clear snapshot state in case the snapshot button was 42518c2ecf20Sopenharmony_ci pressed while we weren't streaming */ 42528c2ecf20Sopenharmony_ci sd->snapshot_needs_reset = 1; 42538c2ecf20Sopenharmony_ci sd_reset_snapshot(gspca_dev); 42548c2ecf20Sopenharmony_ci 42558c2ecf20Sopenharmony_ci sd->first_frame = 3; 42568c2ecf20Sopenharmony_ci 42578c2ecf20Sopenharmony_ci ov51x_restart(sd); 42588c2ecf20Sopenharmony_ci ov51x_led_control(sd, 1); 42598c2ecf20Sopenharmony_ci return gspca_dev->usb_err; 42608c2ecf20Sopenharmony_ci} 42618c2ecf20Sopenharmony_ci 42628c2ecf20Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev) 42638c2ecf20Sopenharmony_ci{ 42648c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 42658c2ecf20Sopenharmony_ci 42668c2ecf20Sopenharmony_ci ov51x_stop(sd); 42678c2ecf20Sopenharmony_ci ov51x_led_control(sd, 0); 42688c2ecf20Sopenharmony_ci} 42698c2ecf20Sopenharmony_ci 42708c2ecf20Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev) 42718c2ecf20Sopenharmony_ci{ 42728c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 42738c2ecf20Sopenharmony_ci 42748c2ecf20Sopenharmony_ci if (!sd->gspca_dev.present) 42758c2ecf20Sopenharmony_ci return; 42768c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_W9968CF) 42778c2ecf20Sopenharmony_ci w9968cf_stop0(sd); 42788c2ecf20Sopenharmony_ci 42798c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT) 42808c2ecf20Sopenharmony_ci /* If the last button state is pressed, release it now! */ 42818c2ecf20Sopenharmony_ci if (sd->snapshot_pressed) { 42828c2ecf20Sopenharmony_ci input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); 42838c2ecf20Sopenharmony_ci input_sync(gspca_dev->input_dev); 42848c2ecf20Sopenharmony_ci sd->snapshot_pressed = 0; 42858c2ecf20Sopenharmony_ci } 42868c2ecf20Sopenharmony_ci#endif 42878c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_OV519) 42888c2ecf20Sopenharmony_ci reg_w(sd, OV519_R57_SNAPSHOT, 0x23); 42898c2ecf20Sopenharmony_ci} 42908c2ecf20Sopenharmony_ci 42918c2ecf20Sopenharmony_cistatic void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) 42928c2ecf20Sopenharmony_ci{ 42938c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 42948c2ecf20Sopenharmony_ci 42958c2ecf20Sopenharmony_ci if (sd->snapshot_pressed != state) { 42968c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT) 42978c2ecf20Sopenharmony_ci input_report_key(gspca_dev->input_dev, KEY_CAMERA, state); 42988c2ecf20Sopenharmony_ci input_sync(gspca_dev->input_dev); 42998c2ecf20Sopenharmony_ci#endif 43008c2ecf20Sopenharmony_ci if (state) 43018c2ecf20Sopenharmony_ci sd->snapshot_needs_reset = 1; 43028c2ecf20Sopenharmony_ci 43038c2ecf20Sopenharmony_ci sd->snapshot_pressed = state; 43048c2ecf20Sopenharmony_ci } else { 43058c2ecf20Sopenharmony_ci /* On the ov511 / ov519 we need to reset the button state 43068c2ecf20Sopenharmony_ci multiple times, as resetting does not work as long as the 43078c2ecf20Sopenharmony_ci button stays pressed */ 43088c2ecf20Sopenharmony_ci switch (sd->bridge) { 43098c2ecf20Sopenharmony_ci case BRIDGE_OV511: 43108c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 43118c2ecf20Sopenharmony_ci case BRIDGE_OV519: 43128c2ecf20Sopenharmony_ci if (state) 43138c2ecf20Sopenharmony_ci sd->snapshot_needs_reset = 1; 43148c2ecf20Sopenharmony_ci break; 43158c2ecf20Sopenharmony_ci } 43168c2ecf20Sopenharmony_ci } 43178c2ecf20Sopenharmony_ci} 43188c2ecf20Sopenharmony_ci 43198c2ecf20Sopenharmony_cistatic void ov511_pkt_scan(struct gspca_dev *gspca_dev, 43208c2ecf20Sopenharmony_ci u8 *in, /* isoc packet */ 43218c2ecf20Sopenharmony_ci int len) /* iso packet length */ 43228c2ecf20Sopenharmony_ci{ 43238c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 43248c2ecf20Sopenharmony_ci 43258c2ecf20Sopenharmony_ci /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th 43268c2ecf20Sopenharmony_ci * byte non-zero. The EOF packet has image width/height in the 43278c2ecf20Sopenharmony_ci * 10th and 11th bytes. The 9th byte is given as follows: 43288c2ecf20Sopenharmony_ci * 43298c2ecf20Sopenharmony_ci * bit 7: EOF 43308c2ecf20Sopenharmony_ci * 6: compression enabled 43318c2ecf20Sopenharmony_ci * 5: 422/420/400 modes 43328c2ecf20Sopenharmony_ci * 4: 422/420/400 modes 43338c2ecf20Sopenharmony_ci * 3: 1 43348c2ecf20Sopenharmony_ci * 2: snapshot button on 43358c2ecf20Sopenharmony_ci * 1: snapshot frame 43368c2ecf20Sopenharmony_ci * 0: even/odd field 43378c2ecf20Sopenharmony_ci */ 43388c2ecf20Sopenharmony_ci if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && 43398c2ecf20Sopenharmony_ci (in[8] & 0x08)) { 43408c2ecf20Sopenharmony_ci ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1); 43418c2ecf20Sopenharmony_ci if (in[8] & 0x80) { 43428c2ecf20Sopenharmony_ci /* Frame end */ 43438c2ecf20Sopenharmony_ci if ((in[9] + 1) * 8 != gspca_dev->pixfmt.width || 43448c2ecf20Sopenharmony_ci (in[10] + 1) * 8 != gspca_dev->pixfmt.height) { 43458c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Invalid frame size, got: %dx%d, requested: %dx%d\n", 43468c2ecf20Sopenharmony_ci (in[9] + 1) * 8, (in[10] + 1) * 8, 43478c2ecf20Sopenharmony_ci gspca_dev->pixfmt.width, 43488c2ecf20Sopenharmony_ci gspca_dev->pixfmt.height); 43498c2ecf20Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 43508c2ecf20Sopenharmony_ci return; 43518c2ecf20Sopenharmony_ci } 43528c2ecf20Sopenharmony_ci /* Add 11 byte footer to frame, might be useful */ 43538c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, in, 11); 43548c2ecf20Sopenharmony_ci return; 43558c2ecf20Sopenharmony_ci } else { 43568c2ecf20Sopenharmony_ci /* Frame start */ 43578c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0); 43588c2ecf20Sopenharmony_ci sd->packet_nr = 0; 43598c2ecf20Sopenharmony_ci } 43608c2ecf20Sopenharmony_ci } 43618c2ecf20Sopenharmony_ci 43628c2ecf20Sopenharmony_ci /* Ignore the packet number */ 43638c2ecf20Sopenharmony_ci len--; 43648c2ecf20Sopenharmony_ci 43658c2ecf20Sopenharmony_ci /* intermediate packet */ 43668c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, in, len); 43678c2ecf20Sopenharmony_ci} 43688c2ecf20Sopenharmony_ci 43698c2ecf20Sopenharmony_cistatic void ov518_pkt_scan(struct gspca_dev *gspca_dev, 43708c2ecf20Sopenharmony_ci u8 *data, /* isoc packet */ 43718c2ecf20Sopenharmony_ci int len) /* iso packet length */ 43728c2ecf20Sopenharmony_ci{ 43738c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 43748c2ecf20Sopenharmony_ci 43758c2ecf20Sopenharmony_ci /* A false positive here is likely, until OVT gives me 43768c2ecf20Sopenharmony_ci * the definitive SOF/EOF format */ 43778c2ecf20Sopenharmony_ci if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { 43788c2ecf20Sopenharmony_ci ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1); 43798c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 43808c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); 43818c2ecf20Sopenharmony_ci sd->packet_nr = 0; 43828c2ecf20Sopenharmony_ci } 43838c2ecf20Sopenharmony_ci 43848c2ecf20Sopenharmony_ci if (gspca_dev->last_packet_type == DISCARD_PACKET) 43858c2ecf20Sopenharmony_ci return; 43868c2ecf20Sopenharmony_ci 43878c2ecf20Sopenharmony_ci /* Does this device use packet numbers ? */ 43888c2ecf20Sopenharmony_ci if (len & 7) { 43898c2ecf20Sopenharmony_ci len--; 43908c2ecf20Sopenharmony_ci if (sd->packet_nr == data[len]) 43918c2ecf20Sopenharmony_ci sd->packet_nr++; 43928c2ecf20Sopenharmony_ci /* The last few packets of the frame (which are all 0's 43938c2ecf20Sopenharmony_ci except that they may contain part of the footer), are 43948c2ecf20Sopenharmony_ci numbered 0 */ 43958c2ecf20Sopenharmony_ci else if (sd->packet_nr == 0 || data[len]) { 43968c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Invalid packet nr: %d (expect: %d)\n", 43978c2ecf20Sopenharmony_ci (int)data[len], (int)sd->packet_nr); 43988c2ecf20Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 43998c2ecf20Sopenharmony_ci return; 44008c2ecf20Sopenharmony_ci } 44018c2ecf20Sopenharmony_ci } 44028c2ecf20Sopenharmony_ci 44038c2ecf20Sopenharmony_ci /* intermediate packet */ 44048c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 44058c2ecf20Sopenharmony_ci} 44068c2ecf20Sopenharmony_ci 44078c2ecf20Sopenharmony_cistatic void ov519_pkt_scan(struct gspca_dev *gspca_dev, 44088c2ecf20Sopenharmony_ci u8 *data, /* isoc packet */ 44098c2ecf20Sopenharmony_ci int len) /* iso packet length */ 44108c2ecf20Sopenharmony_ci{ 44118c2ecf20Sopenharmony_ci /* Header of ov519 is 16 bytes: 44128c2ecf20Sopenharmony_ci * Byte Value Description 44138c2ecf20Sopenharmony_ci * 0 0xff magic 44148c2ecf20Sopenharmony_ci * 1 0xff magic 44158c2ecf20Sopenharmony_ci * 2 0xff magic 44168c2ecf20Sopenharmony_ci * 3 0xXX 0x50 = SOF, 0x51 = EOF 44178c2ecf20Sopenharmony_ci * 9 0xXX 0x01 initial frame without data, 44188c2ecf20Sopenharmony_ci * 0x00 standard frame with image 44198c2ecf20Sopenharmony_ci * 14 Lo in EOF: length of image data / 8 44208c2ecf20Sopenharmony_ci * 15 Hi 44218c2ecf20Sopenharmony_ci */ 44228c2ecf20Sopenharmony_ci 44238c2ecf20Sopenharmony_ci if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { 44248c2ecf20Sopenharmony_ci switch (data[3]) { 44258c2ecf20Sopenharmony_ci case 0x50: /* start of frame */ 44268c2ecf20Sopenharmony_ci /* Don't check the button state here, as the state 44278c2ecf20Sopenharmony_ci usually (always ?) changes at EOF and checking it 44288c2ecf20Sopenharmony_ci here leads to unnecessary snapshot state resets. */ 44298c2ecf20Sopenharmony_ci#define HDRSZ 16 44308c2ecf20Sopenharmony_ci data += HDRSZ; 44318c2ecf20Sopenharmony_ci len -= HDRSZ; 44328c2ecf20Sopenharmony_ci#undef HDRSZ 44338c2ecf20Sopenharmony_ci if (data[0] == 0xff || data[1] == 0xd8) 44348c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, 44358c2ecf20Sopenharmony_ci data, len); 44368c2ecf20Sopenharmony_ci else 44378c2ecf20Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 44388c2ecf20Sopenharmony_ci return; 44398c2ecf20Sopenharmony_ci case 0x51: /* end of frame */ 44408c2ecf20Sopenharmony_ci ov51x_handle_button(gspca_dev, data[11] & 1); 44418c2ecf20Sopenharmony_ci if (data[9] != 0) 44428c2ecf20Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 44438c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, 44448c2ecf20Sopenharmony_ci NULL, 0); 44458c2ecf20Sopenharmony_ci return; 44468c2ecf20Sopenharmony_ci } 44478c2ecf20Sopenharmony_ci } 44488c2ecf20Sopenharmony_ci 44498c2ecf20Sopenharmony_ci /* intermediate packet */ 44508c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 44518c2ecf20Sopenharmony_ci} 44528c2ecf20Sopenharmony_ci 44538c2ecf20Sopenharmony_cistatic void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, 44548c2ecf20Sopenharmony_ci u8 *data, /* isoc packet */ 44558c2ecf20Sopenharmony_ci int len) /* iso packet length */ 44568c2ecf20Sopenharmony_ci{ 44578c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 44588c2ecf20Sopenharmony_ci 44598c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 44608c2ecf20Sopenharmony_ci 44618c2ecf20Sopenharmony_ci /* A short read signals EOF */ 44628c2ecf20Sopenharmony_ci if (len < gspca_dev->cam.bulk_size) { 44638c2ecf20Sopenharmony_ci /* If the frame is short, and it is one of the first ones 44648c2ecf20Sopenharmony_ci the sensor and bridge are still syncing, so drop it. */ 44658c2ecf20Sopenharmony_ci if (sd->first_frame) { 44668c2ecf20Sopenharmony_ci sd->first_frame--; 44678c2ecf20Sopenharmony_ci if (gspca_dev->image_len < 44688c2ecf20Sopenharmony_ci sd->gspca_dev.pixfmt.width * 44698c2ecf20Sopenharmony_ci sd->gspca_dev.pixfmt.height) 44708c2ecf20Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 44718c2ecf20Sopenharmony_ci } 44728c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 44738c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); 44748c2ecf20Sopenharmony_ci } 44758c2ecf20Sopenharmony_ci} 44768c2ecf20Sopenharmony_ci 44778c2ecf20Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev, 44788c2ecf20Sopenharmony_ci u8 *data, /* isoc packet */ 44798c2ecf20Sopenharmony_ci int len) /* iso packet length */ 44808c2ecf20Sopenharmony_ci{ 44818c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 44828c2ecf20Sopenharmony_ci 44838c2ecf20Sopenharmony_ci switch (sd->bridge) { 44848c2ecf20Sopenharmony_ci case BRIDGE_OV511: 44858c2ecf20Sopenharmony_ci case BRIDGE_OV511PLUS: 44868c2ecf20Sopenharmony_ci ov511_pkt_scan(gspca_dev, data, len); 44878c2ecf20Sopenharmony_ci break; 44888c2ecf20Sopenharmony_ci case BRIDGE_OV518: 44898c2ecf20Sopenharmony_ci case BRIDGE_OV518PLUS: 44908c2ecf20Sopenharmony_ci ov518_pkt_scan(gspca_dev, data, len); 44918c2ecf20Sopenharmony_ci break; 44928c2ecf20Sopenharmony_ci case BRIDGE_OV519: 44938c2ecf20Sopenharmony_ci ov519_pkt_scan(gspca_dev, data, len); 44948c2ecf20Sopenharmony_ci break; 44958c2ecf20Sopenharmony_ci case BRIDGE_OVFX2: 44968c2ecf20Sopenharmony_ci ovfx2_pkt_scan(gspca_dev, data, len); 44978c2ecf20Sopenharmony_ci break; 44988c2ecf20Sopenharmony_ci case BRIDGE_W9968CF: 44998c2ecf20Sopenharmony_ci w9968cf_pkt_scan(gspca_dev, data, len); 45008c2ecf20Sopenharmony_ci break; 45018c2ecf20Sopenharmony_ci } 45028c2ecf20Sopenharmony_ci} 45038c2ecf20Sopenharmony_ci 45048c2ecf20Sopenharmony_ci/* -- management routines -- */ 45058c2ecf20Sopenharmony_ci 45068c2ecf20Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev, s32 val) 45078c2ecf20Sopenharmony_ci{ 45088c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 45098c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals brit_7660[][7] = { 45108c2ecf20Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90}, 45118c2ecf20Sopenharmony_ci {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}}, 45128c2ecf20Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1}, 45138c2ecf20Sopenharmony_ci {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}}, 45148c2ecf20Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2}, 45158c2ecf20Sopenharmony_ci {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}}, 45168c2ecf20Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3}, 45178c2ecf20Sopenharmony_ci {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}}, 45188c2ecf20Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3}, 45198c2ecf20Sopenharmony_ci {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}}, 45208c2ecf20Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3}, 45218c2ecf20Sopenharmony_ci {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}}, 45228c2ecf20Sopenharmony_ci {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4}, 45238c2ecf20Sopenharmony_ci {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}} 45248c2ecf20Sopenharmony_ci }; 45258c2ecf20Sopenharmony_ci 45268c2ecf20Sopenharmony_ci switch (sd->sensor) { 45278c2ecf20Sopenharmony_ci case SEN_OV8610: 45288c2ecf20Sopenharmony_ci case SEN_OV7610: 45298c2ecf20Sopenharmony_ci case SEN_OV76BE: 45308c2ecf20Sopenharmony_ci case SEN_OV6620: 45318c2ecf20Sopenharmony_ci case SEN_OV6630: 45328c2ecf20Sopenharmony_ci case SEN_OV66308AF: 45338c2ecf20Sopenharmony_ci case SEN_OV7640: 45348c2ecf20Sopenharmony_ci case SEN_OV7648: 45358c2ecf20Sopenharmony_ci i2c_w(sd, OV7610_REG_BRT, val); 45368c2ecf20Sopenharmony_ci break; 45378c2ecf20Sopenharmony_ci case SEN_OV7620: 45388c2ecf20Sopenharmony_ci case SEN_OV7620AE: 45398c2ecf20Sopenharmony_ci i2c_w(sd, OV7610_REG_BRT, val); 45408c2ecf20Sopenharmony_ci break; 45418c2ecf20Sopenharmony_ci case SEN_OV7660: 45428c2ecf20Sopenharmony_ci write_i2c_regvals(sd, brit_7660[val], 45438c2ecf20Sopenharmony_ci ARRAY_SIZE(brit_7660[0])); 45448c2ecf20Sopenharmony_ci break; 45458c2ecf20Sopenharmony_ci case SEN_OV7670: 45468c2ecf20Sopenharmony_ci/*win trace 45478c2ecf20Sopenharmony_ci * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ 45488c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val)); 45498c2ecf20Sopenharmony_ci break; 45508c2ecf20Sopenharmony_ci } 45518c2ecf20Sopenharmony_ci} 45528c2ecf20Sopenharmony_ci 45538c2ecf20Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev, s32 val) 45548c2ecf20Sopenharmony_ci{ 45558c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 45568c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals contrast_7660[][31] = { 45578c2ecf20Sopenharmony_ci {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0}, 45588c2ecf20Sopenharmony_ci {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30}, 45598c2ecf20Sopenharmony_ci {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24}, 45608c2ecf20Sopenharmony_ci {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34}, 45618c2ecf20Sopenharmony_ci {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65}, 45628c2ecf20Sopenharmony_ci {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83}, 45638c2ecf20Sopenharmony_ci {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f}, 45648c2ecf20Sopenharmony_ci {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}}, 45658c2ecf20Sopenharmony_ci {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94}, 45668c2ecf20Sopenharmony_ci {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30}, 45678c2ecf20Sopenharmony_ci {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24}, 45688c2ecf20Sopenharmony_ci {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31}, 45698c2ecf20Sopenharmony_ci {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62}, 45708c2ecf20Sopenharmony_ci {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81}, 45718c2ecf20Sopenharmony_ci {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1}, 45728c2ecf20Sopenharmony_ci {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}}, 45738c2ecf20Sopenharmony_ci {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84}, 45748c2ecf20Sopenharmony_ci {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40}, 45758c2ecf20Sopenharmony_ci {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24}, 45768c2ecf20Sopenharmony_ci {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34}, 45778c2ecf20Sopenharmony_ci {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d}, 45788c2ecf20Sopenharmony_ci {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81}, 45798c2ecf20Sopenharmony_ci {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e}, 45808c2ecf20Sopenharmony_ci {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}}, 45818c2ecf20Sopenharmony_ci {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70}, 45828c2ecf20Sopenharmony_ci {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48}, 45838c2ecf20Sopenharmony_ci {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34}, 45848c2ecf20Sopenharmony_ci {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22}, 45858c2ecf20Sopenharmony_ci {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58}, 45868c2ecf20Sopenharmony_ci {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80}, 45878c2ecf20Sopenharmony_ci {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9}, 45888c2ecf20Sopenharmony_ci {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}}, 45898c2ecf20Sopenharmony_ci {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80}, 45908c2ecf20Sopenharmony_ci {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60}, 45918c2ecf20Sopenharmony_ci {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38}, 45928c2ecf20Sopenharmony_ci {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e}, 45938c2ecf20Sopenharmony_ci {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46}, 45948c2ecf20Sopenharmony_ci {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c}, 45958c2ecf20Sopenharmony_ci {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4}, 45968c2ecf20Sopenharmony_ci {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}}, 45978c2ecf20Sopenharmony_ci {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80}, 45988c2ecf20Sopenharmony_ci {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30}, 45998c2ecf20Sopenharmony_ci {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50}, 46008c2ecf20Sopenharmony_ci {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08}, 46018c2ecf20Sopenharmony_ci {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a}, 46028c2ecf20Sopenharmony_ci {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b}, 46038c2ecf20Sopenharmony_ci {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3}, 46048c2ecf20Sopenharmony_ci {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}}, 46058c2ecf20Sopenharmony_ci {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60}, 46068c2ecf20Sopenharmony_ci {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8}, 46078c2ecf20Sopenharmony_ci {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c}, 46088c2ecf20Sopenharmony_ci {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04}, 46098c2ecf20Sopenharmony_ci {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22}, 46108c2ecf20Sopenharmony_ci {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b}, 46118c2ecf20Sopenharmony_ci {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde}, 46128c2ecf20Sopenharmony_ci {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}}, 46138c2ecf20Sopenharmony_ci }; 46148c2ecf20Sopenharmony_ci 46158c2ecf20Sopenharmony_ci switch (sd->sensor) { 46168c2ecf20Sopenharmony_ci case SEN_OV7610: 46178c2ecf20Sopenharmony_ci case SEN_OV6620: 46188c2ecf20Sopenharmony_ci i2c_w(sd, OV7610_REG_CNT, val); 46198c2ecf20Sopenharmony_ci break; 46208c2ecf20Sopenharmony_ci case SEN_OV6630: 46218c2ecf20Sopenharmony_ci case SEN_OV66308AF: 46228c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); 46238c2ecf20Sopenharmony_ci break; 46248c2ecf20Sopenharmony_ci case SEN_OV8610: { 46258c2ecf20Sopenharmony_ci static const u8 ctab[] = { 46268c2ecf20Sopenharmony_ci 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f 46278c2ecf20Sopenharmony_ci }; 46288c2ecf20Sopenharmony_ci 46298c2ecf20Sopenharmony_ci /* Use Y gamma control instead. Bit 0 enables it. */ 46308c2ecf20Sopenharmony_ci i2c_w(sd, 0x64, ctab[val >> 5]); 46318c2ecf20Sopenharmony_ci break; 46328c2ecf20Sopenharmony_ci } 46338c2ecf20Sopenharmony_ci case SEN_OV7620: 46348c2ecf20Sopenharmony_ci case SEN_OV7620AE: { 46358c2ecf20Sopenharmony_ci static const u8 ctab[] = { 46368c2ecf20Sopenharmony_ci 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, 46378c2ecf20Sopenharmony_ci 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff 46388c2ecf20Sopenharmony_ci }; 46398c2ecf20Sopenharmony_ci 46408c2ecf20Sopenharmony_ci /* Use Y gamma control instead. Bit 0 enables it. */ 46418c2ecf20Sopenharmony_ci i2c_w(sd, 0x64, ctab[val >> 4]); 46428c2ecf20Sopenharmony_ci break; 46438c2ecf20Sopenharmony_ci } 46448c2ecf20Sopenharmony_ci case SEN_OV7660: 46458c2ecf20Sopenharmony_ci write_i2c_regvals(sd, contrast_7660[val], 46468c2ecf20Sopenharmony_ci ARRAY_SIZE(contrast_7660[0])); 46478c2ecf20Sopenharmony_ci break; 46488c2ecf20Sopenharmony_ci case SEN_OV7670: 46498c2ecf20Sopenharmony_ci /* check that this isn't just the same as ov7610 */ 46508c2ecf20Sopenharmony_ci i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); 46518c2ecf20Sopenharmony_ci break; 46528c2ecf20Sopenharmony_ci } 46538c2ecf20Sopenharmony_ci} 46548c2ecf20Sopenharmony_ci 46558c2ecf20Sopenharmony_cistatic void setexposure(struct gspca_dev *gspca_dev, s32 val) 46568c2ecf20Sopenharmony_ci{ 46578c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 46588c2ecf20Sopenharmony_ci 46598c2ecf20Sopenharmony_ci i2c_w(sd, 0x10, val); 46608c2ecf20Sopenharmony_ci} 46618c2ecf20Sopenharmony_ci 46628c2ecf20Sopenharmony_cistatic void setcolors(struct gspca_dev *gspca_dev, s32 val) 46638c2ecf20Sopenharmony_ci{ 46648c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 46658c2ecf20Sopenharmony_ci static const struct ov_i2c_regvals colors_7660[][6] = { 46668c2ecf20Sopenharmony_ci {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a}, 46678c2ecf20Sopenharmony_ci {0x53, 0x19}, {0x54, 0x23}}, 46688c2ecf20Sopenharmony_ci {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11}, 46698c2ecf20Sopenharmony_ci {0x53, 0x2c}, {0x54, 0x3e}}, 46708c2ecf20Sopenharmony_ci {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19}, 46718c2ecf20Sopenharmony_ci {0x53, 0x40}, {0x54, 0x59}}, 46728c2ecf20Sopenharmony_ci {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20}, 46738c2ecf20Sopenharmony_ci {0x53, 0x53}, {0x54, 0x73}}, 46748c2ecf20Sopenharmony_ci {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28}, 46758c2ecf20Sopenharmony_ci {0x53, 0x66}, {0x54, 0x8e}}, 46768c2ecf20Sopenharmony_ci }; 46778c2ecf20Sopenharmony_ci 46788c2ecf20Sopenharmony_ci switch (sd->sensor) { 46798c2ecf20Sopenharmony_ci case SEN_OV8610: 46808c2ecf20Sopenharmony_ci case SEN_OV7610: 46818c2ecf20Sopenharmony_ci case SEN_OV76BE: 46828c2ecf20Sopenharmony_ci case SEN_OV6620: 46838c2ecf20Sopenharmony_ci case SEN_OV6630: 46848c2ecf20Sopenharmony_ci case SEN_OV66308AF: 46858c2ecf20Sopenharmony_ci i2c_w(sd, OV7610_REG_SAT, val); 46868c2ecf20Sopenharmony_ci break; 46878c2ecf20Sopenharmony_ci case SEN_OV7620: 46888c2ecf20Sopenharmony_ci case SEN_OV7620AE: 46898c2ecf20Sopenharmony_ci /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ 46908c2ecf20Sopenharmony_ci/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e); 46918c2ecf20Sopenharmony_ci if (rc < 0) 46928c2ecf20Sopenharmony_ci goto out; */ 46938c2ecf20Sopenharmony_ci i2c_w(sd, OV7610_REG_SAT, val); 46948c2ecf20Sopenharmony_ci break; 46958c2ecf20Sopenharmony_ci case SEN_OV7640: 46968c2ecf20Sopenharmony_ci case SEN_OV7648: 46978c2ecf20Sopenharmony_ci i2c_w(sd, OV7610_REG_SAT, val & 0xf0); 46988c2ecf20Sopenharmony_ci break; 46998c2ecf20Sopenharmony_ci case SEN_OV7660: 47008c2ecf20Sopenharmony_ci write_i2c_regvals(sd, colors_7660[val], 47018c2ecf20Sopenharmony_ci ARRAY_SIZE(colors_7660[0])); 47028c2ecf20Sopenharmony_ci break; 47038c2ecf20Sopenharmony_ci case SEN_OV7670: 47048c2ecf20Sopenharmony_ci /* supported later once I work out how to do it 47058c2ecf20Sopenharmony_ci * transparently fail now! */ 47068c2ecf20Sopenharmony_ci /* set REG_COM13 values for UV sat auto mode */ 47078c2ecf20Sopenharmony_ci break; 47088c2ecf20Sopenharmony_ci } 47098c2ecf20Sopenharmony_ci} 47108c2ecf20Sopenharmony_ci 47118c2ecf20Sopenharmony_cistatic void setautobright(struct gspca_dev *gspca_dev, s32 val) 47128c2ecf20Sopenharmony_ci{ 47138c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 47148c2ecf20Sopenharmony_ci 47158c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2d, val ? 0x10 : 0x00, 0x10); 47168c2ecf20Sopenharmony_ci} 47178c2ecf20Sopenharmony_ci 47188c2ecf20Sopenharmony_cistatic void setfreq_i(struct sd *sd, s32 val) 47198c2ecf20Sopenharmony_ci{ 47208c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV7660 47218c2ecf20Sopenharmony_ci || sd->sensor == SEN_OV7670) { 47228c2ecf20Sopenharmony_ci switch (val) { 47238c2ecf20Sopenharmony_ci case 0: /* Banding filter disabled */ 47248c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); 47258c2ecf20Sopenharmony_ci break; 47268c2ecf20Sopenharmony_ci case 1: /* 50 hz */ 47278c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, 47288c2ecf20Sopenharmony_ci OV7670_COM8_BFILT); 47298c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18); 47308c2ecf20Sopenharmony_ci break; 47318c2ecf20Sopenharmony_ci case 2: /* 60 hz */ 47328c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, 47338c2ecf20Sopenharmony_ci OV7670_COM8_BFILT); 47348c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18); 47358c2ecf20Sopenharmony_ci break; 47368c2ecf20Sopenharmony_ci case 3: /* Auto hz - ov7670 only */ 47378c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, 47388c2ecf20Sopenharmony_ci OV7670_COM8_BFILT); 47398c2ecf20Sopenharmony_ci i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO, 47408c2ecf20Sopenharmony_ci 0x18); 47418c2ecf20Sopenharmony_ci break; 47428c2ecf20Sopenharmony_ci } 47438c2ecf20Sopenharmony_ci } else { 47448c2ecf20Sopenharmony_ci switch (val) { 47458c2ecf20Sopenharmony_ci case 0: /* Banding filter disabled */ 47468c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2d, 0x00, 0x04); 47478c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2a, 0x00, 0x80); 47488c2ecf20Sopenharmony_ci break; 47498c2ecf20Sopenharmony_ci case 1: /* 50 hz (filter on and framerate adj) */ 47508c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2d, 0x04, 0x04); 47518c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2a, 0x80, 0x80); 47528c2ecf20Sopenharmony_ci /* 20 fps -> 16.667 fps */ 47538c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV6620 || 47548c2ecf20Sopenharmony_ci sd->sensor == SEN_OV6630 || 47558c2ecf20Sopenharmony_ci sd->sensor == SEN_OV66308AF) 47568c2ecf20Sopenharmony_ci i2c_w(sd, 0x2b, 0x5e); 47578c2ecf20Sopenharmony_ci else 47588c2ecf20Sopenharmony_ci i2c_w(sd, 0x2b, 0xac); 47598c2ecf20Sopenharmony_ci break; 47608c2ecf20Sopenharmony_ci case 2: /* 60 hz (filter on, ...) */ 47618c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2d, 0x04, 0x04); 47628c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV6620 || 47638c2ecf20Sopenharmony_ci sd->sensor == SEN_OV6630 || 47648c2ecf20Sopenharmony_ci sd->sensor == SEN_OV66308AF) { 47658c2ecf20Sopenharmony_ci /* 20 fps -> 15 fps */ 47668c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2a, 0x80, 0x80); 47678c2ecf20Sopenharmony_ci i2c_w(sd, 0x2b, 0xa8); 47688c2ecf20Sopenharmony_ci } else { 47698c2ecf20Sopenharmony_ci /* no framerate adj. */ 47708c2ecf20Sopenharmony_ci i2c_w_mask(sd, 0x2a, 0x00, 0x80); 47718c2ecf20Sopenharmony_ci } 47728c2ecf20Sopenharmony_ci break; 47738c2ecf20Sopenharmony_ci } 47748c2ecf20Sopenharmony_ci } 47758c2ecf20Sopenharmony_ci} 47768c2ecf20Sopenharmony_ci 47778c2ecf20Sopenharmony_cistatic void setfreq(struct gspca_dev *gspca_dev, s32 val) 47788c2ecf20Sopenharmony_ci{ 47798c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 47808c2ecf20Sopenharmony_ci 47818c2ecf20Sopenharmony_ci setfreq_i(sd, val); 47828c2ecf20Sopenharmony_ci 47838c2ecf20Sopenharmony_ci /* Ugly but necessary */ 47848c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_W9968CF) 47858c2ecf20Sopenharmony_ci w9968cf_set_crop_window(sd); 47868c2ecf20Sopenharmony_ci} 47878c2ecf20Sopenharmony_ci 47888c2ecf20Sopenharmony_cistatic int sd_get_jcomp(struct gspca_dev *gspca_dev, 47898c2ecf20Sopenharmony_ci struct v4l2_jpegcompression *jcomp) 47908c2ecf20Sopenharmony_ci{ 47918c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 47928c2ecf20Sopenharmony_ci 47938c2ecf20Sopenharmony_ci if (sd->bridge != BRIDGE_W9968CF) 47948c2ecf20Sopenharmony_ci return -ENOTTY; 47958c2ecf20Sopenharmony_ci 47968c2ecf20Sopenharmony_ci memset(jcomp, 0, sizeof *jcomp); 47978c2ecf20Sopenharmony_ci jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); 47988c2ecf20Sopenharmony_ci jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT | 47998c2ecf20Sopenharmony_ci V4L2_JPEG_MARKER_DRI; 48008c2ecf20Sopenharmony_ci return 0; 48018c2ecf20Sopenharmony_ci} 48028c2ecf20Sopenharmony_ci 48038c2ecf20Sopenharmony_cistatic int sd_set_jcomp(struct gspca_dev *gspca_dev, 48048c2ecf20Sopenharmony_ci const struct v4l2_jpegcompression *jcomp) 48058c2ecf20Sopenharmony_ci{ 48068c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 48078c2ecf20Sopenharmony_ci 48088c2ecf20Sopenharmony_ci if (sd->bridge != BRIDGE_W9968CF) 48098c2ecf20Sopenharmony_ci return -ENOTTY; 48108c2ecf20Sopenharmony_ci 48118c2ecf20Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); 48128c2ecf20Sopenharmony_ci return 0; 48138c2ecf20Sopenharmony_ci} 48148c2ecf20Sopenharmony_ci 48158c2ecf20Sopenharmony_cistatic int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 48168c2ecf20Sopenharmony_ci{ 48178c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = 48188c2ecf20Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 48198c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 48208c2ecf20Sopenharmony_ci 48218c2ecf20Sopenharmony_ci gspca_dev->usb_err = 0; 48228c2ecf20Sopenharmony_ci 48238c2ecf20Sopenharmony_ci switch (ctrl->id) { 48248c2ecf20Sopenharmony_ci case V4L2_CID_AUTOGAIN: 48258c2ecf20Sopenharmony_ci gspca_dev->exposure->val = i2c_r(sd, 0x10); 48268c2ecf20Sopenharmony_ci break; 48278c2ecf20Sopenharmony_ci } 48288c2ecf20Sopenharmony_ci return 0; 48298c2ecf20Sopenharmony_ci} 48308c2ecf20Sopenharmony_ci 48318c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl) 48328c2ecf20Sopenharmony_ci{ 48338c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = 48348c2ecf20Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 48358c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 48368c2ecf20Sopenharmony_ci 48378c2ecf20Sopenharmony_ci gspca_dev->usb_err = 0; 48388c2ecf20Sopenharmony_ci 48398c2ecf20Sopenharmony_ci if (!gspca_dev->streaming) 48408c2ecf20Sopenharmony_ci return 0; 48418c2ecf20Sopenharmony_ci 48428c2ecf20Sopenharmony_ci switch (ctrl->id) { 48438c2ecf20Sopenharmony_ci case V4L2_CID_BRIGHTNESS: 48448c2ecf20Sopenharmony_ci setbrightness(gspca_dev, ctrl->val); 48458c2ecf20Sopenharmony_ci break; 48468c2ecf20Sopenharmony_ci case V4L2_CID_CONTRAST: 48478c2ecf20Sopenharmony_ci setcontrast(gspca_dev, ctrl->val); 48488c2ecf20Sopenharmony_ci break; 48498c2ecf20Sopenharmony_ci case V4L2_CID_POWER_LINE_FREQUENCY: 48508c2ecf20Sopenharmony_ci setfreq(gspca_dev, ctrl->val); 48518c2ecf20Sopenharmony_ci break; 48528c2ecf20Sopenharmony_ci case V4L2_CID_AUTOBRIGHTNESS: 48538c2ecf20Sopenharmony_ci if (ctrl->is_new) 48548c2ecf20Sopenharmony_ci setautobright(gspca_dev, ctrl->val); 48558c2ecf20Sopenharmony_ci if (!ctrl->val && sd->brightness->is_new) 48568c2ecf20Sopenharmony_ci setbrightness(gspca_dev, sd->brightness->val); 48578c2ecf20Sopenharmony_ci break; 48588c2ecf20Sopenharmony_ci case V4L2_CID_SATURATION: 48598c2ecf20Sopenharmony_ci setcolors(gspca_dev, ctrl->val); 48608c2ecf20Sopenharmony_ci break; 48618c2ecf20Sopenharmony_ci case V4L2_CID_HFLIP: 48628c2ecf20Sopenharmony_ci sethvflip(gspca_dev, ctrl->val, sd->vflip->val); 48638c2ecf20Sopenharmony_ci break; 48648c2ecf20Sopenharmony_ci case V4L2_CID_AUTOGAIN: 48658c2ecf20Sopenharmony_ci if (ctrl->is_new) 48668c2ecf20Sopenharmony_ci setautogain(gspca_dev, ctrl->val); 48678c2ecf20Sopenharmony_ci if (!ctrl->val && gspca_dev->exposure->is_new) 48688c2ecf20Sopenharmony_ci setexposure(gspca_dev, gspca_dev->exposure->val); 48698c2ecf20Sopenharmony_ci break; 48708c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_COMPRESSION_QUALITY: 48718c2ecf20Sopenharmony_ci return -EBUSY; /* Should never happen, as we grab the ctrl */ 48728c2ecf20Sopenharmony_ci } 48738c2ecf20Sopenharmony_ci return gspca_dev->usb_err; 48748c2ecf20Sopenharmony_ci} 48758c2ecf20Sopenharmony_ci 48768c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = { 48778c2ecf20Sopenharmony_ci .g_volatile_ctrl = sd_g_volatile_ctrl, 48788c2ecf20Sopenharmony_ci .s_ctrl = sd_s_ctrl, 48798c2ecf20Sopenharmony_ci}; 48808c2ecf20Sopenharmony_ci 48818c2ecf20Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev) 48828c2ecf20Sopenharmony_ci{ 48838c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 48848c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 48858c2ecf20Sopenharmony_ci 48868c2ecf20Sopenharmony_ci gspca_dev->vdev.ctrl_handler = hdl; 48878c2ecf20Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 10); 48888c2ecf20Sopenharmony_ci if (valid_controls[sd->sensor].has_brightness) 48898c2ecf20Sopenharmony_ci sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 48908c2ecf20Sopenharmony_ci V4L2_CID_BRIGHTNESS, 0, 48918c2ecf20Sopenharmony_ci sd->sensor == SEN_OV7660 ? 6 : 255, 1, 48928c2ecf20Sopenharmony_ci sd->sensor == SEN_OV7660 ? 3 : 127); 48938c2ecf20Sopenharmony_ci if (valid_controls[sd->sensor].has_contrast) { 48948c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV7660) 48958c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 48968c2ecf20Sopenharmony_ci V4L2_CID_CONTRAST, 0, 6, 1, 3); 48978c2ecf20Sopenharmony_ci else 48988c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 48998c2ecf20Sopenharmony_ci V4L2_CID_CONTRAST, 0, 255, 1, 49008c2ecf20Sopenharmony_ci (sd->sensor == SEN_OV6630 || 49018c2ecf20Sopenharmony_ci sd->sensor == SEN_OV66308AF) ? 200 : 127); 49028c2ecf20Sopenharmony_ci } 49038c2ecf20Sopenharmony_ci if (valid_controls[sd->sensor].has_sat) 49048c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 49058c2ecf20Sopenharmony_ci V4L2_CID_SATURATION, 0, 49068c2ecf20Sopenharmony_ci sd->sensor == SEN_OV7660 ? 4 : 255, 1, 49078c2ecf20Sopenharmony_ci sd->sensor == SEN_OV7660 ? 2 : 127); 49088c2ecf20Sopenharmony_ci if (valid_controls[sd->sensor].has_exposure) 49098c2ecf20Sopenharmony_ci gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 49108c2ecf20Sopenharmony_ci V4L2_CID_EXPOSURE, 0, 255, 1, 127); 49118c2ecf20Sopenharmony_ci if (valid_controls[sd->sensor].has_hvflip) { 49128c2ecf20Sopenharmony_ci sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 49138c2ecf20Sopenharmony_ci V4L2_CID_HFLIP, 0, 1, 1, 0); 49148c2ecf20Sopenharmony_ci sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 49158c2ecf20Sopenharmony_ci V4L2_CID_VFLIP, 0, 1, 1, 0); 49168c2ecf20Sopenharmony_ci } 49178c2ecf20Sopenharmony_ci if (valid_controls[sd->sensor].has_autobright) 49188c2ecf20Sopenharmony_ci sd->autobright = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 49198c2ecf20Sopenharmony_ci V4L2_CID_AUTOBRIGHTNESS, 0, 1, 1, 1); 49208c2ecf20Sopenharmony_ci if (valid_controls[sd->sensor].has_autogain) 49218c2ecf20Sopenharmony_ci gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 49228c2ecf20Sopenharmony_ci V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 49238c2ecf20Sopenharmony_ci if (valid_controls[sd->sensor].has_freq) { 49248c2ecf20Sopenharmony_ci if (sd->sensor == SEN_OV7670) 49258c2ecf20Sopenharmony_ci sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, 49268c2ecf20Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY, 49278c2ecf20Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0, 49288c2ecf20Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY_AUTO); 49298c2ecf20Sopenharmony_ci else 49308c2ecf20Sopenharmony_ci sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, 49318c2ecf20Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY, 49328c2ecf20Sopenharmony_ci V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0); 49338c2ecf20Sopenharmony_ci } 49348c2ecf20Sopenharmony_ci if (sd->bridge == BRIDGE_W9968CF) 49358c2ecf20Sopenharmony_ci sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 49368c2ecf20Sopenharmony_ci V4L2_CID_JPEG_COMPRESSION_QUALITY, 49378c2ecf20Sopenharmony_ci QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF); 49388c2ecf20Sopenharmony_ci 49398c2ecf20Sopenharmony_ci if (hdl->error) { 49408c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Could not initialize controls\n"); 49418c2ecf20Sopenharmony_ci return hdl->error; 49428c2ecf20Sopenharmony_ci } 49438c2ecf20Sopenharmony_ci if (gspca_dev->autogain) 49448c2ecf20Sopenharmony_ci v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, true); 49458c2ecf20Sopenharmony_ci if (sd->autobright) 49468c2ecf20Sopenharmony_ci v4l2_ctrl_auto_cluster(2, &sd->autobright, 0, false); 49478c2ecf20Sopenharmony_ci if (sd->hflip) 49488c2ecf20Sopenharmony_ci v4l2_ctrl_cluster(2, &sd->hflip); 49498c2ecf20Sopenharmony_ci return 0; 49508c2ecf20Sopenharmony_ci} 49518c2ecf20Sopenharmony_ci 49528c2ecf20Sopenharmony_ci/* sub-driver description */ 49538c2ecf20Sopenharmony_cistatic const struct sd_desc sd_desc = { 49548c2ecf20Sopenharmony_ci .name = MODULE_NAME, 49558c2ecf20Sopenharmony_ci .config = sd_config, 49568c2ecf20Sopenharmony_ci .init = sd_init, 49578c2ecf20Sopenharmony_ci .init_controls = sd_init_controls, 49588c2ecf20Sopenharmony_ci .isoc_init = sd_isoc_init, 49598c2ecf20Sopenharmony_ci .start = sd_start, 49608c2ecf20Sopenharmony_ci .stopN = sd_stopN, 49618c2ecf20Sopenharmony_ci .stop0 = sd_stop0, 49628c2ecf20Sopenharmony_ci .pkt_scan = sd_pkt_scan, 49638c2ecf20Sopenharmony_ci .dq_callback = sd_reset_snapshot, 49648c2ecf20Sopenharmony_ci .get_jcomp = sd_get_jcomp, 49658c2ecf20Sopenharmony_ci .set_jcomp = sd_set_jcomp, 49668c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT) 49678c2ecf20Sopenharmony_ci .other_input = 1, 49688c2ecf20Sopenharmony_ci#endif 49698c2ecf20Sopenharmony_ci}; 49708c2ecf20Sopenharmony_ci 49718c2ecf20Sopenharmony_ci/* -- module initialisation -- */ 49728c2ecf20Sopenharmony_cistatic const struct usb_device_id device_table[] = { 49738c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF }, 49748c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x4052), 49758c2ecf20Sopenharmony_ci .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, 49768c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, 49778c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, 49788c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, 49798c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 }, 49808c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, 49818c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 }, 49828c2ecf20Sopenharmony_ci {USB_DEVICE(0x045e, 0x028c), 49838c2ecf20Sopenharmony_ci .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, 49848c2ecf20Sopenharmony_ci {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, 49858c2ecf20Sopenharmony_ci {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, 49868c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, 49878c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, 49888c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0x0519), 49898c2ecf20Sopenharmony_ci .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, 49908c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0x0530), 49918c2ecf20Sopenharmony_ci .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, 49928c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 }, 49938c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, 49948c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, 49958c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, 49968c2ecf20Sopenharmony_ci {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, 49978c2ecf20Sopenharmony_ci {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, 49988c2ecf20Sopenharmony_ci {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, 49998c2ecf20Sopenharmony_ci {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, 50008c2ecf20Sopenharmony_ci {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, 50018c2ecf20Sopenharmony_ci {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 }, 50028c2ecf20Sopenharmony_ci {} 50038c2ecf20Sopenharmony_ci}; 50048c2ecf20Sopenharmony_ci 50058c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table); 50068c2ecf20Sopenharmony_ci 50078c2ecf20Sopenharmony_ci/* -- device connect -- */ 50088c2ecf20Sopenharmony_cistatic int sd_probe(struct usb_interface *intf, 50098c2ecf20Sopenharmony_ci const struct usb_device_id *id) 50108c2ecf20Sopenharmony_ci{ 50118c2ecf20Sopenharmony_ci return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 50128c2ecf20Sopenharmony_ci THIS_MODULE); 50138c2ecf20Sopenharmony_ci} 50148c2ecf20Sopenharmony_ci 50158c2ecf20Sopenharmony_cistatic struct usb_driver sd_driver = { 50168c2ecf20Sopenharmony_ci .name = MODULE_NAME, 50178c2ecf20Sopenharmony_ci .id_table = device_table, 50188c2ecf20Sopenharmony_ci .probe = sd_probe, 50198c2ecf20Sopenharmony_ci .disconnect = gspca_disconnect, 50208c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 50218c2ecf20Sopenharmony_ci .suspend = gspca_suspend, 50228c2ecf20Sopenharmony_ci .resume = gspca_resume, 50238c2ecf20Sopenharmony_ci .reset_resume = gspca_resume, 50248c2ecf20Sopenharmony_ci#endif 50258c2ecf20Sopenharmony_ci}; 50268c2ecf20Sopenharmony_ci 50278c2ecf20Sopenharmony_cimodule_usb_driver(sd_driver); 50288c2ecf20Sopenharmony_ci 50298c2ecf20Sopenharmony_cimodule_param(frame_rate, int, 0644); 50308c2ecf20Sopenharmony_ciMODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)"); 5031