18668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/*
28668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * Support for the sensor part which is integrated (I think) into the
38668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
48668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * but instead direct bridge writes.
58668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede *
68668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
78668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede *
88668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * Strongly based on qc-usb-messenger, which is:
98668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
108668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede *		      Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
118668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * Copyright (c) 2002, 2003 Tuukka Toivonen
128668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede *
138668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * This program is free software; you can redistribute it and/or modify
148668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * it under the terms of the GNU General Public License as published by
158668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * the Free Software Foundation; either version 2 of the License, or
168668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * (at your option) any later version.
178668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede *
188668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * This program is distributed in the hope that it will be useful,
198668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * but WITHOUT ANY WARRANTY; without even the implied warranty of
208668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
218668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * GNU General Public License for more details.
228668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede *
238668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * You should have received a copy of the GNU General Public License
248668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * along with this program; if not, write to the Free Software
258668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
268668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede *
278668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede */
288668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
29133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches
318668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede#include "stv06xx_st6422.h"
328668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
3371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine/* controls */
3471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moineenum e_ctrl {
3571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	BRIGHTNESS,
3671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	CONTRAST,
3771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	GAIN,
3871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	EXPOSURE,
3971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	NCTRLS		/* number of controls */
4071e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine};
4171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
4271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine/* sensor settings */
4371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestruct st6422_settings {
4471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	struct gspca_ctrl ctrls[NCTRLS];
4571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine};
4671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
478668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goedestatic struct v4l2_pix_format st6422_mode[] = {
488668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	/* Note we actually get 124 lines of data, of which we skip the 4st
498668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	   4 as they are garbage */
508668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	{
518668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		162,
528668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		120,
538668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		V4L2_PIX_FMT_SGRBG8,
548668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		V4L2_FIELD_NONE,
558668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		.sizeimage = 162 * 120,
568668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		.bytesperline = 162,
578668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		.colorspace = V4L2_COLORSPACE_SRGB,
588668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		.priv = 1
598668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	},
608668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	/* Note we actually get 248 lines of data, of which we skip the 4st
618668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	   4 as they are garbage, and we tell the app it only gets the
628668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	   first 240 of the 244 lines it actually gets, so that it ignores
638668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	   the last 4. */
648668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	{
658668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		324,
668668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		240,
678668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		V4L2_PIX_FMT_SGRBG8,
688668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		V4L2_FIELD_NONE,
698668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		.sizeimage = 324 * 244,
708668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		.bytesperline = 324,
718668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		.colorspace = V4L2_COLORSPACE_SRGB,
728668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		.priv = 0
738668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	},
748668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede};
758668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
7671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine/* V4L2 controls supported by the driver */
7771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic void st6422_set_brightness(struct gspca_dev *gspca_dev);
7871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic void st6422_set_contrast(struct gspca_dev *gspca_dev);
7971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic void st6422_set_gain(struct gspca_dev *gspca_dev);
8071e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic void st6422_set_exposure(struct gspca_dev *gspca_dev);
8171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
8271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic const struct ctrl st6422_ctrl[NCTRLS] = {
8371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine[BRIGHTNESS] = {
848668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{
858668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.id		= V4L2_CID_BRIGHTNESS,
868668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.type		= V4L2_CTRL_TYPE_INTEGER,
878668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.name		= "Brightness",
888668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.minimum	= 0,
898668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.maximum	= 31,
908668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.step		= 1,
918668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.default_value  = 3
928668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		},
9371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		.set_control = st6422_set_brightness
948668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	},
9571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine[CONTRAST] = {
968668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{
978668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.id		= V4L2_CID_CONTRAST,
988668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.type		= V4L2_CTRL_TYPE_INTEGER,
998668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.name		= "Contrast",
1008668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.minimum	= 0,
1018668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.maximum	= 15,
1028668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.step		= 1,
1038668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.default_value  = 11
1048668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		},
10571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		.set_control = st6422_set_contrast
1068668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	},
10771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine[GAIN] = {
1088668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{
1098668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.id		= V4L2_CID_GAIN,
1108668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.type		= V4L2_CTRL_TYPE_INTEGER,
1118668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.name		= "Gain",
1128668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.minimum	= 0,
1138668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.maximum	= 255,
1148668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.step		= 1,
1158668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.default_value  = 64
1168668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		},
11771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		.set_control = st6422_set_gain
1188668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	},
11971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine[EXPOSURE] = {
1208668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{
1218668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.id		= V4L2_CID_EXPOSURE,
1228668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.type		= V4L2_CTRL_TYPE_INTEGER,
1238668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.name		= "Exposure",
1248668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.minimum	= 0,
12571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine#define EXPOSURE_MAX 1023
12671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine			.maximum	= EXPOSURE_MAX,
1278668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.step		= 1,
1288668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede			.default_value  = 256
1298668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		},
13071e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		.set_control = st6422_set_exposure
1318668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	},
1328668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede};
1338668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1348668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goedestatic int st6422_probe(struct sd *sd)
1358668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
13671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	struct st6422_settings *sensor_settings;
1378668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1388668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	if (sd->bridge != BRIDGE_ST6422)
1398668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		return -ENODEV;
1408668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
141133a9fe949862d9ed8411fb423739f4cee08232dJoe Perches	pr_info("st6422 sensor detected\n");
1428668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
14371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
1448668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	if (!sensor_settings)
1458668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		return -ENOMEM;
1468668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1478668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	sd->gspca_dev.cam.cam_mode = st6422_mode;
1488668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
14971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
1508668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	sd->desc.ctrls = st6422_ctrl;
1518668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
1528668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	sd->sensor_priv = sensor_settings;
1538668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1548668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	return 0;
1558668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
1568668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1578668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goedestatic int st6422_init(struct sd *sd)
1588668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
1598668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	int err = 0, i;
1608668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1618668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	const u16 st6422_bridge_init[][2] = {
1628668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ STV_ISO_ENABLE, 0x00 }, /* disable capture */
1638668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1436, 0x00 },
1648668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1432, 0x03 },	/* 0x00-0x1F brightness */
1651d00d6c1ff13607974fcd9469aa9466fcd253c3aJean-François Moine		{ 0x143a, 0xf9 },	/* 0x00-0x0F contrast */
1668668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x0509, 0x38 },	/* R */
1678668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x050a, 0x38 },	/* G */
1688668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x050b, 0x38 },	/* B */
1691d00d6c1ff13607974fcd9469aa9466fcd253c3aJean-François Moine		{ 0x050c, 0x2a },
1708668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x050d, 0x01 },
1718668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1728668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1738668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1431, 0x00 },	/* 0x00-0x07 ??? */
1748668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1433, 0x34 },	/* 160x120, 0x00-0x01 night filter */
1758668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1438, 0x18 },	/* 640x480 */
1768668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* 18 bayes */
1778668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* 10 compressed? */
1788668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1798668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1439, 0x00 },
180bf5c562a3e6f7fd4071284caa01f81b031aacc97Erik Andrén/* anti-noise?  0xa2 gives a perfect image */
1818668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1828668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x143b, 0x05 },
1838668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x143c, 0x00 },	/* 0x00-0x01 - ??? */
1848668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1858668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1868668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* shutter time 0x0000-0x03FF */
1878668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* low value  give good picures on moving objects (but requires much light) */
1888668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* high value gives good picures in darkness (but tends to be overexposed) */
1898668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x143e, 0x01 },
1908668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x143d, 0x00 },
1918668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1928668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1442, 0xe2 },
1938668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* write: 1x1x xxxx */
1948668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* read:  1x1x xxxx */
1958668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/*        bit 5 == button pressed and hold if 0 */
1968668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* write 0xe2,0xea */
1978668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
1988668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* 0x144a */
1998668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* 0x00 init */
2008668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* bit 7 == button has been pressed, but not handled */
2018668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2028668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* interrupt */
2038668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* if(urb->iso_frame_desc[i].status == 0x80) { */
2048668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* if(urb->iso_frame_desc[i].status == 0x88) { */
2058668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2068668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1500, 0xd0 },
2078668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1500, 0xd0 },
2088668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1500, 0x50 },	/* 0x00 - 0xFF  0x80 == compr ? */
2098668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2108668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1501, 0xaf },
211bf5c562a3e6f7fd4071284caa01f81b031aacc97Erik Andrén/* high val-> light area gets darker */
212bf5c562a3e6f7fd4071284caa01f81b031aacc97Erik Andrén/* low val -> light area gets lighter */
2138668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1502, 0xc2 },
214bf5c562a3e6f7fd4071284caa01f81b031aacc97Erik Andrén/* high val-> light area gets darker */
215bf5c562a3e6f7fd4071284caa01f81b031aacc97Erik Andrén/* low val -> light area gets lighter */
2168668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1503, 0x45 },
217bf5c562a3e6f7fd4071284caa01f81b031aacc97Erik Andrén/* high val-> light area gets darker */
218bf5c562a3e6f7fd4071284caa01f81b031aacc97Erik Andrén/* low val -> light area gets lighter */
2198668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x1505, 0x02 },
2208668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* 2  : 324x248  80352 bytes */
2218668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* 7  : 248x162  40176 bytes */
2228668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede/* c+f: 162*124  20088 bytes */
2238668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2248668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x150e, 0x8e },
2258668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x150f, 0x37 },
2268668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x15c0, 0x00 },
2278668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x15c3, 0x08 },	/* 0x04/0x14 ... test pictures ??? */
2288668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2298668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2308668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		{ 0x143f, 0x01 },	/* commit settings */
2318668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2328668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	};
2338668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2348668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
2358668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
2368668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede					       st6422_bridge_init[i][1]);
2378668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	}
2388668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2398668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	return err;
2408668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
2418668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
2428668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goedestatic void st6422_disconnect(struct sd *sd)
2438668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
2448668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	sd->sensor = NULL;
2458668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	kfree(sd->sensor_priv);
2468668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
2478668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
24871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic int setbrightness(struct sd *sd)
24971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine{
25071e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	struct st6422_settings *sensor_settings = sd->sensor_priv;
25171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
25271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	/* val goes from 0 -> 31 */
25371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	return stv06xx_write_bridge(sd, 0x1432,
25471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine			sensor_settings->ctrls[BRIGHTNESS].val);
25571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine}
25671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
25771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic int setcontrast(struct sd *sd)
25871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine{
25971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	struct st6422_settings *sensor_settings = sd->sensor_priv;
26071e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
26171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	/* Val goes from 0 -> 15 */
26271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	return stv06xx_write_bridge(sd, 0x143a,
26371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine			sensor_settings->ctrls[CONTRAST].val | 0xf0);
26471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine}
26571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
26671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic int setgain(struct sd *sd)
2678668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
26871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	struct st6422_settings *sensor_settings = sd->sensor_priv;
26971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	u8 gain;
270c0b33bdc5b8d9c1120dece660480d4dd86b817eeHans de Goede	int err;
2718668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
27271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	gain = sensor_settings->ctrls[GAIN].val;
2738668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
27471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	/* Set red, green, blue, gain */
27571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = stv06xx_write_bridge(sd, 0x0509, gain);
2768668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	if (err < 0)
2778668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		return err;
2788668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
27971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = stv06xx_write_bridge(sd, 0x050a, gain);
2808668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	if (err < 0)
2818668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		return err;
2828668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
28371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = stv06xx_write_bridge(sd, 0x050b, gain);
2848668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	if (err < 0)
2858668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		return err;
2868668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
28771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	/* 2 mystery writes */
28871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
2898668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	if (err < 0)
2908668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		return err;
2918668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
29271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	return stv06xx_write_bridge(sd, 0x050d, 0x01);
2938668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
2948668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
29571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic int setexposure(struct sd *sd)
2968668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
29771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	struct st6422_settings *sensor_settings = sd->sensor_priv;
29871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	u16 expo;
29971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	int err;
3008668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
30171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	expo = sensor_settings->ctrls[EXPOSURE].val;
30271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
30371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err < 0)
30471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		return err;
3058668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
30671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
3078668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
3088668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
30971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic int st6422_start(struct sd *sd)
3108668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
3118668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	int err;
31271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	struct cam *cam = &sd->gspca_dev.cam;
3138668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
31471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
31571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
31671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	else
31771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		err = stv06xx_write_bridge(sd, 0x1505, 0x02);
31871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err < 0)
31971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		return err;
3208668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
32171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = setbrightness(sd);
32271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err < 0)
32371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		return err;
3248668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
32571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = setcontrast(sd);
32671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err < 0)
32771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		return err;
32871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
32971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = setexposure(sd);
33071e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err < 0)
33171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		return err;
33271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
33371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = setgain(sd);
3348668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	if (err < 0)
3358668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede		return err;
3368668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
3378668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	/* commit settings */
3388668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
3398668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	return (err < 0) ? err : 0;
3408668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
3418668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
34271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic int st6422_stop(struct sd *sd)
3438668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
34471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	PDEBUG(D_STREAM, "Halting stream");
3458668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
3468668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	return 0;
3478668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
3488668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
34971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic void st6422_set_brightness(struct gspca_dev *gspca_dev)
3508668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
3518668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	int err;
3528668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	struct sd *sd = (struct sd *) gspca_dev;
3538668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
35471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = setbrightness(sd);
3558668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
3568668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	/* commit settings */
35771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err >= 0)
35871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
3598668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
36071e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	gspca_dev->usb_err = err;
3618668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
3628668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
36371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic void st6422_set_contrast(struct gspca_dev *gspca_dev)
3648668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
3658668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	int err;
3668668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	struct sd *sd = (struct sd *) gspca_dev;
3678668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
36871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = setcontrast(sd);
3698668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
3708668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	/* commit settings */
37171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err >= 0)
37271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
37371e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
37471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	gspca_dev->usb_err = err;
3758668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
3768668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
37771e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic void st6422_set_gain(struct gspca_dev *gspca_dev)
3788668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
37971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	int err;
3808668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	struct sd *sd = (struct sd *) gspca_dev;
3818668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
38271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = setgain(sd);
3838668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
38471e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	/* commit settings */
38571e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err >= 0)
38671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
3878668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
38871e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	gspca_dev->usb_err = err;
3898668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
3908668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
39171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moinestatic void st6422_set_exposure(struct gspca_dev *gspca_dev)
3928668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede{
3938668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	int err;
3948668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	struct sd *sd = (struct sd *) gspca_dev;
3958668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
39671e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	err = setexposure(sd);
3978668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede
3988668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede	/* commit settings */
39971e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	if (err >= 0)
40071e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine		err = stv06xx_write_bridge(sd, 0x143f, 0x01);
40171e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine
40271e84ea7f082eb02df6ef40f55d2c4a998f6e1dfJean-François Moine	gspca_dev->usb_err = err;
4038668d504d72c384fbfb6ab6f5d02a9fe4d813554Hans de Goede}
404