brintos

brintos / linux-shallow public Read only

0
0
Text · 40.7 KiB · 91efc65 Raw
1822 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ov534-ov9xxx gspca driver4 *5 * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr6 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>7 * Copyright (C) 2008 Jim Paris <jim@jtan.com>8 *9 * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>10 * USB protocol reverse engineered by Jim Paris <jim@jtan.com>11 * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/12 */13 14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt15 16#define MODULE_NAME "ov534_9"17 18#include "gspca.h"19 20#define OV534_REG_ADDRESS	0xf1	/* sensor address */21#define OV534_REG_SUBADDR	0xf222#define OV534_REG_WRITE		0xf323#define OV534_REG_READ		0xf424#define OV534_REG_OPERATION	0xf525#define OV534_REG_STATUS	0xf626 27#define OV534_OP_WRITE_3	0x3728#define OV534_OP_WRITE_2	0x3329#define OV534_OP_READ_2		0xf930 31#define CTRL_TIMEOUT 50032 33MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");34MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");35MODULE_LICENSE("GPL");36 37/* specific webcam descriptor */38struct sd {39	struct gspca_dev gspca_dev;	/* !! must be the first item */40	__u32 last_pts;41	u8 last_fid;42 43	u8 sensor;44};45enum sensors {46	SENSOR_OV965x,		/* ov9657 */47	SENSOR_OV971x,		/* ov9712 */48	SENSOR_OV562x,		/* ov5621 */49	SENSOR_OV361x,		/* ov3610 */50	NSENSORS51};52 53static const struct v4l2_pix_format ov965x_mode[] = {54#define QVGA_MODE 055	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,56		.bytesperline = 320,57		.sizeimage = 320 * 240 * 3 / 8 + 590,58		.colorspace = V4L2_COLORSPACE_JPEG},59#define VGA_MODE 160	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,61		.bytesperline = 640,62		.sizeimage = 640 * 480 * 3 / 8 + 590,63		.colorspace = V4L2_COLORSPACE_JPEG},64#define SVGA_MODE 265	{800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,66		.bytesperline = 800,67		.sizeimage = 800 * 600 * 3 / 8 + 590,68		.colorspace = V4L2_COLORSPACE_JPEG},69#define XGA_MODE 370	{1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,71		.bytesperline = 1024,72		.sizeimage = 1024 * 768 * 3 / 8 + 590,73		.colorspace = V4L2_COLORSPACE_JPEG},74#define SXGA_MODE 475	{1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,76		.bytesperline = 1280,77		.sizeimage = 1280 * 1024 * 3 / 8 + 590,78		.colorspace = V4L2_COLORSPACE_JPEG},79};80 81static const struct v4l2_pix_format ov971x_mode[] = {82	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,83		.bytesperline = 640,84		.sizeimage = 640 * 480,85		.colorspace = V4L2_COLORSPACE_SRGB86	}87};88 89static const struct v4l2_pix_format ov562x_mode[] = {90	{2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,91		.bytesperline = 2592,92		.sizeimage = 2592 * 1680,93		.colorspace = V4L2_COLORSPACE_SRGB94	}95};96 97enum ov361x {98	ov361x_2048 = 0,99	ov361x_1600,100	ov361x_1024,101	ov361x_640,102	ov361x_320,103	ov361x_160,104	ov361x_last105};106 107static const struct v4l2_pix_format ov361x_mode[] = {108	{0x800, 0x600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,109		.bytesperline = 0x800,110		.sizeimage = 0x800 * 0x600,111		.colorspace = V4L2_COLORSPACE_SRGB},112	{1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,113		.bytesperline = 1600,114		.sizeimage = 1600 * 1200,115		.colorspace = V4L2_COLORSPACE_SRGB},116	{1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,117		.bytesperline = 768,118		.sizeimage = 1024 * 768,119		.colorspace = V4L2_COLORSPACE_SRGB},120	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,121		.bytesperline = 640,122		.sizeimage = 640 * 480,123		.colorspace = V4L2_COLORSPACE_SRGB},124	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,125		.bytesperline = 320,126		.sizeimage = 320 * 240,127		.colorspace = V4L2_COLORSPACE_SRGB},128	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,129		.bytesperline = 160,130		.sizeimage = 160 * 120,131		.colorspace = V4L2_COLORSPACE_SRGB}132};133 134static const u8 ov361x_start_2048[][2] = {135	{0x12, 0x80},136	{0x13, 0xcf},137	{0x14, 0x40},138	{0x15, 0x00},139	{0x01, 0x80},140	{0x02, 0x80},141	{0x04, 0x70},142	{0x0d, 0x40},143	{0x0f, 0x47},144	{0x11, 0x81},145	{0x32, 0x36},146	{0x33, 0x0c},147	{0x34, 0x00},148	{0x35, 0x90},149	{0x12, 0x00},150	{0x17, 0x10},151	{0x18, 0x90},152	{0x19, 0x00},153	{0x1a, 0xc0},154};155static const u8 ov361x_bridge_start_2048[][2] = {156	{0xf1, 0x60},157	{0x88, 0x00},158	{0x89, 0x08},159	{0x8a, 0x00},160	{0x8b, 0x06},161	{0x8c, 0x01},162	{0x8d, 0x10},163	{0x1c, 0x00},164	{0x1d, 0x48},165	{0x1d, 0x00},166	{0x1d, 0xff},167	{0x1c, 0x0a},168	{0x1d, 0x2e},169	{0x1d, 0x1e},170};171 172static const u8 ov361x_start_1600[][2] = {173	{0x12, 0x80},174	{0x13, 0xcf},175	{0x14, 0x40},176	{0x15, 0x00},177	{0x01, 0x80},178	{0x02, 0x80},179	{0x04, 0x70},180	{0x0d, 0x40},181	{0x0f, 0x47},182	{0x11, 0x81},183	{0x32, 0x36},184	{0x33, 0x0C},185	{0x34, 0x00},186	{0x35, 0x90},187	{0x12, 0x00},188	{0x17, 0x10},189	{0x18, 0x90},190	{0x19, 0x00},191	{0x1a, 0xc0},192};193static const u8 ov361x_bridge_start_1600[][2] = {194	{0xf1, 0x60},  /* Hsize[7:0] */195	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */196	{0x89, 0x08},  /* Vsize[7:0] */197	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */198	{0x8b, 0x06},  /* for Iso */199	{0x8c, 0x01},  /* RAW input */200	{0x8d, 0x10},201	{0x1c, 0x00},  /* RAW output, Iso transfer */202	{0x1d, 0x48},203	{0x1d, 0x00},204	{0x1d, 0xff},205	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */206	{0x1d, 0x2e},  /* for Iso */207	{0x1d, 0x1e},208};209 210static const u8 ov361x_start_1024[][2] = {211	{0x12, 0x80},212	{0x13, 0xcf},213	{0x14, 0x40},214	{0x15, 0x00},215	{0x01, 0x80},216	{0x02, 0x80},217	{0x04, 0x70},218	{0x0d, 0x40},219	{0x0f, 0x47},220	{0x11, 0x81},221	{0x32, 0x36},222	{0x33, 0x0C},223	{0x34, 0x00},224	{0x35, 0x90},225	{0x12, 0x40},226	{0x17, 0x1f},227	{0x18, 0x5f},228	{0x19, 0x00},229	{0x1a, 0x68},230};231static const u8 ov361x_bridge_start_1024[][2] = {232	{0xf1, 0x60},  /* Hsize[7:0] */233	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */234	{0x89, 0x04},  /* Vsize[7:0] */235	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */236	{0x8b, 0x03},  /* for Iso */237	{0x8c, 0x01},  /* RAW input  */238	{0x8d, 0x10},239	{0x1c, 0x00},  /* RAW output, Iso transfer */240	{0x1d, 0x48},241	{0x1d, 0x00},242	{0x1d, 0xff},243	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */244	{0x1d, 0x2e},  /* for Iso */245	{0x1d, 0x1e},246};247 248static const u8 ov361x_start_640[][2] = {249	{0x12, 0x80},250	{0x13, 0xcf},251	{0x14, 0x40},252	{0x15, 0x00},253	{0x01, 0x80},254	{0x02, 0x80},255	{0x04, 0x70},256	{0x0d, 0x40},257	{0x0f, 0x47},258	{0x11, 0x81},259	{0x32, 0x36},260	{0x33, 0x0C},261	{0x34, 0x00},262	{0x35, 0x90},263	{0x12, 0x40},264	{0x17, 0x1f},265	{0x18, 0x5f},266	{0x19, 0x00},267	{0x1a, 0x68},268};269 270static const u8 ov361x_bridge_start_640[][2] = {271	{0xf1, 0x60},  /* Hsize[7:0]*/272	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */273	{0x89, 0x04},  /* Vsize[7:0] */274	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */275	{0x8b, 0x03},  /* for Iso */276	{0x8c, 0x01},  /* RAW input */277	{0x8d, 0x10},278	{0x1c, 0x00},  /* RAW output, Iso transfer */279	{0x1d, 0x48},280	{0x1d, 0x00},281	{0x1d, 0xff},282	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */283	{0x1d, 0x2e},  /* for Iso */284	{0x1d, 0x1e},285};286 287static const u8 ov361x_start_320[][2] = {288	{0x12, 0x80},289	{0x13, 0xcf},290	{0x14, 0x40},291	{0x15, 0x00},292	{0x01, 0x80},293	{0x02, 0x80},294	{0x04, 0x70},295	{0x0d, 0x40},296	{0x0f, 0x47},297	{0x11, 0x81},298	{0x32, 0x36},299	{0x33, 0x0C},300	{0x34, 0x00},301	{0x35, 0x90},302	{0x12, 0x40},303	{0x17, 0x1f},304	{0x18, 0x5f},305	{0x19, 0x00},306	{0x1a, 0x68},307};308 309static const u8 ov361x_bridge_start_320[][2] = {310	{0xf1, 0x60},  /* Hsize[7:0] */311	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */312	{0x89, 0x04},  /* Vsize[7:0] */313	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */314	{0x8b, 0x03},  /* for Iso */315	{0x8c, 0x01},  /* RAW input */316	{0x8d, 0x10},317	{0x1c, 0x00},  /* RAW output, Iso transfer; */318	{0x1d, 0x48},319	{0x1d, 0x00},320	{0x1d, 0xff},321	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */322	{0x1d, 0x2e},  /* for Iso */323	{0x1d, 0x1e},324};325 326static const u8 ov361x_start_160[][2] = {327	{0x12, 0x80},328	{0x13, 0xcf},329	{0x14, 0x40},330	{0x15, 0x00},331	{0x01, 0x80},332	{0x02, 0x80},333	{0x04, 0x70},334	{0x0d, 0x40},335	{0x0f, 0x47},336	{0x11, 0x81},337	{0x32, 0x36},338	{0x33, 0x0C},339	{0x34, 0x00},340	{0x35, 0x90},341	{0x12, 0x40},342	{0x17, 0x1f},343	{0x18, 0x5f},344	{0x19, 0x00},345	{0x1a, 0x68},346};347 348static const u8 ov361x_bridge_start_160[][2] = {349	{0xf1, 0x60},  /* Hsize[7:0] */350	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */351	{0x89, 0x04},  /* Vsize[7:0] */352	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */353	{0x8b, 0x03},  /* for Iso */354	{0x8c, 0x01},  /* RAW input */355	{0x8d, 0x10},356	{0x1c, 0x00},  /* RAW output, Iso transfer */357	{0x1d, 0x48},358	{0x1d, 0x00},359	{0x1d, 0xff},360	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */361	{0x1d, 0x2e},  /* for Iso */362	{0x1d, 0x1e},363};364 365static const u8 bridge_init[][2] = {366	{0x88, 0xf8},367	{0x89, 0xff},368	{0x76, 0x03},369	{0x92, 0x03},370	{0x95, 0x10},371	{0xe2, 0x00},372	{0xe7, 0x3e},373	{0x8d, 0x1c},374	{0x8e, 0x00},375	{0x8f, 0x00},376	{0x1f, 0x00},377	{0xc3, 0xf9},378	{0x89, 0xff},379	{0x88, 0xf8},380	{0x76, 0x03},381	{0x92, 0x01},382	{0x93, 0x18},383	{0x1c, 0x0a},384	{0x1d, 0x48},385	{0xc0, 0x50},386	{0xc1, 0x3c},387	{0x34, 0x05},388	{0xc2, 0x0c},389	{0xc3, 0xf9},390	{0x34, 0x05},391	{0xe7, 0x2e},392	{0x31, 0xf9},393	{0x35, 0x02},394	{0xd9, 0x10},395	{0x25, 0x42},396	{0x94, 0x11},397};398 399static const u8 ov965x_init[][2] = {400	{0x12, 0x80},	/* com7 - SSCB reset */401	{0x00, 0x00},	/* gain */402	{0x01, 0x80},	/* blue */403	{0x02, 0x80},	/* red */404	{0x03, 0x1b},	/* vref */405	{0x04, 0x03},	/* com1 - exposure low bits */406	{0x0b, 0x57},	/* ver */407	{0x0e, 0x61},	/* com5 */408	{0x0f, 0x42},	/* com6 */409	{0x11, 0x00},	/* clkrc */410	{0x12, 0x02},	/* com7 - 15fps VGA YUYV */411	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */412	{0x14, 0x28},	/* com9 */413	{0x16, 0x24},	/* reg16 */414	{0x17, 0x1d},	/* hstart*/415	{0x18, 0xbd},	/* hstop */416	{0x19, 0x01},	/* vstrt */417	{0x1a, 0x81},	/* vstop*/418	{0x1e, 0x04},	/* mvfp */419	{0x24, 0x3c},	/* aew */420	{0x25, 0x36},	/* aeb */421	{0x26, 0x71},	/* vpt */422	{0x27, 0x08},	/* bbias */423	{0x28, 0x08},	/* gbbias */424	{0x29, 0x15},	/* gr com */425	{0x2a, 0x00},	/* exhch */426	{0x2b, 0x00},	/* exhcl */427	{0x2c, 0x08},	/* rbias */428	{0x32, 0xff},	/* href */429	{0x33, 0x00},	/* chlf */430	{0x34, 0x3f},	/* aref1 */431	{0x35, 0x00},	/* aref2 */432	{0x36, 0xf8},	/* aref3 */433	{0x38, 0x72},	/* adc2 */434	{0x39, 0x57},	/* aref4 */435	{0x3a, 0x80},	/* tslb - yuyv */436	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */437	{0x3d, 0x99},	/* com13 */438	{0x3f, 0xc1},	/* edge */439	{0x40, 0xc0},	/* com15 */440	{0x41, 0x40},	/* com16 */441	{0x42, 0xc0},	/* com17 */442	{0x43, 0x0a},	/* rsvd */443	{0x44, 0xf0},444	{0x45, 0x46},445	{0x46, 0x62},446	{0x47, 0x2a},447	{0x48, 0x3c},448	{0x4a, 0xfc},449	{0x4b, 0xfc},450	{0x4c, 0x7f},451	{0x4d, 0x7f},452	{0x4e, 0x7f},453	{0x4f, 0x98},	/* matrix */454	{0x50, 0x98},455	{0x51, 0x00},456	{0x52, 0x28},457	{0x53, 0x70},458	{0x54, 0x98},459	{0x58, 0x1a},	/* matrix coef sign */460	{0x59, 0x85},	/* AWB control */461	{0x5a, 0xa9},462	{0x5b, 0x64},463	{0x5c, 0x84},464	{0x5d, 0x53},465	{0x5e, 0x0e},466	{0x5f, 0xf0},	/* AWB blue limit */467	{0x60, 0xf0},	/* AWB red limit */468	{0x61, 0xf0},	/* AWB green limit */469	{0x62, 0x00},	/* lcc1 */470	{0x63, 0x00},	/* lcc2 */471	{0x64, 0x02},	/* lcc3 */472	{0x65, 0x16},	/* lcc4 */473	{0x66, 0x01},	/* lcc5 */474	{0x69, 0x02},	/* hv */475	{0x6b, 0x5a},	/* dbvl */476	{0x6c, 0x04},477	{0x6d, 0x55},478	{0x6e, 0x00},479	{0x6f, 0x9d},480	{0x70, 0x21},	/* dnsth */481	{0x71, 0x78},482	{0x72, 0x00},	/* poidx */483	{0x73, 0x01},	/* pckdv */484	{0x74, 0x3a},	/* xindx */485	{0x75, 0x35},	/* yindx */486	{0x76, 0x01},487	{0x77, 0x02},488	{0x7a, 0x12},	/* gamma curve */489	{0x7b, 0x08},490	{0x7c, 0x16},491	{0x7d, 0x30},492	{0x7e, 0x5e},493	{0x7f, 0x72},494	{0x80, 0x82},495	{0x81, 0x8e},496	{0x82, 0x9a},497	{0x83, 0xa4},498	{0x84, 0xac},499	{0x85, 0xb8},500	{0x86, 0xc3},501	{0x87, 0xd6},502	{0x88, 0xe6},503	{0x89, 0xf2},504	{0x8a, 0x03},505	{0x8c, 0x89},	/* com19 */506	{0x14, 0x28},	/* com9 */507	{0x90, 0x7d},508	{0x91, 0x7b},509	{0x9d, 0x03},	/* lcc6 */510	{0x9e, 0x04},	/* lcc7 */511	{0x9f, 0x7a},512	{0xa0, 0x79},513	{0xa1, 0x40},	/* aechm */514	{0xa4, 0x50},	/* com21 */515	{0xa5, 0x68},	/* com26 */516	{0xa6, 0x4a},	/* AWB green */517	{0xa8, 0xc1},	/* refa8 */518	{0xa9, 0xef},	/* refa9 */519	{0xaa, 0x92},520	{0xab, 0x04},521	{0xac, 0x80},	/* black level control */522	{0xad, 0x80},523	{0xae, 0x80},524	{0xaf, 0x80},525	{0xb2, 0xf2},526	{0xb3, 0x20},527	{0xb4, 0x20},	/* ctrlb4 */528	{0xb5, 0x00},529	{0xb6, 0xaf},530	{0xbb, 0xae},531	{0xbc, 0x7f},	/* ADC channel offsets */532	{0xdb, 0x7f},533	{0xbe, 0x7f},534	{0xbf, 0x7f},535	{0xc0, 0xe2},536	{0xc1, 0xc0},537	{0xc2, 0x01},538	{0xc3, 0x4e},539	{0xc6, 0x85},540	{0xc7, 0x80},	/* com24 */541	{0xc9, 0xe0},542	{0xca, 0xe8},543	{0xcb, 0xf0},544	{0xcc, 0xd8},545	{0xcd, 0xf1},546	{0x4f, 0x98},	/* matrix */547	{0x50, 0x98},548	{0x51, 0x00},549	{0x52, 0x28},550	{0x53, 0x70},551	{0x54, 0x98},552	{0x58, 0x1a},553	{0xff, 0x41},	/* read 41, write ff 00 */554	{0x41, 0x40},	/* com16 */555 556	{0xc5, 0x03},	/* 60 Hz banding filter */557	{0x6a, 0x02},	/* 50 Hz banding filter */558 559	{0x12, 0x62},	/* com7 - 30fps VGA YUV */560	{0x36, 0xfa},	/* aref3 */561	{0x69, 0x0a},	/* hv */562	{0x8c, 0x89},	/* com22 */563	{0x14, 0x28},	/* com9 */564	{0x3e, 0x0c},565	{0x41, 0x40},	/* com16 */566	{0x72, 0x00},567	{0x73, 0x00},568	{0x74, 0x3a},569	{0x75, 0x35},570	{0x76, 0x01},571	{0xc7, 0x80},572	{0x03, 0x12},	/* vref */573	{0x17, 0x16},	/* hstart */574	{0x18, 0x02},	/* hstop */575	{0x19, 0x01},	/* vstrt */576	{0x1a, 0x3d},	/* vstop */577	{0x32, 0xff},	/* href */578	{0xc0, 0xaa},579};580 581static const u8 bridge_init_2[][2] = {582	{0x94, 0xaa},583	{0xf1, 0x60},584	{0xe5, 0x04},585	{0xc0, 0x50},586	{0xc1, 0x3c},587	{0x8c, 0x00},588	{0x8d, 0x1c},589	{0x34, 0x05},590 591	{0xc2, 0x0c},592	{0xc3, 0xf9},593	{0xda, 0x01},594	{0x50, 0x00},595	{0x51, 0xa0},596	{0x52, 0x3c},597	{0x53, 0x00},598	{0x54, 0x00},599	{0x55, 0x00},600	{0x57, 0x00},601	{0x5c, 0x00},602	{0x5a, 0xa0},603	{0x5b, 0x78},604	{0x35, 0x02},605	{0xd9, 0x10},606	{0x94, 0x11},607};608 609static const u8 ov965x_init_2[][2] = {610	{0x3b, 0xc4},611	{0x1e, 0x04},	/* mvfp */612	{0x13, 0xe0},	/* com8 */613	{0x00, 0x00},	/* gain */614	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */615	{0x11, 0x03},	/* clkrc */616	{0x6b, 0x5a},	/* dblv */617	{0x6a, 0x05},618	{0xc5, 0x07},619	{0xa2, 0x4b},620	{0xa3, 0x3e},621	{0x2d, 0x00},622	{0xff, 0x42},	/* read 42, write ff 00 */623	{0x42, 0xc0},	/* com17 */624	{0x2d, 0x00},625	{0xff, 0x42},	/* read 42, write ff 00 */626	{0x42, 0xc1},	/* com17 */627/* sharpness */628	{0x3f, 0x01},629	{0xff, 0x42},	/* read 42, write ff 00 */630	{0x42, 0xc1},	/* com17 */631/* saturation */632	{0x4f, 0x98},	/* matrix */633	{0x50, 0x98},634	{0x51, 0x00},635	{0x52, 0x28},636	{0x53, 0x70},637	{0x54, 0x98},638	{0x58, 0x1a},639	{0xff, 0x41},	/* read 41, write ff 00 */640	{0x41, 0x40},	/* com16 */641/* contrast */642	{0x56, 0x40},643/* brightness */644	{0x55, 0x8f},645/* expo */646	{0x10, 0x25},	/* aech - exposure high bits */647	{0xff, 0x13},	/* read 13, write ff 00 */648	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */649};650 651static const u8 ov971x_init[][2] = {652	{0x12, 0x80},653	{0x09, 0x10},654	{0x1e, 0x07},655	{0x5f, 0x18},656	{0x69, 0x04},657	{0x65, 0x2a},658	{0x68, 0x0a},659	{0x39, 0x28},660	{0x4d, 0x90},661	{0xc1, 0x80},662	{0x0c, 0x30},663	{0x6d, 0x02},664	{0x96, 0xf1},665	{0xbc, 0x68},666	{0x12, 0x00},667	{0x3b, 0x00},668	{0x97, 0x80},669	{0x17, 0x25},670	{0x18, 0xa2},671	{0x19, 0x01},672	{0x1a, 0xca},673	{0x03, 0x0a},674	{0x32, 0x07},675	{0x98, 0x40},	/*{0x98, 0x00},*/676	{0x99, 0xA0},	/*{0x99, 0x00},*/677	{0x9a, 0x01},	/*{0x9a, 0x00},*/678	{0x57, 0x00},679	{0x58, 0x78},	/*{0x58, 0xc8},*/680	{0x59, 0x50},	/*{0x59, 0xa0},*/681	{0x4c, 0x13},682	{0x4b, 0x36},683	{0x3d, 0x3c},684	{0x3e, 0x03},685	{0xbd, 0x50},	/*{0xbd, 0xa0},*/686	{0xbe, 0x78},	/*{0xbe, 0xc8},*/687	{0x4e, 0x55},688	{0x4f, 0x55},689	{0x50, 0x55},690	{0x51, 0x55},691	{0x24, 0x55},692	{0x25, 0x40},693	{0x26, 0xa1},694	{0x5c, 0x59},695	{0x5d, 0x00},696	{0x11, 0x00},697	{0x2a, 0x98},698	{0x2b, 0x06},699	{0x2d, 0x00},700	{0x2e, 0x00},701	{0x13, 0xa5},702	{0x14, 0x40},703	{0x4a, 0x00},704	{0x49, 0xce},705	{0x22, 0x03},706	{0x09, 0x00}707};708 709static const u8 ov965x_start_1_vga[][2] = {	/* same for qvga */710	{0x12, 0x62},	/* com7 - 30fps VGA YUV */711	{0x36, 0xfa},	/* aref3 */712	{0x69, 0x0a},	/* hv */713	{0x8c, 0x89},	/* com22 */714	{0x14, 0x28},	/* com9 */715	{0x3e, 0x0c},	/* com14 */716	{0x41, 0x40},	/* com16 */717	{0x72, 0x00},718	{0x73, 0x00},719	{0x74, 0x3a},720	{0x75, 0x35},721	{0x76, 0x01},722	{0xc7, 0x80},	/* com24 */723	{0x03, 0x12},	/* vref */724	{0x17, 0x16},	/* hstart */725	{0x18, 0x02},	/* hstop */726	{0x19, 0x01},	/* vstrt */727	{0x1a, 0x3d},	/* vstop */728	{0x32, 0xff},	/* href */729	{0xc0, 0xaa},730};731 732static const u8 ov965x_start_1_svga[][2] = {733	{0x12, 0x02},	/* com7 - YUYV - VGA 15 full resolution */734	{0x36, 0xf8},	/* aref3 */735	{0x69, 0x02},	/* hv */736	{0x8c, 0x0d},	/* com22 */737	{0x3e, 0x0c},	/* com14 */738	{0x41, 0x40},	/* com16 */739	{0x72, 0x00},740	{0x73, 0x01},741	{0x74, 0x3a},742	{0x75, 0x35},743	{0x76, 0x01},744	{0xc7, 0x80},	/* com24 */745	{0x03, 0x1b},	/* vref */746	{0x17, 0x1d},	/* hstart */747	{0x18, 0xbd},	/* hstop */748	{0x19, 0x01},	/* vstrt */749	{0x1a, 0x81},	/* vstop */750	{0x32, 0xff},	/* href */751	{0xc0, 0xe2},752};753 754static const u8 ov965x_start_1_xga[][2] = {755	{0x12, 0x02},	/* com7 */756	{0x36, 0xf8},	/* aref3 */757	{0x69, 0x02},	/* hv */758	{0x8c, 0x89},	/* com22 */759	{0x14, 0x28},	/* com9 */760	{0x3e, 0x0c},	/* com14 */761	{0x41, 0x40},	/* com16 */762	{0x72, 0x00},763	{0x73, 0x01},764	{0x74, 0x3a},765	{0x75, 0x35},766	{0x76, 0x01},767	{0xc7, 0x80},	/* com24 */768	{0x03, 0x1b},	/* vref */769	{0x17, 0x1d},	/* hstart */770	{0x18, 0xbd},	/* hstop */771	{0x19, 0x01},	/* vstrt */772	{0x1a, 0x81},	/* vstop */773	{0x32, 0xff},	/* href */774	{0xc0, 0xe2},775};776 777static const u8 ov965x_start_1_sxga[][2] = {778	{0x12, 0x02},	/* com7 */779	{0x36, 0xf8},	/* aref3 */780	{0x69, 0x02},	/* hv */781	{0x8c, 0x89},	/* com22 */782	{0x14, 0x28},	/* com9 */783	{0x3e, 0x0c},	/* com14 */784	{0x41, 0x40},	/* com16 */785	{0x72, 0x00},786	{0x73, 0x01},787	{0x74, 0x3a},788	{0x75, 0x35},789	{0x76, 0x01},790	{0xc7, 0x80},	/* com24 */791	{0x03, 0x1b},	/* vref */792	{0x17, 0x1d},	/* hstart */793	{0x18, 0x02},	/* hstop */794	{0x19, 0x01},	/* vstrt */795	{0x1a, 0x81},	/* vstop */796	{0x32, 0xff},	/* href */797	{0xc0, 0xe2},798};799 800static const u8 bridge_start_qvga[][2] = {801	{0x94, 0xaa},802	{0xf1, 0x60},803	{0xe5, 0x04},804	{0xc0, 0x50},805	{0xc1, 0x3c},806	{0x8c, 0x00},807	{0x8d, 0x1c},808	{0x34, 0x05},809 810	{0xc2, 0x4c},811	{0xc3, 0xf9},812	{0xda, 0x00},813	{0x50, 0x00},814	{0x51, 0xa0},815	{0x52, 0x78},816	{0x53, 0x00},817	{0x54, 0x00},818	{0x55, 0x00},819	{0x57, 0x00},820	{0x5c, 0x00},821	{0x5a, 0x50},822	{0x5b, 0x3c},823	{0x35, 0x02},824	{0xd9, 0x10},825	{0x94, 0x11},826};827 828static const u8 bridge_start_vga[][2] = {829	{0x94, 0xaa},830	{0xf1, 0x60},831	{0xe5, 0x04},832	{0xc0, 0x50},833	{0xc1, 0x3c},834	{0x8c, 0x00},835	{0x8d, 0x1c},836	{0x34, 0x05},837	{0xc2, 0x0c},838	{0xc3, 0xf9},839	{0xda, 0x01},840	{0x50, 0x00},841	{0x51, 0xa0},842	{0x52, 0x3c},843	{0x53, 0x00},844	{0x54, 0x00},845	{0x55, 0x00},846	{0x57, 0x00},847	{0x5c, 0x00},848	{0x5a, 0xa0},849	{0x5b, 0x78},850	{0x35, 0x02},851	{0xd9, 0x10},852	{0x94, 0x11},853};854 855static const u8 bridge_start_svga[][2] = {856	{0x94, 0xaa},857	{0xf1, 0x60},858	{0xe5, 0x04},859	{0xc0, 0xa0},860	{0xc1, 0x80},861	{0x8c, 0x00},862	{0x8d, 0x1c},863	{0x34, 0x05},864	{0xc2, 0x4c},865	{0xc3, 0xf9},866	{0x50, 0x00},867	{0x51, 0x40},868	{0x52, 0x00},869	{0x53, 0x00},870	{0x54, 0x00},871	{0x55, 0x88},872	{0x57, 0x00},873	{0x5c, 0x00},874	{0x5a, 0xc8},875	{0x5b, 0x96},876	{0x35, 0x02},877	{0xd9, 0x10},878	{0xda, 0x00},879	{0x94, 0x11},880};881 882static const u8 bridge_start_xga[][2] = {883	{0x94, 0xaa},884	{0xf1, 0x60},885	{0xe5, 0x04},886	{0xc0, 0xa0},887	{0xc1, 0x80},888	{0x8c, 0x00},889	{0x8d, 0x1c},890	{0x34, 0x05},891	{0xc2, 0x4c},892	{0xc3, 0xf9},893	{0x50, 0x00},894	{0x51, 0x40},895	{0x52, 0x00},896	{0x53, 0x00},897	{0x54, 0x00},898	{0x55, 0x88},899	{0x57, 0x00},900	{0x5c, 0x01},901	{0x5a, 0x00},902	{0x5b, 0xc0},903	{0x35, 0x02},904	{0xd9, 0x10},905	{0xda, 0x01},906	{0x94, 0x11},907};908 909static const u8 bridge_start_sxga[][2] = {910	{0x94, 0xaa},911	{0xf1, 0x60},912	{0xe5, 0x04},913	{0xc0, 0xa0},914	{0xc1, 0x80},915	{0x8c, 0x00},916	{0x8d, 0x1c},917	{0x34, 0x05},918	{0xc2, 0x0c},919	{0xc3, 0xf9},920	{0xda, 0x00},921	{0x35, 0x02},922	{0xd9, 0x10},923	{0x94, 0x11},924};925 926static const u8 ov965x_start_2_qvga[][2] = {927	{0x3b, 0xe4},	/* com11 - night mode 1/4 frame rate */928	{0x1e, 0x04},	/* mvfp */929	{0x13, 0xe0},	/* com8 */930	{0x00, 0x00},931	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */932	{0x11, 0x01},	/* clkrc */933	{0x6b, 0x5a},	/* dblv */934	{0x6a, 0x02},	/* 50 Hz banding filter */935	{0xc5, 0x03},	/* 60 Hz banding filter */936	{0xa2, 0x96},	/* bd50 */937	{0xa3, 0x7d},	/* bd60 */938 939	{0xff, 0x13},	/* read 13, write ff 00 */940	{0x13, 0xe7},941	{0x3a, 0x80},	/* tslb - yuyv */942};943 944static const u8 ov965x_start_2_vga[][2] = {945	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */946	{0x1e, 0x04},	/* mvfp */947	{0x13, 0xe0},	/* com8 */948	{0x00, 0x00},949	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */950	{0x11, 0x03},	/* clkrc */951	{0x6b, 0x5a},	/* dblv */952	{0x6a, 0x05},	/* 50 Hz banding filter */953	{0xc5, 0x07},	/* 60 Hz banding filter */954	{0xa2, 0x4b},	/* bd50 */955	{0xa3, 0x3e},	/* bd60 */956 957	{0x2d, 0x00},	/* advfl */958};959 960static const u8 ov965x_start_2_svga[][2] = {	/* same for xga */961	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */962	{0x1e, 0x04},	/* mvfp */963	{0x13, 0xe0},	/* com8 */964	{0x00, 0x00},965	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */966	{0x11, 0x01},	/* clkrc */967	{0x6b, 0x5a},	/* dblv */968	{0x6a, 0x0c},	/* 50 Hz banding filter */969	{0xc5, 0x0f},	/* 60 Hz banding filter */970	{0xa2, 0x4e},	/* bd50 */971	{0xa3, 0x41},	/* bd60 */972};973 974static const u8 ov965x_start_2_sxga[][2] = {975	{0x13, 0xe0},	/* com8 */976	{0x00, 0x00},977	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */978	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */979	{0x1e, 0x04},	/* mvfp */980	{0x11, 0x01},	/* clkrc */981	{0x6b, 0x5a},	/* dblv */982	{0x6a, 0x0c},	/* 50 Hz banding filter */983	{0xc5, 0x0f},	/* 60 Hz banding filter */984	{0xa2, 0x4e},	/* bd50 */985	{0xa3, 0x41},	/* bd60 */986};987 988static const u8 ov562x_init[][2] = {989	{0x88, 0x20},990	{0x89, 0x0a},991	{0x8a, 0x90},992	{0x8b, 0x06},993	{0x8c, 0x01},994	{0x8d, 0x10},995	{0x1c, 0x00},996	{0x1d, 0x48},997	{0x1d, 0x00},998	{0x1d, 0xff},999	{0x1c, 0x0a},1000	{0x1d, 0x2e},1001	{0x1d, 0x1e},1002};1003 1004static const u8 ov562x_init_2[][2] = {1005	{0x12, 0x80},1006	{0x11, 0x41},1007	{0x13, 0x00},1008	{0x10, 0x1e},1009	{0x3b, 0x07},1010	{0x5b, 0x40},1011	{0x39, 0x07},1012	{0x53, 0x02},1013	{0x54, 0x60},1014	{0x04, 0x20},1015	{0x27, 0x04},1016	{0x3d, 0x40},1017	{0x36, 0x00},1018	{0xc5, 0x04},1019	{0x4e, 0x00},1020	{0x4f, 0x93},1021	{0x50, 0x7b},1022	{0xca, 0x0c},1023	{0xcb, 0x0f},1024	{0x39, 0x07},1025	{0x4a, 0x10},1026	{0x3e, 0x0a},1027	{0x3d, 0x00},1028	{0x0c, 0x38},1029	{0x38, 0x90},1030	{0x46, 0x30},1031	{0x4f, 0x93},1032	{0x50, 0x7b},1033	{0xab, 0x00},1034	{0xca, 0x0c},1035	{0xcb, 0x0f},1036	{0x37, 0x02},1037	{0x44, 0x48},1038	{0x8d, 0x44},1039	{0x2a, 0x00},1040	{0x2b, 0x00},1041	{0x32, 0x00},1042	{0x38, 0x90},1043	{0x53, 0x02},1044	{0x54, 0x60},1045	{0x12, 0x00},1046	{0x17, 0x12},1047	{0x18, 0xb4},1048	{0x19, 0x0c},1049	{0x1a, 0xf4},1050	{0x03, 0x4a},1051	{0x89, 0x20},1052	{0x83, 0x80},1053	{0xb7, 0x9d},1054	{0xb6, 0x11},1055	{0xb5, 0x55},1056	{0xb4, 0x00},1057	{0xa9, 0xf0},1058	{0xa8, 0x0a},1059	{0xb8, 0xf0},1060	{0xb9, 0xf0},1061	{0xba, 0xf0},1062	{0x81, 0x07},1063	{0x63, 0x44},1064	{0x13, 0xc7},1065	{0x14, 0x60},1066	{0x33, 0x75},1067	{0x2c, 0x00},1068	{0x09, 0x00},1069	{0x35, 0x30},1070	{0x27, 0x04},1071	{0x3c, 0x07},1072	{0x3a, 0x0a},1073	{0x3b, 0x07},1074	{0x01, 0x40},1075	{0x02, 0x40},1076	{0x16, 0x40},1077	{0x52, 0xb0},1078	{0x51, 0x83},1079	{0x21, 0xbb},1080	{0x22, 0x10},1081	{0x23, 0x03},1082	{0x35, 0x38},1083	{0x20, 0x90},1084	{0x28, 0x30},1085	{0x73, 0xe1},1086	{0x6c, 0x00},1087	{0x6d, 0x80},1088	{0x6e, 0x00},1089	{0x70, 0x04},1090	{0x71, 0x00},1091	{0x8d, 0x04},1092	{0x64, 0x00},1093	{0x65, 0x00},1094	{0x66, 0x00},1095	{0x67, 0x00},1096	{0x68, 0x00},1097	{0x69, 0x00},1098	{0x6a, 0x00},1099	{0x6b, 0x00},1100	{0x71, 0x94},1101	{0x74, 0x20},1102	{0x80, 0x09},1103	{0x85, 0xc0},1104};1105 1106static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)1107{1108	struct usb_device *udev = gspca_dev->dev;1109	int ret;1110 1111	if (gspca_dev->usb_err < 0)1112		return;1113	gspca_dev->usb_buf[0] = val;1114	ret = usb_control_msg(udev,1115			      usb_sndctrlpipe(udev, 0),1116			      0x01,1117			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,1118			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);1119	if (ret < 0) {1120		pr_err("reg_w failed %d\n", ret);1121		gspca_dev->usb_err = ret;1122	}1123}1124 1125static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)1126{1127	gspca_dbg(gspca_dev, D_USBO, "reg_w [%04x] = %02x\n", reg, val);1128	reg_w_i(gspca_dev, reg, val);1129}1130 1131static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)1132{1133	struct usb_device *udev = gspca_dev->dev;1134	int ret;1135 1136	if (gspca_dev->usb_err < 0)1137		return 0;1138	ret = usb_control_msg(udev,1139			      usb_rcvctrlpipe(udev, 0),1140			      0x01,1141			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,1142			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);1143	gspca_dbg(gspca_dev, D_USBI, "reg_r [%04x] -> %02x\n",1144		  reg, gspca_dev->usb_buf[0]);1145	if (ret < 0) {1146		pr_err("reg_r err %d\n", ret);1147		gspca_dev->usb_err = ret;1148		return 0;1149	}1150	return gspca_dev->usb_buf[0];1151}1152 1153static int sccb_check_status(struct gspca_dev *gspca_dev)1154{1155	u8 data;1156	int i;1157 1158	for (i = 0; i < 5; i++) {1159		msleep(20);1160		data = reg_r(gspca_dev, OV534_REG_STATUS);1161 1162		switch (data) {1163		case 0x00:1164			return 1;1165		case 0x04:1166			return 0;1167		case 0x03:1168			break;1169		default:1170			gspca_dbg(gspca_dev, D_USBI|D_USBO,1171				  "sccb status 0x%02x, attempt %d/5\n",1172				  data, i + 1);1173		}1174	}1175	return 0;1176}1177 1178static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)1179{1180	gspca_dbg(gspca_dev, D_USBO, "sccb_write [%02x] = %02x\n", reg, val);1181	reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);1182	reg_w_i(gspca_dev, OV534_REG_WRITE, val);1183	reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);1184 1185	if (!sccb_check_status(gspca_dev))1186		pr_err("sccb_write failed\n");1187}1188 1189static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)1190{1191	reg_w(gspca_dev, OV534_REG_SUBADDR, reg);1192	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);1193	if (!sccb_check_status(gspca_dev))1194		pr_err("sccb_read failed 1\n");1195 1196	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);1197	if (!sccb_check_status(gspca_dev))1198		pr_err("sccb_read failed 2\n");1199 1200	return reg_r(gspca_dev, OV534_REG_READ);1201}1202 1203/* output a bridge sequence (reg - val) */1204static void reg_w_array(struct gspca_dev *gspca_dev,1205			const u8 (*data)[2], int len)1206{1207	while (--len >= 0) {1208		reg_w(gspca_dev, (*data)[0], (*data)[1]);1209		data++;1210	}1211}1212 1213/* output a sensor sequence (reg - val) */1214static void sccb_w_array(struct gspca_dev *gspca_dev,1215			const u8 (*data)[2], int len)1216{1217	while (--len >= 0) {1218		if ((*data)[0] != 0xff) {1219			sccb_write(gspca_dev, (*data)[0], (*data)[1]);1220		} else {1221			sccb_read(gspca_dev, (*data)[1]);1222			sccb_write(gspca_dev, 0xff, 0x00);1223		}1224		data++;1225	}1226}1227 1228/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.1229 * (direction and output)? */1230static void set_led(struct gspca_dev *gspca_dev, int status)1231{1232	u8 data;1233 1234	gspca_dbg(gspca_dev, D_CONF, "led status: %d\n", status);1235 1236	data = reg_r(gspca_dev, 0x21);1237	data |= 0x80;1238	reg_w(gspca_dev, 0x21, data);1239 1240	data = reg_r(gspca_dev, 0x23);1241	if (status)1242		data |= 0x80;1243	else1244		data &= ~0x80;1245 1246	reg_w(gspca_dev, 0x23, data);1247 1248	if (!status) {1249		data = reg_r(gspca_dev, 0x21);1250		data &= ~0x80;1251		reg_w(gspca_dev, 0x21, data);1252	}1253}1254 1255static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)1256{1257	struct sd *sd = (struct sd *) gspca_dev;1258	u8 val;1259	s8 sval;1260 1261	if (sd->sensor == SENSOR_OV562x) {1262		sval = brightness;1263		val = 0x76;1264		val += sval;1265		sccb_write(gspca_dev, 0x24, val);1266		val = 0x6a;1267		val += sval;1268		sccb_write(gspca_dev, 0x25, val);1269		if (sval < -40)1270			val = 0x71;1271		else if (sval < 20)1272			val = 0x94;1273		else1274			val = 0xe6;1275		sccb_write(gspca_dev, 0x26, val);1276	} else {1277		val = brightness;1278		if (val < 8)1279			val = 15 - val;		/* f .. 8 */1280		else1281			val = val - 8;		/* 0 .. 7 */1282		sccb_write(gspca_dev, 0x55,	/* brtn - brightness adjustment */1283				0x0f | (val << 4));1284	}1285}1286 1287static void setcontrast(struct gspca_dev *gspca_dev, s32 val)1288{1289	sccb_write(gspca_dev, 0x56,	/* cnst1 - contrast 1 ctrl coeff */1290			val << 4);1291}1292 1293static void setautogain(struct gspca_dev *gspca_dev, s32 autogain)1294{1295	u8 val;1296 1297/*fixme: should adjust agc/awb/aec by different controls */1298	val = sccb_read(gspca_dev, 0x13);		/* com8 */1299	sccb_write(gspca_dev, 0xff, 0x00);1300	if (autogain)1301		val |= 0x05;		/* agc & aec */1302	else1303		val &= 0xfa;1304	sccb_write(gspca_dev, 0x13, val);1305}1306 1307static void setexposure(struct gspca_dev *gspca_dev, s32 exposure)1308{1309	static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};1310	u8 val;1311 1312	sccb_write(gspca_dev, 0x10, expo[exposure]);	/* aec[9:2] */1313 1314	val = sccb_read(gspca_dev, 0x13);		/* com8 */1315	sccb_write(gspca_dev, 0xff, 0x00);1316	sccb_write(gspca_dev, 0x13, val);1317 1318	val = sccb_read(gspca_dev, 0xa1);		/* aech */1319	sccb_write(gspca_dev, 0xff, 0x00);1320	sccb_write(gspca_dev, 0xa1, val & 0xe0);	/* aec[15:10] = 0 */1321}1322 1323static void setsharpness(struct gspca_dev *gspca_dev, s32 val)1324{1325	if (val < 0) {				/* auto */1326		val = sccb_read(gspca_dev, 0x42);	/* com17 */1327		sccb_write(gspca_dev, 0xff, 0x00);1328		sccb_write(gspca_dev, 0x42, val | 0x40);1329				/* Edge enhancement strength auto adjust */1330		return;1331	}1332	if (val != 0)1333		val = 1 << (val - 1);1334	sccb_write(gspca_dev, 0x3f,	/* edge - edge enhance. factor */1335			val);1336	val = sccb_read(gspca_dev, 0x42);		/* com17 */1337	sccb_write(gspca_dev, 0xff, 0x00);1338	sccb_write(gspca_dev, 0x42, val & 0xbf);1339}1340 1341static void setsatur(struct gspca_dev *gspca_dev, s32 val)1342{1343	u8 val1, val2, val3;1344	static const u8 matrix[5][2] = {1345		{0x14, 0x38},1346		{0x1e, 0x54},1347		{0x28, 0x70},1348		{0x32, 0x8c},1349		{0x48, 0x90}1350	};1351 1352	val1 = matrix[val][0];1353	val2 = matrix[val][1];1354	val3 = val1 + val2;1355	sccb_write(gspca_dev, 0x4f, val3);	/* matrix coeff */1356	sccb_write(gspca_dev, 0x50, val3);1357	sccb_write(gspca_dev, 0x51, 0x00);1358	sccb_write(gspca_dev, 0x52, val1);1359	sccb_write(gspca_dev, 0x53, val2);1360	sccb_write(gspca_dev, 0x54, val3);1361	sccb_write(gspca_dev, 0x58, 0x1a);	/* mtxs - coeff signs */1362 1363	val1 = sccb_read(gspca_dev, 0x41);	/* com16 */1364	sccb_write(gspca_dev, 0xff, 0x00);1365	sccb_write(gspca_dev, 0x41, val1);1366}1367 1368static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq)1369{1370	u8 val;1371 1372	val = sccb_read(gspca_dev, 0x13);		/* com8 */1373	sccb_write(gspca_dev, 0xff, 0x00);1374	if (freq == 0) {1375		sccb_write(gspca_dev, 0x13, val & 0xdf);1376		return;1377	}1378	sccb_write(gspca_dev, 0x13, val | 0x20);1379 1380	val = sccb_read(gspca_dev, 0x42);		/* com17 */1381	sccb_write(gspca_dev, 0xff, 0x00);1382	if (freq == 1)1383		val |= 0x01;1384	else1385		val &= 0xfe;1386	sccb_write(gspca_dev, 0x42, val);1387}1388 1389/* this function is called at probe time */1390static int sd_config(struct gspca_dev *gspca_dev,1391		     const struct usb_device_id *id)1392{1393	return 0;1394}1395 1396/* this function is called at probe and resume time */1397static int sd_init(struct gspca_dev *gspca_dev)1398{1399	struct sd *sd = (struct sd *) gspca_dev;1400	u16 sensor_id;1401 1402	/* reset bridge */1403	reg_w(gspca_dev, 0xe7, 0x3a);1404	reg_w(gspca_dev, 0xe0, 0x08);1405	msleep(100);1406 1407	/* initialize the sensor address */1408	reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);1409 1410	/* reset sensor */1411	sccb_write(gspca_dev, 0x12, 0x80);1412	msleep(10);1413 1414	/* probe the sensor */1415	sccb_read(gspca_dev, 0x0a);1416	sensor_id = sccb_read(gspca_dev, 0x0a) << 8;1417	sccb_read(gspca_dev, 0x0b);1418	sensor_id |= sccb_read(gspca_dev, 0x0b);1419	gspca_dbg(gspca_dev, D_PROBE, "Sensor ID: %04x\n", sensor_id);1420 1421	/* initialize */1422	if ((sensor_id & 0xfff0) == 0x9650) {1423		sd->sensor = SENSOR_OV965x;1424 1425		gspca_dev->cam.cam_mode = ov965x_mode;1426		gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);1427 1428		reg_w_array(gspca_dev, bridge_init,1429				ARRAY_SIZE(bridge_init));1430		sccb_w_array(gspca_dev, ov965x_init,1431				ARRAY_SIZE(ov965x_init));1432		reg_w_array(gspca_dev, bridge_init_2,1433				ARRAY_SIZE(bridge_init_2));1434		sccb_w_array(gspca_dev, ov965x_init_2,1435				ARRAY_SIZE(ov965x_init_2));1436		reg_w(gspca_dev, 0xe0, 0x00);1437		reg_w(gspca_dev, 0xe0, 0x01);1438		set_led(gspca_dev, 0);1439		reg_w(gspca_dev, 0xe0, 0x00);1440	} else if ((sensor_id & 0xfff0) == 0x9710) {1441		const char *p;1442		int l;1443 1444		sd->sensor = SENSOR_OV971x;1445 1446		gspca_dev->cam.cam_mode = ov971x_mode;1447		gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);1448 1449		gspca_dev->cam.bulk = 1;1450		gspca_dev->cam.bulk_size = 16384;1451		gspca_dev->cam.bulk_nurbs = 2;1452 1453		sccb_w_array(gspca_dev, ov971x_init,1454				ARRAY_SIZE(ov971x_init));1455 1456		/* set video format on bridge processor */1457		/* access bridge processor's video format registers at: 0x00 */1458		reg_w(gspca_dev, 0x1c, 0x00);1459		/*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/1460		reg_w(gspca_dev, 0x1d, 0x00);1461 1462		/* Will W. specific stuff1463		 * set VSYNC to1464		 *	output (0x1f) if first webcam1465		 *	input (0x17) if 2nd or 3rd webcam */1466		p = video_device_node_name(&gspca_dev->vdev);1467		l = strlen(p) - 1;1468		if (p[l] == '0')1469			reg_w(gspca_dev, 0x56, 0x1f);1470		else1471			reg_w(gspca_dev, 0x56, 0x17);1472	} else if ((sensor_id & 0xfff0) == 0x5620) {1473		sd->sensor = SENSOR_OV562x;1474		gspca_dev->cam.cam_mode = ov562x_mode;1475		gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);1476 1477		reg_w_array(gspca_dev, ov562x_init,1478				ARRAY_SIZE(ov562x_init));1479		sccb_w_array(gspca_dev, ov562x_init_2,1480				ARRAY_SIZE(ov562x_init_2));1481		reg_w(gspca_dev, 0xe0, 0x00);1482	} else if ((sensor_id & 0xfff0) == 0x3610) {1483		sd->sensor = SENSOR_OV361x;1484		gspca_dev->cam.cam_mode = ov361x_mode;1485		gspca_dev->cam.nmodes = ARRAY_SIZE(ov361x_mode);1486		reg_w(gspca_dev, 0xe7, 0x3a);1487		reg_w(gspca_dev, 0xf1, 0x60);1488		sccb_write(gspca_dev, 0x12, 0x80);1489	} else {1490		pr_err("Unknown sensor %04x", sensor_id);1491		return -EINVAL;1492	}1493 1494	return gspca_dev->usb_err;1495}1496 1497static int sd_start_ov361x(struct gspca_dev *gspca_dev)1498{1499	sccb_write(gspca_dev, 0x12, 0x80);1500	msleep(20);1501	switch (gspca_dev->curr_mode % (ov361x_last)) {1502	case ov361x_2048:1503		reg_w_array(gspca_dev, ov361x_bridge_start_2048,1504			    ARRAY_SIZE(ov361x_bridge_start_2048));1505		sccb_w_array(gspca_dev, ov361x_start_2048,1506			     ARRAY_SIZE(ov361x_start_2048));1507		break;1508	case ov361x_1600:1509		reg_w_array(gspca_dev, ov361x_bridge_start_1600,1510			    ARRAY_SIZE(ov361x_bridge_start_1600));1511		sccb_w_array(gspca_dev, ov361x_start_1600,1512			     ARRAY_SIZE(ov361x_start_1600));1513		break;1514	case ov361x_1024:1515		reg_w_array(gspca_dev, ov361x_bridge_start_1024,1516			    ARRAY_SIZE(ov361x_bridge_start_1024));1517		sccb_w_array(gspca_dev, ov361x_start_1024,1518			     ARRAY_SIZE(ov361x_start_1024));1519		break;1520	case ov361x_640:1521		reg_w_array(gspca_dev, ov361x_bridge_start_640,1522			    ARRAY_SIZE(ov361x_bridge_start_640));1523		sccb_w_array(gspca_dev, ov361x_start_640,1524			     ARRAY_SIZE(ov361x_start_640));1525		break;1526	case ov361x_320:1527		reg_w_array(gspca_dev, ov361x_bridge_start_320,1528			    ARRAY_SIZE(ov361x_bridge_start_320));1529		sccb_w_array(gspca_dev, ov361x_start_320,1530			     ARRAY_SIZE(ov361x_start_320));1531		break;1532	case ov361x_160:1533		reg_w_array(gspca_dev, ov361x_bridge_start_160,1534			    ARRAY_SIZE(ov361x_bridge_start_160));1535		sccb_w_array(gspca_dev, ov361x_start_160,1536			     ARRAY_SIZE(ov361x_start_160));1537		break;1538	}1539	reg_w(gspca_dev, 0xe0, 0x00); /* start transfer */1540 1541	return gspca_dev->usb_err;1542}1543 1544static int sd_start(struct gspca_dev *gspca_dev)1545{1546	struct sd *sd = (struct sd *) gspca_dev;1547 1548	if (sd->sensor == SENSOR_OV971x)1549		return gspca_dev->usb_err;1550	if (sd->sensor == SENSOR_OV562x)1551		return gspca_dev->usb_err;1552	if (sd->sensor == SENSOR_OV361x)1553		return sd_start_ov361x(gspca_dev);1554 1555	switch (gspca_dev->curr_mode) {1556	case QVGA_MODE:			/* 320x240 */1557		sccb_w_array(gspca_dev, ov965x_start_1_vga,1558				ARRAY_SIZE(ov965x_start_1_vga));1559		reg_w_array(gspca_dev, bridge_start_qvga,1560				ARRAY_SIZE(bridge_start_qvga));1561		sccb_w_array(gspca_dev, ov965x_start_2_qvga,1562				ARRAY_SIZE(ov965x_start_2_qvga));1563		break;1564	case VGA_MODE:			/* 640x480 */1565		sccb_w_array(gspca_dev, ov965x_start_1_vga,1566				ARRAY_SIZE(ov965x_start_1_vga));1567		reg_w_array(gspca_dev, bridge_start_vga,1568				ARRAY_SIZE(bridge_start_vga));1569		sccb_w_array(gspca_dev, ov965x_start_2_vga,1570				ARRAY_SIZE(ov965x_start_2_vga));1571		break;1572	case SVGA_MODE:			/* 800x600 */1573		sccb_w_array(gspca_dev, ov965x_start_1_svga,1574				ARRAY_SIZE(ov965x_start_1_svga));1575		reg_w_array(gspca_dev, bridge_start_svga,1576				ARRAY_SIZE(bridge_start_svga));1577		sccb_w_array(gspca_dev, ov965x_start_2_svga,1578				ARRAY_SIZE(ov965x_start_2_svga));1579		break;1580	case XGA_MODE:			/* 1024x768 */1581		sccb_w_array(gspca_dev, ov965x_start_1_xga,1582				ARRAY_SIZE(ov965x_start_1_xga));1583		reg_w_array(gspca_dev, bridge_start_xga,1584				ARRAY_SIZE(bridge_start_xga));1585		sccb_w_array(gspca_dev, ov965x_start_2_svga,1586				ARRAY_SIZE(ov965x_start_2_svga));1587		break;1588	default:1589/*	case SXGA_MODE:			 * 1280x1024 */1590		sccb_w_array(gspca_dev, ov965x_start_1_sxga,1591				ARRAY_SIZE(ov965x_start_1_sxga));1592		reg_w_array(gspca_dev, bridge_start_sxga,1593				ARRAY_SIZE(bridge_start_sxga));1594		sccb_w_array(gspca_dev, ov965x_start_2_sxga,1595				ARRAY_SIZE(ov965x_start_2_sxga));1596		break;1597	}1598 1599	reg_w(gspca_dev, 0xe0, 0x00);1600	reg_w(gspca_dev, 0xe0, 0x00);1601	set_led(gspca_dev, 1);1602	return gspca_dev->usb_err;1603}1604 1605static void sd_stopN(struct gspca_dev *gspca_dev)1606{1607	if (((struct sd *)gspca_dev)->sensor == SENSOR_OV361x) {1608		reg_w(gspca_dev, 0xe0, 0x01); /* stop transfer */1609		/* reg_w(gspca_dev, 0x31, 0x09); */1610		return;1611	}1612	reg_w(gspca_dev, 0xe0, 0x01);1613	set_led(gspca_dev, 0);1614	reg_w(gspca_dev, 0xe0, 0x00);1615}1616 1617/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */1618#define UVC_STREAM_EOH	(1 << 7)1619#define UVC_STREAM_ERR	(1 << 6)1620#define UVC_STREAM_STI	(1 << 5)1621#define UVC_STREAM_RES	(1 << 4)1622#define UVC_STREAM_SCR	(1 << 3)1623#define UVC_STREAM_PTS	(1 << 2)1624#define UVC_STREAM_EOF	(1 << 1)1625#define UVC_STREAM_FID	(1 << 0)1626 1627static void sd_pkt_scan(struct gspca_dev *gspca_dev,1628			u8 *data, int len)1629{1630	struct sd *sd = (struct sd *) gspca_dev;1631	__u32 this_pts;1632	u8 this_fid;1633	int remaining_len = len;1634	int payload_len;1635 1636	payload_len = gspca_dev->cam.bulk ? 2048 : 2040;1637	do {1638		len = min(remaining_len, payload_len);1639 1640		/* Payloads are prefixed with a UVC-style header.  We1641		   consider a frame to start when the FID toggles, or the PTS1642		   changes.  A frame ends when EOF is set, and we've received1643		   the correct number of bytes. */1644 1645		/* Verify UVC header.  Header length is always 12 */1646		if (data[0] != 12 || len < 12) {1647			gspca_dbg(gspca_dev, D_PACK, "bad header\n");1648			goto discard;1649		}1650 1651		/* Check errors */1652		if (data[1] & UVC_STREAM_ERR) {1653			gspca_dbg(gspca_dev, D_PACK, "payload error\n");1654			goto discard;1655		}1656 1657		/* Extract PTS and FID */1658		if (!(data[1] & UVC_STREAM_PTS)) {1659			gspca_dbg(gspca_dev, D_PACK, "PTS not present\n");1660			goto discard;1661		}1662		this_pts = (data[5] << 24) | (data[4] << 16)1663						| (data[3] << 8) | data[2];1664		this_fid = data[1] & UVC_STREAM_FID;1665 1666		/* If PTS or FID has changed, start a new frame. */1667		if (this_pts != sd->last_pts || this_fid != sd->last_fid) {1668			if (gspca_dev->last_packet_type == INTER_PACKET)1669				gspca_frame_add(gspca_dev, LAST_PACKET,1670						NULL, 0);1671			sd->last_pts = this_pts;1672			sd->last_fid = this_fid;1673			gspca_frame_add(gspca_dev, FIRST_PACKET,1674					data + 12, len - 12);1675		/* If this packet is marked as EOF, end the frame */1676		} else if (data[1] & UVC_STREAM_EOF) {1677			sd->last_pts = 0;1678			gspca_frame_add(gspca_dev, LAST_PACKET,1679					data + 12, len - 12);1680		} else {1681 1682			/* Add the data from this payload */1683			gspca_frame_add(gspca_dev, INTER_PACKET,1684					data + 12, len - 12);1685		}1686 1687		/* Done this payload */1688		goto scan_next;1689 1690discard:1691		/* Discard data until a new frame starts. */1692		gspca_dev->last_packet_type = DISCARD_PACKET;1693 1694scan_next:1695		remaining_len -= len;1696		data += len;1697	} while (remaining_len > 0);1698}1699 1700static int sd_s_ctrl(struct v4l2_ctrl *ctrl)1701{1702	struct gspca_dev *gspca_dev =1703		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);1704 1705	gspca_dev->usb_err = 0;1706 1707	if (!gspca_dev->streaming)1708		return 0;1709 1710	switch (ctrl->id) {1711	case V4L2_CID_BRIGHTNESS:1712		setbrightness(gspca_dev, ctrl->val);1713		break;1714	case V4L2_CID_CONTRAST:1715		setcontrast(gspca_dev, ctrl->val);1716		break;1717	case V4L2_CID_SATURATION:1718		setsatur(gspca_dev, ctrl->val);1719		break;1720	case V4L2_CID_POWER_LINE_FREQUENCY:1721		setlightfreq(gspca_dev, ctrl->val);1722		break;1723	case V4L2_CID_SHARPNESS:1724		setsharpness(gspca_dev, ctrl->val);1725		break;1726	case V4L2_CID_AUTOGAIN:1727		if (ctrl->is_new)1728			setautogain(gspca_dev, ctrl->val);1729		if (!ctrl->val && gspca_dev->exposure->is_new)1730			setexposure(gspca_dev, gspca_dev->exposure->val);1731		break;1732	}1733	return gspca_dev->usb_err;1734}1735 1736static const struct v4l2_ctrl_ops sd_ctrl_ops = {1737	.s_ctrl = sd_s_ctrl,1738};1739 1740static int sd_init_controls(struct gspca_dev *gspca_dev)1741{1742	struct sd *sd = (struct sd *)gspca_dev;1743	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;1744 1745	if (sd->sensor == SENSOR_OV971x)1746		return 0;1747	if (sd->sensor == SENSOR_OV361x)1748		return 0;1749	gspca_dev->vdev.ctrl_handler = hdl;1750	v4l2_ctrl_handler_init(hdl, 7);1751	if (sd->sensor == SENSOR_OV562x) {1752		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1753			V4L2_CID_BRIGHTNESS, -90, 90, 1, 0);1754	} else {1755		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1756			V4L2_CID_BRIGHTNESS, 0, 15, 1, 7);1757		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1758			V4L2_CID_CONTRAST, 0, 15, 1, 3);1759		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1760			V4L2_CID_SATURATION, 0, 4, 1, 2);1761		/* -1 = auto */1762		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1763			V4L2_CID_SHARPNESS, -1, 4, 1, -1);1764		gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1765			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);1766		gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1767			V4L2_CID_EXPOSURE, 0, 3, 1, 0);1768		v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,1769			V4L2_CID_POWER_LINE_FREQUENCY,1770			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);1771		v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);1772	}1773 1774	if (hdl->error) {1775		pr_err("Could not initialize controls\n");1776		return hdl->error;1777	}1778	return 0;1779}1780 1781/* sub-driver description */1782static const struct sd_desc sd_desc = {1783	.name     = MODULE_NAME,1784	.config   = sd_config,1785	.init     = sd_init,1786	.init_controls = sd_init_controls,1787	.start    = sd_start,1788	.stopN    = sd_stopN,1789	.pkt_scan = sd_pkt_scan,1790};1791 1792/* -- module initialisation -- */1793static const struct usb_device_id device_table[] = {1794	{USB_DEVICE(0x05a9, 0x8065)},1795	{USB_DEVICE(0x06f8, 0x3003)},1796	{USB_DEVICE(0x05a9, 0x1550)},1797	{}1798};1799 1800MODULE_DEVICE_TABLE(usb, device_table);1801 1802/* -- device connect -- */1803static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)1804{1805	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),1806				THIS_MODULE);1807}1808 1809static struct usb_driver sd_driver = {1810	.name       = MODULE_NAME,1811	.id_table   = device_table,1812	.probe      = sd_probe,1813	.disconnect = gspca_disconnect,1814#ifdef CONFIG_PM1815	.suspend    = gspca_suspend,1816	.resume     = gspca_resume,1817	.reset_resume = gspca_resume,1818#endif1819};1820 1821module_usb_driver(sd_driver);1822