brintos

brintos / linux-shallow public Read only

0
0
Text · 24.6 KiB · 431527e Raw
912 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Sunplus spca561 subdriver4 *5 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr6 *7 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 12#define MODULE_NAME "spca561"13 14#include <linux/input.h>15#include "gspca.h"16 17MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");18MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");19MODULE_LICENSE("GPL");20 21#define EXPOSURE_MAX (2047 + 325)22 23/* specific webcam descriptor */24struct sd {25	struct gspca_dev gspca_dev;	/* !! must be the first item */26 27	struct { /* hue/contrast control cluster */28		struct v4l2_ctrl *contrast;29		struct v4l2_ctrl *hue;30	};31	struct v4l2_ctrl *autogain;32 33#define EXPO12A_DEF 334	__u8 expo12a;		/* expo/gain? for rev 12a */35 36	__u8 chip_revision;37#define Rev012A 038#define Rev072A 139 40	signed char ag_cnt;41#define AG_CNT_START 1342};43 44static const struct v4l2_pix_format sif_012a_mode[] = {45	{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,46		.bytesperline = 160,47		.sizeimage = 160 * 120,48		.colorspace = V4L2_COLORSPACE_SRGB,49		.priv = 3},50	{176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,51		.bytesperline = 176,52		.sizeimage = 176 * 144,53		.colorspace = V4L2_COLORSPACE_SRGB,54		.priv = 2},55	{320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,56		.bytesperline = 320,57		.sizeimage = 320 * 240 * 4 / 8,58		.colorspace = V4L2_COLORSPACE_SRGB,59		.priv = 1},60	{352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,61		.bytesperline = 352,62		.sizeimage = 352 * 288 * 4 / 8,63		.colorspace = V4L2_COLORSPACE_SRGB,64		.priv = 0},65};66 67static const struct v4l2_pix_format sif_072a_mode[] = {68	{160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,69		.bytesperline = 160,70		.sizeimage = 160 * 120,71		.colorspace = V4L2_COLORSPACE_SRGB,72		.priv = 3},73	{176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,74		.bytesperline = 176,75		.sizeimage = 176 * 144,76		.colorspace = V4L2_COLORSPACE_SRGB,77		.priv = 2},78	{320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,79		.bytesperline = 320,80		.sizeimage = 320 * 240,81		.colorspace = V4L2_COLORSPACE_SRGB,82		.priv = 1},83	{352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,84		.bytesperline = 352,85		.sizeimage = 352 * 288,86		.colorspace = V4L2_COLORSPACE_SRGB,87		.priv = 0},88};89 90/*91 * Initialization data92 * I'm not very sure how to split initialization from open data93 * chunks. For now, we'll consider everything as initialization94 */95/* Frame packet header offsets for the spca561 */96#define SPCA561_OFFSET_SNAP 197#define SPCA561_OFFSET_TYPE 298#define SPCA561_OFFSET_COMPRESS 399#define SPCA561_OFFSET_FRAMSEQ   4100#define SPCA561_OFFSET_GPIO 5101#define SPCA561_OFFSET_USBBUFF 6102#define SPCA561_OFFSET_WIN2GRAVE 7103#define SPCA561_OFFSET_WIN2RAVE 8104#define SPCA561_OFFSET_WIN2BAVE 9105#define SPCA561_OFFSET_WIN2GBAVE 10106#define SPCA561_OFFSET_WIN1GRAVE 11107#define SPCA561_OFFSET_WIN1RAVE 12108#define SPCA561_OFFSET_WIN1BAVE 13109#define SPCA561_OFFSET_WIN1GBAVE 14110#define SPCA561_OFFSET_FREQ 15111#define SPCA561_OFFSET_VSYNC 16112#define SPCA561_INDEX_I2C_BASE 0x8800113#define SPCA561_SNAPBIT 0x20114#define SPCA561_SNAPCTRL 0x40115 116static const u16 rev72a_reset[][2] = {117	{0x0000, 0x8114},	/* Software GPIO output data */118	{0x0001, 0x8114},	/* Software GPIO output data */119	{0x0000, 0x8112},	/* Some kind of reset */120	{}121};122static const __u16 rev72a_init_data1[][2] = {123	{0x0003, 0x8701},	/* PCLK clock delay adjustment */124	{0x0001, 0x8703},	/* HSYNC from cmos inverted */125	{0x0011, 0x8118},	/* Enable and conf sensor */126	{0x0001, 0x8118},	/* Conf sensor */127	{0x0092, 0x8804},	/* I know nothing about these */128	{0x0010, 0x8802},	/* 0x88xx registers, so I won't */129	{}130};131static const u16 rev72a_init_sensor1[][2] = {132	{0x0001, 0x000d},133	{0x0002, 0x0018},134	{0x0004, 0x0165},135	{0x0005, 0x0021},136	{0x0007, 0x00aa},137	{0x0020, 0x1504},138	{0x0039, 0x0002},139	{0x0035, 0x0010},140	{0x0009, 0x1049},141	{0x0028, 0x000b},142	{0x003b, 0x000f},143	{0x003c, 0x0000},144	{}145};146static const __u16 rev72a_init_data2[][2] = {147	{0x0018, 0x8601},	/* Pixel/line selection for color separation */148	{0x0000, 0x8602},	/* Optical black level for user setting */149	{0x0060, 0x8604},	/* Optical black horizontal offset */150	{0x0002, 0x8605},	/* Optical black vertical offset */151	{0x0000, 0x8603},	/* Non-automatic optical black level */152	{0x0002, 0x865b},	/* Horizontal offset for valid pixels */153	{0x0000, 0x865f},	/* Vertical valid pixels window (x2) */154	{0x00b0, 0x865d},	/* Horizontal valid pixels window (x2) */155	{0x0090, 0x865e},	/* Vertical valid lines window (x2) */156	{0x00e0, 0x8406},	/* Memory buffer threshold */157	{0x0000, 0x8660},	/* Compensation memory stuff */158	{0x0002, 0x8201},	/* Output address for r/w serial EEPROM */159	{0x0008, 0x8200},	/* Clear valid bit for serial EEPROM */160	{0x0001, 0x8200},	/* OprMode to be executed by hardware */161/* from ms-win */162	{0x0000, 0x8611},	/* R offset for white balance */163	{0x00fd, 0x8612},	/* Gr offset for white balance */164	{0x0003, 0x8613},	/* B offset for white balance */165	{0x0000, 0x8614},	/* Gb offset for white balance */166/* from ms-win */167	{0x0035, 0x8651},	/* R gain for white balance */168	{0x0040, 0x8652},	/* Gr gain for white balance */169	{0x005f, 0x8653},	/* B gain for white balance */170	{0x0040, 0x8654},	/* Gb gain for white balance */171	{0x0002, 0x8502},	/* Maximum average bit rate stuff */172	{0x0011, 0x8802},173 174	{0x0087, 0x8700},	/* Set master clock (96Mhz????) */175	{0x0081, 0x8702},	/* Master clock output enable */176 177	{0x0000, 0x8500},	/* Set image type (352x288 no compression) */178	/* Originally was 0x0010 (352x288 compression) */179 180	{0x0002, 0x865b},	/* Horizontal offset for valid pixels */181	{0x0003, 0x865c},	/* Vertical offset for valid lines */182	{}183};184static const u16 rev72a_init_sensor2[][2] = {185	{0x0003, 0x0121},186	{0x0004, 0x0165},187	{0x0005, 0x002f},	/* blanking control column */188	{0x0006, 0x0000},	/* blanking mode row*/189	{0x000a, 0x0002},190	{0x0009, 0x1061},	/* setexposure times && pixel clock191				 * 0001 0 | 000 0110 0001 */192	{0x0035, 0x0014},193	{}194};195 196/******************** QC Express etch2 stuff ********************/197static const __u16 Pb100_1map8300[][2] = {198	/* reg, value */199	{0x8320, 0x3304},200 201	{0x8303, 0x0125},	/* image area */202	{0x8304, 0x0169},203	{0x8328, 0x000b},204	{0x833c, 0x0001},		/*fixme: win:07*/205 206	{0x832f, 0x1904},		/*fixme: was 0419*/207	{0x8307, 0x00aa},208	{0x8301, 0x0003},209	{0x8302, 0x000e},210	{}211};212static const __u16 Pb100_2map8300[][2] = {213	/* reg, value */214	{0x8339, 0x0000},215	{0x8307, 0x00aa},216	{}217};218 219static const __u16 spca561_161rev12A_data1[][2] = {220	{0x29, 0x8118},		/* Control register (various enable bits) */221	{0x08, 0x8114},		/* GPIO: Led off */222	{0x0e, 0x8112},		/* 0x0e stream off 0x3e stream on */223	{0x00, 0x8102},		/* white balance - new */224	{0x92, 0x8804},225	{0x04, 0x8802},		/* windows uses 08 */226	{}227};228static const __u16 spca561_161rev12A_data2[][2] = {229	{0x21, 0x8118},230	{0x10, 0x8500},231	{0x07, 0x8601},232	{0x07, 0x8602},233	{0x04, 0x8501},234 235	{0x07, 0x8201},		/* windows uses 02 */236	{0x08, 0x8200},237	{0x01, 0x8200},238 239	{0x90, 0x8604},240	{0x00, 0x8605},241	{0xb0, 0x8603},242 243	/* sensor gains */244	{0x07, 0x8601},		/* white balance - new */245	{0x07, 0x8602},		/* white balance - new */246	{0x00, 0x8610},		/* *red */247	{0x00, 0x8611},		/* 3f   *green */248	{0x00, 0x8612},		/* green *blue */249	{0x00, 0x8613},		/* blue *green */250	{0x43, 0x8614},		/* green *red - white balance - was 0x35 */251	{0x40, 0x8615},		/* 40   *green - white balance - was 0x35 */252	{0x71, 0x8616},		/* 7a   *blue - white balance - was 0x35 */253	{0x40, 0x8617},		/* 40   *green - white balance - was 0x35 */254 255	{0x0c, 0x8620},		/* 0c */256	{0xc8, 0x8631},		/* c8 */257	{0xc8, 0x8634},		/* c8 */258	{0x23, 0x8635},		/* 23 */259	{0x1f, 0x8636},		/* 1f */260	{0xdd, 0x8637},		/* dd */261	{0xe1, 0x8638},		/* e1 */262	{0x1d, 0x8639},		/* 1d */263	{0x21, 0x863a},		/* 21 */264	{0xe3, 0x863b},		/* e3 */265	{0xdf, 0x863c},		/* df */266	{0xf0, 0x8505},267	{0x32, 0x850a},268/*	{0x99, 0x8700},		 * - white balance - new (removed) */269	/* HDG we used to do this in stop0, making the init state and the state270	   after a start / stop different, so do this here instead. */271	{0x29, 0x8118},272	{}273};274 275static void reg_w_val(struct gspca_dev *gspca_dev, __u16 index, __u8 value)276{277	int ret;278	struct usb_device *dev = gspca_dev->dev;279 280	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),281			      0,		/* request */282			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,283			      value, index, NULL, 0, 500);284	gspca_dbg(gspca_dev, D_USBO, "reg write: 0x%02x:0x%02x\n",285		  index, value);286	if (ret < 0)287		pr_err("reg write: error %d\n", ret);288}289 290static void write_vector(struct gspca_dev *gspca_dev,291			const __u16 data[][2])292{293	int i;294 295	i = 0;296	while (data[i][1] != 0) {297		reg_w_val(gspca_dev, data[i][1], data[i][0]);298		i++;299	}300}301 302/* read 'len' bytes to gspca_dev->usb_buf */303static void reg_r(struct gspca_dev *gspca_dev,304		  __u16 index, __u16 length)305{306	usb_control_msg(gspca_dev->dev,307			usb_rcvctrlpipe(gspca_dev->dev, 0),308			0,			/* request */309			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,310			0,			/* value */311			index, gspca_dev->usb_buf, length, 500);312}313 314/* write 'len' bytes from gspca_dev->usb_buf */315static void reg_w_buf(struct gspca_dev *gspca_dev,316		      __u16 index, __u16 len)317{318	usb_control_msg(gspca_dev->dev,319			usb_sndctrlpipe(gspca_dev->dev, 0),320			0,			/* request */321			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,322			0,			/* value */323			index, gspca_dev->usb_buf, len, 500);324}325 326static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)327{328	int retry = 60;329 330	reg_w_val(gspca_dev, 0x8801, reg);331	reg_w_val(gspca_dev, 0x8805, value);332	reg_w_val(gspca_dev, 0x8800, value >> 8);333	do {334		reg_r(gspca_dev, 0x8803, 1);335		if (!gspca_dev->usb_buf[0])336			return;337		msleep(10);338	} while (--retry);339}340 341static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)342{343	int retry = 60;344	__u8 value;345 346	reg_w_val(gspca_dev, 0x8804, 0x92);347	reg_w_val(gspca_dev, 0x8801, reg);348	reg_w_val(gspca_dev, 0x8802, mode | 0x01);349	do {350		reg_r(gspca_dev, 0x8803, 1);351		if (!gspca_dev->usb_buf[0]) {352			reg_r(gspca_dev, 0x8800, 1);353			value = gspca_dev->usb_buf[0];354			reg_r(gspca_dev, 0x8805, 1);355			return ((int) value << 8) | gspca_dev->usb_buf[0];356		}357		msleep(10);358	} while (--retry);359	return -1;360}361 362static void sensor_mapwrite(struct gspca_dev *gspca_dev,363			    const __u16 (*sensormap)[2])364{365	while ((*sensormap)[0]) {366		gspca_dev->usb_buf[0] = (*sensormap)[1];367		gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;368		reg_w_buf(gspca_dev, (*sensormap)[0], 2);369		sensormap++;370	}371}372 373static void write_sensor_72a(struct gspca_dev *gspca_dev,374			    const __u16 (*sensor)[2])375{376	while ((*sensor)[0]) {377		i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);378		sensor++;379	}380}381 382static void init_161rev12A(struct gspca_dev *gspca_dev)383{384	write_vector(gspca_dev, spca561_161rev12A_data1);385	sensor_mapwrite(gspca_dev, Pb100_1map8300);386/*fixme: should be in sd_start*/387	write_vector(gspca_dev, spca561_161rev12A_data2);388	sensor_mapwrite(gspca_dev, Pb100_2map8300);389}390 391/* this function is called at probe time */392static int sd_config(struct gspca_dev *gspca_dev,393		     const struct usb_device_id *id)394{395	struct sd *sd = (struct sd *) gspca_dev;396	struct cam *cam;397	__u16 vendor, product;398	__u8 data1, data2;399 400	/* Read frm global register the USB product and vendor IDs, just to401	 * prove that we can communicate with the device.  This works, which402	 * confirms at we are communicating properly and that the device403	 * is a 561. */404	reg_r(gspca_dev, 0x8104, 1);405	data1 = gspca_dev->usb_buf[0];406	reg_r(gspca_dev, 0x8105, 1);407	data2 = gspca_dev->usb_buf[0];408	vendor = (data2 << 8) | data1;409	reg_r(gspca_dev, 0x8106, 1);410	data1 = gspca_dev->usb_buf[0];411	reg_r(gspca_dev, 0x8107, 1);412	data2 = gspca_dev->usb_buf[0];413	product = (data2 << 8) | data1;414	if (vendor != id->idVendor || product != id->idProduct) {415		gspca_dbg(gspca_dev, D_PROBE, "Bad vendor / product from device\n");416		return -EINVAL;417	}418 419	cam = &gspca_dev->cam;420	cam->needs_full_bandwidth = 1;421 422	sd->chip_revision = id->driver_info;423	if (sd->chip_revision == Rev012A) {424		cam->cam_mode = sif_012a_mode;425		cam->nmodes = ARRAY_SIZE(sif_012a_mode);426	} else {427		cam->cam_mode = sif_072a_mode;428		cam->nmodes = ARRAY_SIZE(sif_072a_mode);429	}430	sd->expo12a = EXPO12A_DEF;431	return 0;432}433 434/* this function is called at probe and resume time */435static int sd_init_12a(struct gspca_dev *gspca_dev)436{437	gspca_dbg(gspca_dev, D_STREAM, "Chip revision: 012a\n");438	init_161rev12A(gspca_dev);439	return 0;440}441static int sd_init_72a(struct gspca_dev *gspca_dev)442{443	gspca_dbg(gspca_dev, D_STREAM, "Chip revision: 072a\n");444	write_vector(gspca_dev, rev72a_reset);445	msleep(200);446	write_vector(gspca_dev, rev72a_init_data1);447	write_sensor_72a(gspca_dev, rev72a_init_sensor1);448	write_vector(gspca_dev, rev72a_init_data2);449	write_sensor_72a(gspca_dev, rev72a_init_sensor2);450	reg_w_val(gspca_dev, 0x8112, 0x30);451	return 0;452}453 454static void setbrightness(struct gspca_dev *gspca_dev, s32 val)455{456	struct sd *sd = (struct sd *) gspca_dev;457	__u16 reg;458 459	if (sd->chip_revision == Rev012A)460		reg = 0x8610;461	else462		reg = 0x8611;463 464	reg_w_val(gspca_dev, reg + 0, val);		/* R */465	reg_w_val(gspca_dev, reg + 1, val);		/* Gr */466	reg_w_val(gspca_dev, reg + 2, val);		/* B */467	reg_w_val(gspca_dev, reg + 3, val);		/* Gb */468}469 470static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)471{472	struct sd *sd = (struct sd *) gspca_dev;473	__u8 blue, red;474	__u16 reg;475 476	/* try to emulate MS-win as possible */477	red = 0x20 + white * 3 / 8;478	blue = 0x90 - white * 5 / 8;479	if (sd->chip_revision == Rev012A) {480		reg = 0x8614;481	} else {482		reg = 0x8651;483		red += contrast - 0x20;484		blue += contrast - 0x20;485		reg_w_val(gspca_dev, 0x8652, contrast + 0x20); /* Gr */486		reg_w_val(gspca_dev, 0x8654, contrast + 0x20); /* Gb */487	}488	reg_w_val(gspca_dev, reg, red);489	reg_w_val(gspca_dev, reg + 2, blue);490}491 492/* rev 12a only */493static void setexposure(struct gspca_dev *gspca_dev, s32 val)494{495	int i, expo = 0;496 497	/* Register 0x8309 controls exposure for the spca561,498	   the basic exposure setting goes from 1-2047, where 1 is completely499	   dark and 2047 is very bright. It not only influences exposure but500	   also the framerate (to allow for longer exposure) from 1 - 300 it501	   only raises the exposure time then from 300 - 600 it halves the502	   framerate to be able to further raise the exposure time and for every503	   300 more it halves the framerate again. This allows for a maximum504	   exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).505	   Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12506	   configure a divider for the base framerate which us used at the507	   exposure setting of 1-300. These bits configure the base framerate508	   according to the following formula: fps = 60 / (value + 2) */509 510	/* We choose to use the high bits setting the fixed framerate divisor511	   asap, as setting high basic exposure setting without the fixed512	   divider in combination with high gains makes the cam stop */513	static const int table[] =  { 0, 450, 550, 625, EXPOSURE_MAX };514 515	for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {516		if (val <= table[i + 1]) {517			expo  = val - table[i];518			if (i)519				expo += 300;520			expo |= i << 11;521			break;522		}523	}524 525	gspca_dev->usb_buf[0] = expo;526	gspca_dev->usb_buf[1] = expo >> 8;527	reg_w_buf(gspca_dev, 0x8309, 2);528}529 530/* rev 12a only */531static void setgain(struct gspca_dev *gspca_dev, s32 val)532{533	/* gain reg low 6 bits  0-63 gain, bit 6 and 7, both double the534	   sensitivity when set, so 31 + one of them set == 63, and 15535	   with both of them set == 63 */536	if (val < 64)537		gspca_dev->usb_buf[0] = val;538	else if (val < 128)539		gspca_dev->usb_buf[0] = (val / 2) | 0x40;540	else541		gspca_dev->usb_buf[0] = (val / 4) | 0xc0;542 543	gspca_dev->usb_buf[1] = 0;544	reg_w_buf(gspca_dev, 0x8335, 2);545}546 547static void setautogain(struct gspca_dev *gspca_dev, s32 val)548{549	struct sd *sd = (struct sd *) gspca_dev;550 551	if (val)552		sd->ag_cnt = AG_CNT_START;553	else554		sd->ag_cnt = -1;555}556 557static int sd_start_12a(struct gspca_dev *gspca_dev)558{559	int mode;560	static const __u8 Reg8391[8] =561		{0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};562 563	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;564	if (mode <= 1) {565		/* Use compression on 320x240 and above */566		reg_w_val(gspca_dev, 0x8500, 0x10 | mode);567	} else {568		/* I couldn't get the compression to work below 320x240569		 * Fortunately at these resolutions the bandwidth570		 * is sufficient to push raw frames at ~20fps */571		reg_w_val(gspca_dev, 0x8500, mode);572	}		/* -- qq@kuku.eu.org */573 574	gspca_dev->usb_buf[0] = 0xaa;575	gspca_dev->usb_buf[1] = 0x00;576	reg_w_buf(gspca_dev, 0x8307, 2);577	/* clock - lower 0x8X values lead to fps > 30 */578	reg_w_val(gspca_dev, 0x8700, 0x8a);579					/* 0x8f 0x85 0x27 clock */580	reg_w_val(gspca_dev, 0x8112, 0x1e | 0x20);581	reg_w_val(gspca_dev, 0x850b, 0x03);582	memcpy(gspca_dev->usb_buf, Reg8391, 8);583	reg_w_buf(gspca_dev, 0x8391, 8);584	reg_w_buf(gspca_dev, 0x8390, 8);585 586	/* Led ON (bit 3 -> 0 */587	reg_w_val(gspca_dev, 0x8114, 0x00);588	return 0;589}590static int sd_start_72a(struct gspca_dev *gspca_dev)591{592	struct sd *sd = (struct sd *) gspca_dev;593	int Clck;594	int mode;595 596	write_vector(gspca_dev, rev72a_reset);597	msleep(200);598	write_vector(gspca_dev, rev72a_init_data1);599	write_sensor_72a(gspca_dev, rev72a_init_sensor1);600 601	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;602	switch (mode) {603	default:604	case 0:605		Clck = 0x27;		/* ms-win 0x87 */606		break;607	case 1:608		Clck = 0x25;609		break;610	case 2:611		Clck = 0x22;612		break;613	case 3:614		Clck = 0x21;615		break;616	}617	reg_w_val(gspca_dev, 0x8700, Clck);	/* 0x27 clock */618	reg_w_val(gspca_dev, 0x8702, 0x81);619	reg_w_val(gspca_dev, 0x8500, mode);	/* mode */620	write_sensor_72a(gspca_dev, rev72a_init_sensor2);621	setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue),622			v4l2_ctrl_g_ctrl(sd->contrast));623/*	setbrightness(gspca_dev);	 * fixme: bad values */624	setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));625	reg_w_val(gspca_dev, 0x8112, 0x10 | 0x20);626	return 0;627}628 629static void sd_stopN(struct gspca_dev *gspca_dev)630{631	struct sd *sd = (struct sd *) gspca_dev;632 633	if (sd->chip_revision == Rev012A) {634		reg_w_val(gspca_dev, 0x8112, 0x0e);635		/* Led Off (bit 3 -> 1 */636		reg_w_val(gspca_dev, 0x8114, 0x08);637	} else {638		reg_w_val(gspca_dev, 0x8112, 0x20);639/*		reg_w_val(gspca_dev, 0x8102, 0x00); ?? */640	}641}642 643static void do_autogain(struct gspca_dev *gspca_dev)644{645	struct sd *sd = (struct sd *) gspca_dev;646	int expotimes;647	int pixelclk;648	int gainG;649	__u8 R, Gr, Gb, B;650	int y;651	__u8 luma_mean = 110;652	__u8 luma_delta = 20;653	__u8 spring = 4;654 655	if (sd->ag_cnt < 0)656		return;657	if (--sd->ag_cnt >= 0)658		return;659	sd->ag_cnt = AG_CNT_START;660 661	switch (sd->chip_revision) {662	case Rev072A:663		reg_r(gspca_dev, 0x8621, 1);664		Gr = gspca_dev->usb_buf[0];665		reg_r(gspca_dev, 0x8622, 1);666		R = gspca_dev->usb_buf[0];667		reg_r(gspca_dev, 0x8623, 1);668		B = gspca_dev->usb_buf[0];669		reg_r(gspca_dev, 0x8624, 1);670		Gb = gspca_dev->usb_buf[0];671		y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;672		/* u= (128*B-(43*(Gr+Gb+R))) >> 8; */673		/* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */674 675		if (y < luma_mean - luma_delta ||676		    y > luma_mean + luma_delta) {677			expotimes = i2c_read(gspca_dev, 0x09, 0x10);678			pixelclk = 0x0800;679			expotimes = expotimes & 0x07ff;680			gainG = i2c_read(gspca_dev, 0x35, 0x10);681 682			expotimes += (luma_mean - y) >> spring;683			gainG += (luma_mean - y) / 50;684 685			if (gainG > 0x3f)686				gainG = 0x3f;687			else if (gainG < 3)688				gainG = 3;689			i2c_write(gspca_dev, gainG, 0x35);690 691			if (expotimes > 0x0256)692				expotimes = 0x0256;693			else if (expotimes < 3)694				expotimes = 3;695			i2c_write(gspca_dev, expotimes | pixelclk, 0x09);696		}697		break;698	}699}700 701static void sd_pkt_scan(struct gspca_dev *gspca_dev,702			u8 *data,		/* isoc packet */703			int len)		/* iso packet length */704{705	struct sd *sd = (struct sd *) gspca_dev;706 707	len--;708	switch (*data++) {			/* sequence number */709	case 0:					/* start of frame */710		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);711 712		/* This should never happen */713		if (len < 2) {714			gspca_err(gspca_dev, "Short SOF packet, ignoring\n\n\n\n\n");715			gspca_dev->last_packet_type = DISCARD_PACKET;716			return;717		}718 719#if IS_ENABLED(CONFIG_INPUT)720		if (data[0] & 0x20) {721			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);722			input_sync(gspca_dev->input_dev);723			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);724			input_sync(gspca_dev->input_dev);725		}726#endif727 728		if (data[1] & 0x10) {729			/* compressed bayer */730			gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);731		} else {732			/* raw bayer (with a header, which we skip) */733			if (sd->chip_revision == Rev012A) {734				data += 20;735				len -= 20;736			} else {737				data += 16;738				len -= 16;739			}740			gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);741		}742		return;743	case 0xff:			/* drop (empty mpackets) */744		return;745	}746	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);747}748 749static int sd_s_ctrl(struct v4l2_ctrl *ctrl)750{751	struct gspca_dev *gspca_dev =752		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);753	struct sd *sd = (struct sd *)gspca_dev;754 755	gspca_dev->usb_err = 0;756 757	if (!gspca_dev->streaming)758		return 0;759 760	switch (ctrl->id) {761	case V4L2_CID_BRIGHTNESS:762		setbrightness(gspca_dev, ctrl->val);763		break;764	case V4L2_CID_CONTRAST:765		/* hue/contrast control cluster for 72a */766		setwhite(gspca_dev, sd->hue->val, ctrl->val);767		break;768	case V4L2_CID_HUE:769		/* just plain hue control for 12a */770		setwhite(gspca_dev, ctrl->val, 0);771		break;772	case V4L2_CID_EXPOSURE:773		setexposure(gspca_dev, ctrl->val);774		break;775	case V4L2_CID_GAIN:776		setgain(gspca_dev, ctrl->val);777		break;778	case V4L2_CID_AUTOGAIN:779		setautogain(gspca_dev, ctrl->val);780		break;781	}782	return gspca_dev->usb_err;783}784 785static const struct v4l2_ctrl_ops sd_ctrl_ops = {786	.s_ctrl = sd_s_ctrl,787};788 789static int sd_init_controls_12a(struct gspca_dev *gspca_dev)790{791	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;792 793	gspca_dev->vdev.ctrl_handler = hdl;794	v4l2_ctrl_handler_init(hdl, 3);795	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,796			V4L2_CID_HUE, 1, 0x7f, 1, 0x40);797	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,798			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);799	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,800			V4L2_CID_EXPOSURE, 1, EXPOSURE_MAX, 1, 700);801	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,802			V4L2_CID_GAIN, 0, 255, 1, 63);803 804	if (hdl->error) {805		pr_err("Could not initialize controls\n");806		return hdl->error;807	}808	return 0;809}810 811static int sd_init_controls_72a(struct gspca_dev *gspca_dev)812{813	struct sd *sd = (struct sd *)gspca_dev;814	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;815 816	gspca_dev->vdev.ctrl_handler = hdl;817	v4l2_ctrl_handler_init(hdl, 4);818	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,819			V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x20);820	sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,821			V4L2_CID_HUE, 1, 0x7f, 1, 0x40);822	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,823			V4L2_CID_BRIGHTNESS, 0, 0x3f, 1, 0x20);824	sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,825			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);826 827	if (hdl->error) {828		pr_err("Could not initialize controls\n");829		return hdl->error;830	}831	v4l2_ctrl_cluster(2, &sd->contrast);832	return 0;833}834 835/* sub-driver description */836static const struct sd_desc sd_desc_12a = {837	.name = MODULE_NAME,838	.init_controls = sd_init_controls_12a,839	.config = sd_config,840	.init = sd_init_12a,841	.start = sd_start_12a,842	.stopN = sd_stopN,843	.pkt_scan = sd_pkt_scan,844#if IS_ENABLED(CONFIG_INPUT)845	.other_input = 1,846#endif847};848static const struct sd_desc sd_desc_72a = {849	.name = MODULE_NAME,850	.init_controls = sd_init_controls_72a,851	.config = sd_config,852	.init = sd_init_72a,853	.start = sd_start_72a,854	.stopN = sd_stopN,855	.pkt_scan = sd_pkt_scan,856	.dq_callback = do_autogain,857#if IS_ENABLED(CONFIG_INPUT)858	.other_input = 1,859#endif860};861static const struct sd_desc *sd_desc[2] = {862	&sd_desc_12a,863	&sd_desc_72a864};865 866/* -- module initialisation -- */867static const struct usb_device_id device_table[] = {868	{USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},869	{USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},870	{USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},871	{USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},872	{USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},873	{USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},874	{USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},875	{USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},876	{USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},877	{USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},878	{USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},879	{USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},880	{USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},881	{USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},882	{USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},883	{USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},884	{}885};886 887MODULE_DEVICE_TABLE(usb, device_table);888 889/* -- device connect -- */890static int sd_probe(struct usb_interface *intf,891		    const struct usb_device_id *id)892{893	return gspca_dev_probe(intf, id,894				sd_desc[id->driver_info],895				sizeof(struct sd),896			       THIS_MODULE);897}898 899static struct usb_driver sd_driver = {900	.name = MODULE_NAME,901	.id_table = device_table,902	.probe = sd_probe,903	.disconnect = gspca_disconnect,904#ifdef CONFIG_PM905	.suspend = gspca_suspend,906	.resume = gspca_resume,907	.reset_resume = gspca_resume,908#endif909};910 911module_usb_driver(sd_driver);912