cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pac7302.c (26876B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Pixart PAC7302 driver
      4 *
      5 * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
      6 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
      7 *
      8 * Separated from Pixart PAC7311 library by Márton Németh
      9 * Camera button input handling by Márton Németh <nm127@freemail.hu>
     10 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
     11 */
     12
     13/*
     14 * Some documentation about various registers as determined by trial and error.
     15 *
     16 * Register page 0:
     17 *
     18 * Address	Description
     19 * 0x01		Red balance control
     20 * 0x02		Green balance control
     21 * 0x03		Blue balance control
     22 *		     The Windows driver uses a quadratic approach to map
     23 *		     the settable values (0-200) on register values:
     24 *		     min=0x20, default=0x40, max=0x80
     25 * 0x0f-0x20	Color and saturation control
     26 * 0xa2-0xab	Brightness, contrast and gamma control
     27 * 0xb6		Sharpness control (bits 0-4)
     28 *
     29 * Register page 1:
     30 *
     31 * Address	Description
     32 * 0x78		Global control, bit 6 controls the LED (inverted)
     33 * 0x80		Compression balance, 2 interesting settings:
     34 *		0x0f Default
     35 *		0x50 Values >= this switch the camera to a lower compression,
     36 *		     using the same table for both luminance and chrominance.
     37 *		     This gives a sharper picture. Only usable when running
     38 *		     at < 15 fps! Note currently the driver does not use this
     39 *		     as the quality gain is small and the generated JPG-s are
     40 *		     only understood by v4l-utils >= 0.8.9
     41 *
     42 * Register page 3:
     43 *
     44 * Address	Description
     45 * 0x02		Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
     46 *		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
     47 * 0x03		Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
     48 * 0x04		Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
     49 *		63 -> ~27 fps, the 2 msb's must always be 1 !!
     50 * 0x05		Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
     51 *		1 -> ~30 fps, 2 -> ~20 fps
     52 * 0x0e		Exposure bits 0-7, 0-448, 0 = use full frame time
     53 * 0x0f		Exposure bit 8, 0-448, 448 = no exposure at all
     54 * 0x10		Gain 0-31
     55 * 0x12		Another gain 0-31, unlike 0x10 this one seems to start with an
     56 *		amplification value of 1 rather then 0 at its lowest setting
     57 * 0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
     58 * 0x80		Another framerate control, best left at 1, moving it from 1 to
     59 *		2 causes the framerate to become 3/4th of what it was, and
     60 *		also seems to cause pixel averaging, resulting in an effective
     61 *		resolution of 320x240 and thus a much blockier image
     62 *
     63 * The registers are accessed in the following functions:
     64 *
     65 * Page | Register   | Function
     66 * -----+------------+---------------------------------------------------
     67 *  0   | 0x01       | setredbalance()
     68 *  0   | 0x03       | setbluebalance()
     69 *  0   | 0x0f..0x20 | setcolors()
     70 *  0   | 0xa2..0xab | setbrightcont()
     71 *  0   | 0xb6       | setsharpness()
     72 *  0   | 0xc6       | setwhitebalance()
     73 *  0   | 0xdc       | setbrightcont(), setcolors()
     74 *  3   | 0x02       | setexposure()
     75 *  3   | 0x10, 0x12 | setgain()
     76 *  3   | 0x11       | setcolors(), setgain(), setexposure(), sethvflip()
     77 *  3   | 0x21       | sethvflip()
     78 */
     79
     80#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     81
     82#include <linux/input.h>
     83#include "gspca.h"
     84/* Include pac common sof detection functions */
     85#include "pac_common.h"
     86
     87#define PAC7302_RGB_BALANCE_MIN		  0
     88#define PAC7302_RGB_BALANCE_MAX		200
     89#define PAC7302_RGB_BALANCE_DEFAULT	100
     90#define PAC7302_GAIN_DEFAULT		 15
     91#define PAC7302_GAIN_KNEE		 42
     92#define PAC7302_EXPOSURE_DEFAULT	 66 /* 33 ms / 30 fps */
     93#define PAC7302_EXPOSURE_KNEE		133 /* 66 ms / 15 fps */
     94
     95MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, Thomas Kaiser thomas@kaiser-linux.li");
     96MODULE_DESCRIPTION("Pixart PAC7302");
     97MODULE_LICENSE("GPL");
     98
     99struct sd {
    100	struct gspca_dev gspca_dev;		/* !! must be the first item */
    101
    102	struct { /* brightness / contrast cluster */
    103		struct v4l2_ctrl *brightness;
    104		struct v4l2_ctrl *contrast;
    105	};
    106	struct v4l2_ctrl *saturation;
    107	struct v4l2_ctrl *white_balance;
    108	struct v4l2_ctrl *red_balance;
    109	struct v4l2_ctrl *blue_balance;
    110	struct { /* flip cluster */
    111		struct v4l2_ctrl *hflip;
    112		struct v4l2_ctrl *vflip;
    113	};
    114	struct v4l2_ctrl *sharpness;
    115	u8 flags;
    116#define FL_HFLIP 0x01		/* mirrored by default */
    117#define FL_VFLIP 0x02		/* vertical flipped by default */
    118
    119	u8 sof_read;
    120	s8 autogain_ignore_frames;
    121
    122	atomic_t avg_lum;
    123};
    124
    125static const struct v4l2_pix_format vga_mode[] = {
    126	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
    127		.bytesperline = 640,
    128		.sizeimage = 640 * 480 * 3 / 8 + 590,
    129		.colorspace = V4L2_COLORSPACE_JPEG,
    130	},
    131};
    132
    133#define LOAD_PAGE3		255
    134#define END_OF_SEQUENCE		0
    135
    136static const u8 init_7302[] = {
    137/*	index,value */
    138	0xff, 0x01,		/* page 1 */
    139	0x78, 0x00,		/* deactivate */
    140	0xff, 0x01,
    141	0x78, 0x40,		/* led off */
    142};
    143static const u8 start_7302[] = {
    144/*	index, len, [value]* */
    145	0xff, 1,	0x00,		/* page 0 */
    146	0x00, 12,	0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
    147			0x00, 0x00, 0x00, 0x00,
    148	0x0d, 24,	0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
    149			0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
    150			0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
    151	0x26, 2,	0xaa, 0xaa,
    152	0x2e, 1,	0x31,
    153	0x38, 1,	0x01,
    154	0x3a, 3,	0x14, 0xff, 0x5a,
    155	0x43, 11,	0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
    156			0x00, 0x54, 0x11,
    157	0x55, 1,	0x00,
    158	0x62, 4,	0x10, 0x1e, 0x1e, 0x18,
    159	0x6b, 1,	0x00,
    160	0x6e, 3,	0x08, 0x06, 0x00,
    161	0x72, 3,	0x00, 0xff, 0x00,
    162	0x7d, 23,	0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
    163			0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
    164			0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
    165	0xa2, 10,	0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
    166			0xd2, 0xeb,
    167	0xaf, 1,	0x02,
    168	0xb5, 2,	0x08, 0x08,
    169	0xb8, 2,	0x08, 0x88,
    170	0xc4, 4,	0xae, 0x01, 0x04, 0x01,
    171	0xcc, 1,	0x00,
    172	0xd1, 11,	0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
    173			0xc1, 0xd7, 0xec,
    174	0xdc, 1,	0x01,
    175	0xff, 1,	0x01,		/* page 1 */
    176	0x12, 3,	0x02, 0x00, 0x01,
    177	0x3e, 2,	0x00, 0x00,
    178	0x76, 5,	0x01, 0x20, 0x40, 0x00, 0xf2,
    179	0x7c, 1,	0x00,
    180	0x7f, 10,	0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
    181			0x02, 0x00,
    182	0x96, 5,	0x01, 0x10, 0x04, 0x01, 0x04,
    183	0xc8, 14,	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
    184			0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
    185	0xd8, 1,	0x01,
    186	0xdb, 2,	0x00, 0x01,
    187	0xde, 7,	0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
    188	0xe6, 4,	0x00, 0x00, 0x00, 0x01,
    189	0xeb, 1,	0x00,
    190	0xff, 1,	0x02,		/* page 2 */
    191	0x22, 1,	0x00,
    192	0xff, 1,	0x03,		/* page 3 */
    193	0, LOAD_PAGE3,			/* load the page 3 */
    194	0x11, 1,	0x01,
    195	0xff, 1,	0x02,		/* page 2 */
    196	0x13, 1,	0x00,
    197	0x22, 4,	0x1f, 0xa4, 0xf0, 0x96,
    198	0x27, 2,	0x14, 0x0c,
    199	0x2a, 5,	0xc8, 0x00, 0x18, 0x12, 0x22,
    200	0x64, 8,	0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
    201	0x6e, 1,	0x08,
    202	0xff, 1,	0x01,		/* page 1 */
    203	0x78, 1,	0x00,
    204	0, END_OF_SEQUENCE		/* end of sequence */
    205};
    206
    207#define SKIP		0xaa
    208/* page 3 - the value SKIP says skip the index - see reg_w_page() */
    209static const u8 page3_7302[] = {
    210	0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
    211	0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
    212	0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    213	0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
    214	0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
    215	0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
    216	0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
    217	0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    218	0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
    219	SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
    220	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    221	0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
    222	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    223	0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
    224	0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
    225	0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
    226	0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
    227	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    228	0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
    229	0x00
    230};
    231
    232static void reg_w_buf(struct gspca_dev *gspca_dev,
    233		u8 index,
    234		  const u8 *buffer, int len)
    235{
    236	int ret;
    237
    238	if (gspca_dev->usb_err < 0)
    239		return;
    240	memcpy(gspca_dev->usb_buf, buffer, len);
    241	ret = usb_control_msg(gspca_dev->dev,
    242			usb_sndctrlpipe(gspca_dev->dev, 0),
    243			0,		/* request */
    244			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
    245			0,		/* value */
    246			index, gspca_dev->usb_buf, len,
    247			500);
    248	if (ret < 0) {
    249		pr_err("reg_w_buf failed i: %02x error %d\n",
    250		       index, ret);
    251		gspca_dev->usb_err = ret;
    252	}
    253}
    254
    255
    256static void reg_w(struct gspca_dev *gspca_dev,
    257		u8 index,
    258		u8 value)
    259{
    260	int ret;
    261
    262	if (gspca_dev->usb_err < 0)
    263		return;
    264	gspca_dev->usb_buf[0] = value;
    265	ret = usb_control_msg(gspca_dev->dev,
    266			usb_sndctrlpipe(gspca_dev->dev, 0),
    267			0,			/* request */
    268			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
    269			0, index, gspca_dev->usb_buf, 1,
    270			500);
    271	if (ret < 0) {
    272		pr_err("reg_w() failed i: %02x v: %02x error %d\n",
    273		       index, value, ret);
    274		gspca_dev->usb_err = ret;
    275	}
    276}
    277
    278static void reg_w_seq(struct gspca_dev *gspca_dev,
    279		const u8 *seq, int len)
    280{
    281	while (--len >= 0) {
    282		reg_w(gspca_dev, seq[0], seq[1]);
    283		seq += 2;
    284	}
    285}
    286
    287/* load the beginning of a page */
    288static void reg_w_page(struct gspca_dev *gspca_dev,
    289			const u8 *page, int len)
    290{
    291	int index;
    292	int ret = 0;
    293
    294	if (gspca_dev->usb_err < 0)
    295		return;
    296	for (index = 0; index < len; index++) {
    297		if (page[index] == SKIP)		/* skip this index */
    298			continue;
    299		gspca_dev->usb_buf[0] = page[index];
    300		ret = usb_control_msg(gspca_dev->dev,
    301				usb_sndctrlpipe(gspca_dev->dev, 0),
    302				0,			/* request */
    303			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
    304				0, index, gspca_dev->usb_buf, 1,
    305				500);
    306		if (ret < 0) {
    307			pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
    308			       index, page[index], ret);
    309			gspca_dev->usb_err = ret;
    310			break;
    311		}
    312	}
    313}
    314
    315/* output a variable sequence */
    316static void reg_w_var(struct gspca_dev *gspca_dev,
    317			const u8 *seq,
    318			const u8 *page3, unsigned int page3_len)
    319{
    320	int index, len;
    321
    322	for (;;) {
    323		index = *seq++;
    324		len = *seq++;
    325		switch (len) {
    326		case END_OF_SEQUENCE:
    327			return;
    328		case LOAD_PAGE3:
    329			reg_w_page(gspca_dev, page3, page3_len);
    330			break;
    331		default:
    332			if (len > USB_BUF_SZ) {
    333				gspca_err(gspca_dev, "Incorrect variable sequence\n");
    334				return;
    335			}
    336			while (len > 0) {
    337				if (len < 8) {
    338					reg_w_buf(gspca_dev,
    339						index, seq, len);
    340					seq += len;
    341					break;
    342				}
    343				reg_w_buf(gspca_dev, index, seq, 8);
    344				seq += 8;
    345				index += 8;
    346				len -= 8;
    347			}
    348		}
    349	}
    350	/* not reached */
    351}
    352
    353/* this function is called at probe time for pac7302 */
    354static int sd_config(struct gspca_dev *gspca_dev,
    355			const struct usb_device_id *id)
    356{
    357	struct sd *sd = (struct sd *) gspca_dev;
    358	struct cam *cam;
    359
    360	cam = &gspca_dev->cam;
    361
    362	cam->cam_mode = vga_mode;	/* only 640x480 */
    363	cam->nmodes = ARRAY_SIZE(vga_mode);
    364
    365	sd->flags = id->driver_info;
    366	return 0;
    367}
    368
    369static void setbrightcont(struct gspca_dev *gspca_dev)
    370{
    371	struct sd *sd = (struct sd *) gspca_dev;
    372	int i, v;
    373	static const u8 max[10] =
    374		{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
    375		 0xd4, 0xec};
    376	static const u8 delta[10] =
    377		{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
    378		 0x11, 0x0b};
    379
    380	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
    381	for (i = 0; i < 10; i++) {
    382		v = max[i];
    383		v += (sd->brightness->val - (s32)sd->brightness->maximum)
    384			* 150 / (s32)sd->brightness->maximum; /* 200 ? */
    385		v -= delta[i] * sd->contrast->val / (s32)sd->contrast->maximum;
    386		if (v < 0)
    387			v = 0;
    388		else if (v > 0xff)
    389			v = 0xff;
    390		reg_w(gspca_dev, 0xa2 + i, v);
    391	}
    392	reg_w(gspca_dev, 0xdc, 0x01);
    393}
    394
    395static void setcolors(struct gspca_dev *gspca_dev)
    396{
    397	struct sd *sd = (struct sd *) gspca_dev;
    398	int i, v;
    399	static const int a[9] =
    400		{217, -212, 0, -101, 170, -67, -38, -315, 355};
    401	static const int b[9] =
    402		{19, 106, 0, 19, 106, 1, 19, 106, 1};
    403
    404	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
    405	reg_w(gspca_dev, 0x11, 0x01);
    406	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
    407	for (i = 0; i < 9; i++) {
    408		v = a[i] * sd->saturation->val / (s32)sd->saturation->maximum;
    409		v += b[i];
    410		reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
    411		reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
    412	}
    413	reg_w(gspca_dev, 0xdc, 0x01);
    414}
    415
    416static void setwhitebalance(struct gspca_dev *gspca_dev)
    417{
    418	struct sd *sd = (struct sd *) gspca_dev;
    419
    420	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
    421	reg_w(gspca_dev, 0xc6, sd->white_balance->val);
    422
    423	reg_w(gspca_dev, 0xdc, 0x01);
    424}
    425
    426static u8 rgbbalance_ctrl_to_reg_value(s32 rgb_ctrl_val)
    427{
    428	const unsigned int k = 1000;	/* precision factor */
    429	unsigned int norm;
    430
    431	/* Normed value [0...k] */
    432	norm = k * (rgb_ctrl_val - PAC7302_RGB_BALANCE_MIN)
    433		    / (PAC7302_RGB_BALANCE_MAX - PAC7302_RGB_BALANCE_MIN);
    434	/* Qudratic apporach improves control at small (register) values: */
    435	return 64 * norm * norm / (k*k)  +  32 * norm / k  +  32;
    436	/* Y = 64*X*X + 32*X + 32
    437	 * => register values 0x20-0x80; Windows driver uses these limits */
    438
    439	/* NOTE: for full value range (0x00-0xff) use
    440	 *         Y = 254*X*X + X
    441	 *         => 254 * norm * norm / (k*k)  +  1 * norm / k	*/
    442}
    443
    444static void setredbalance(struct gspca_dev *gspca_dev)
    445{
    446	struct sd *sd = (struct sd *) gspca_dev;
    447
    448	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
    449	reg_w(gspca_dev, 0x01,
    450	      rgbbalance_ctrl_to_reg_value(sd->red_balance->val));
    451
    452	reg_w(gspca_dev, 0xdc, 0x01);
    453}
    454
    455static void setbluebalance(struct gspca_dev *gspca_dev)
    456{
    457	struct sd *sd = (struct sd *) gspca_dev;
    458
    459	reg_w(gspca_dev, 0xff, 0x00);			/* page 0 */
    460	reg_w(gspca_dev, 0x03,
    461	      rgbbalance_ctrl_to_reg_value(sd->blue_balance->val));
    462
    463	reg_w(gspca_dev, 0xdc, 0x01);
    464}
    465
    466static void setgain(struct gspca_dev *gspca_dev)
    467{
    468	u8 reg10, reg12;
    469
    470	if (gspca_dev->gain->val < 32) {
    471		reg10 = gspca_dev->gain->val;
    472		reg12 = 0;
    473	} else {
    474		reg10 = 31;
    475		reg12 = gspca_dev->gain->val - 31;
    476	}
    477
    478	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
    479	reg_w(gspca_dev, 0x10, reg10);
    480	reg_w(gspca_dev, 0x12, reg12);
    481
    482	/* load registers to sensor (Bit 0, auto clear) */
    483	reg_w(gspca_dev, 0x11, 0x01);
    484}
    485
    486static void setexposure(struct gspca_dev *gspca_dev)
    487{
    488	u8 clockdiv;
    489	u16 exposure;
    490
    491	/*
    492	 * Register 2 of frame 3 contains the clock divider configuring the
    493	 * no fps according to the formula: 90 / reg. sd->exposure is the
    494	 * desired exposure time in 0.5 ms.
    495	 */
    496	clockdiv = (90 * gspca_dev->exposure->val + 1999) / 2000;
    497
    498	/*
    499	 * Note clockdiv = 3 also works, but when running at 30 fps, depending
    500	 * on the scene being recorded, the camera switches to another
    501	 * quantization table for certain JPEG blocks, and we don't know how
    502	 * to decompress these blocks. So we cap the framerate at 15 fps.
    503	 */
    504	if (clockdiv < 6)
    505		clockdiv = 6;
    506	else if (clockdiv > 63)
    507		clockdiv = 63;
    508
    509	/*
    510	 * Register 2 MUST be a multiple of 3, except when between 6 and 12?
    511	 * Always round up, otherwise we cannot get the desired frametime
    512	 * using the partial frame time exposure control.
    513	 */
    514	if (clockdiv < 6 || clockdiv > 12)
    515		clockdiv = ((clockdiv + 2) / 3) * 3;
    516
    517	/*
    518	 * frame exposure time in ms = 1000 * clockdiv / 90    ->
    519	 * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90)
    520	 */
    521	exposure = (gspca_dev->exposure->val * 45 * 448) / (1000 * clockdiv);
    522	/* 0 = use full frametime, 448 = no exposure, reverse it */
    523	exposure = 448 - exposure;
    524
    525	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
    526	reg_w(gspca_dev, 0x02, clockdiv);
    527	reg_w(gspca_dev, 0x0e, exposure & 0xff);
    528	reg_w(gspca_dev, 0x0f, exposure >> 8);
    529
    530	/* load registers to sensor (Bit 0, auto clear) */
    531	reg_w(gspca_dev, 0x11, 0x01);
    532}
    533
    534static void sethvflip(struct gspca_dev *gspca_dev)
    535{
    536	struct sd *sd = (struct sd *) gspca_dev;
    537	u8 data, hflip, vflip;
    538
    539	hflip = sd->hflip->val;
    540	if (sd->flags & FL_HFLIP)
    541		hflip = !hflip;
    542	vflip = sd->vflip->val;
    543	if (sd->flags & FL_VFLIP)
    544		vflip = !vflip;
    545
    546	reg_w(gspca_dev, 0xff, 0x03);			/* page 3 */
    547	data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
    548	reg_w(gspca_dev, 0x21, data);
    549
    550	/* load registers to sensor (Bit 0, auto clear) */
    551	reg_w(gspca_dev, 0x11, 0x01);
    552}
    553
    554static void setsharpness(struct gspca_dev *gspca_dev)
    555{
    556	struct sd *sd = (struct sd *) gspca_dev;
    557
    558	reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
    559	reg_w(gspca_dev, 0xb6, sd->sharpness->val);
    560
    561	reg_w(gspca_dev, 0xdc, 0x01);
    562}
    563
    564/* this function is called at probe and resume time for pac7302 */
    565static int sd_init(struct gspca_dev *gspca_dev)
    566{
    567	reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
    568	return gspca_dev->usb_err;
    569}
    570
    571static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
    572{
    573	struct gspca_dev *gspca_dev =
    574		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
    575	struct sd *sd = (struct sd *)gspca_dev;
    576
    577	gspca_dev->usb_err = 0;
    578
    579	if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
    580		/* when switching to autogain set defaults to make sure
    581		   we are on a valid point of the autogain gain /
    582		   exposure knee graph, and give this change time to
    583		   take effect before doing autogain. */
    584		gspca_dev->exposure->val    = PAC7302_EXPOSURE_DEFAULT;
    585		gspca_dev->gain->val        = PAC7302_GAIN_DEFAULT;
    586		sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
    587	}
    588
    589	if (!gspca_dev->streaming)
    590		return 0;
    591
    592	switch (ctrl->id) {
    593	case V4L2_CID_BRIGHTNESS:
    594		setbrightcont(gspca_dev);
    595		break;
    596	case V4L2_CID_SATURATION:
    597		setcolors(gspca_dev);
    598		break;
    599	case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
    600		setwhitebalance(gspca_dev);
    601		break;
    602	case V4L2_CID_RED_BALANCE:
    603		setredbalance(gspca_dev);
    604		break;
    605	case V4L2_CID_BLUE_BALANCE:
    606		setbluebalance(gspca_dev);
    607		break;
    608	case V4L2_CID_AUTOGAIN:
    609		if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
    610			setexposure(gspca_dev);
    611		if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
    612			setgain(gspca_dev);
    613		break;
    614	case V4L2_CID_HFLIP:
    615		sethvflip(gspca_dev);
    616		break;
    617	case V4L2_CID_SHARPNESS:
    618		setsharpness(gspca_dev);
    619		break;
    620	default:
    621		return -EINVAL;
    622	}
    623	return gspca_dev->usb_err;
    624}
    625
    626static const struct v4l2_ctrl_ops sd_ctrl_ops = {
    627	.s_ctrl = sd_s_ctrl,
    628};
    629
    630/* this function is called at probe time */
    631static int sd_init_controls(struct gspca_dev *gspca_dev)
    632{
    633	struct sd *sd = (struct sd *) gspca_dev;
    634	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
    635
    636	gspca_dev->vdev.ctrl_handler = hdl;
    637	v4l2_ctrl_handler_init(hdl, 12);
    638
    639	sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    640					V4L2_CID_BRIGHTNESS, 0, 32, 1, 16);
    641	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    642					V4L2_CID_CONTRAST, 0, 255, 1, 127);
    643
    644	sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    645					V4L2_CID_SATURATION, 0, 255, 1, 127);
    646	sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    647					V4L2_CID_WHITE_BALANCE_TEMPERATURE,
    648					0, 255, 1, 55);
    649	sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    650					V4L2_CID_RED_BALANCE,
    651					PAC7302_RGB_BALANCE_MIN,
    652					PAC7302_RGB_BALANCE_MAX,
    653					1, PAC7302_RGB_BALANCE_DEFAULT);
    654	sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    655					V4L2_CID_BLUE_BALANCE,
    656					PAC7302_RGB_BALANCE_MIN,
    657					PAC7302_RGB_BALANCE_MAX,
    658					1, PAC7302_RGB_BALANCE_DEFAULT);
    659
    660	gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    661					V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
    662	gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    663					V4L2_CID_EXPOSURE, 0, 1023, 1,
    664					PAC7302_EXPOSURE_DEFAULT);
    665	gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    666					V4L2_CID_GAIN, 0, 62, 1,
    667					PAC7302_GAIN_DEFAULT);
    668
    669	sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    670		V4L2_CID_HFLIP, 0, 1, 1, 0);
    671	sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    672		V4L2_CID_VFLIP, 0, 1, 1, 0);
    673
    674	sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    675					V4L2_CID_SHARPNESS, 0, 15, 1, 8);
    676
    677	if (hdl->error) {
    678		pr_err("Could not initialize controls\n");
    679		return hdl->error;
    680	}
    681
    682	v4l2_ctrl_cluster(2, &sd->brightness);
    683	v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
    684	v4l2_ctrl_cluster(2, &sd->hflip);
    685	return 0;
    686}
    687
    688/* -- start the camera -- */
    689static int sd_start(struct gspca_dev *gspca_dev)
    690{
    691	struct sd *sd = (struct sd *) gspca_dev;
    692
    693	reg_w_var(gspca_dev, start_7302,
    694		page3_7302, sizeof(page3_7302));
    695
    696	sd->sof_read = 0;
    697	sd->autogain_ignore_frames = 0;
    698	atomic_set(&sd->avg_lum, 270 + sd->brightness->val);
    699
    700	/* start stream */
    701	reg_w(gspca_dev, 0xff, 0x01);
    702	reg_w(gspca_dev, 0x78, 0x01);
    703
    704	return gspca_dev->usb_err;
    705}
    706
    707static void sd_stopN(struct gspca_dev *gspca_dev)
    708{
    709
    710	/* stop stream */
    711	reg_w(gspca_dev, 0xff, 0x01);
    712	reg_w(gspca_dev, 0x78, 0x00);
    713}
    714
    715/* called on streamoff with alt 0 and on disconnect for pac7302 */
    716static void sd_stop0(struct gspca_dev *gspca_dev)
    717{
    718	if (!gspca_dev->present)
    719		return;
    720	reg_w(gspca_dev, 0xff, 0x01);
    721	reg_w(gspca_dev, 0x78, 0x40);
    722}
    723
    724static void do_autogain(struct gspca_dev *gspca_dev)
    725{
    726	struct sd *sd = (struct sd *) gspca_dev;
    727	int avg_lum = atomic_read(&sd->avg_lum);
    728	int desired_lum;
    729	const int deadzone = 30;
    730
    731	if (sd->autogain_ignore_frames < 0)
    732		return;
    733
    734	if (sd->autogain_ignore_frames > 0) {
    735		sd->autogain_ignore_frames--;
    736	} else {
    737		desired_lum = 270 + sd->brightness->val;
    738
    739		if (gspca_expo_autogain(gspca_dev, avg_lum, desired_lum,
    740					deadzone, PAC7302_GAIN_KNEE,
    741					PAC7302_EXPOSURE_KNEE))
    742			sd->autogain_ignore_frames =
    743						PAC_AUTOGAIN_IGNORE_FRAMES;
    744	}
    745}
    746
    747/* JPEG header */
    748static const u8 jpeg_header[] = {
    749	0xff, 0xd8,	/* SOI: Start of Image */
    750
    751	0xff, 0xc0,	/* SOF0: Start of Frame (Baseline DCT) */
    752	0x00, 0x11,	/* length = 17 bytes (including this length field) */
    753	0x08,		/* Precision: 8 */
    754	0x02, 0x80,	/* height = 640 (image rotated) */
    755	0x01, 0xe0,	/* width = 480 */
    756	0x03,		/* Number of image components: 3 */
    757	0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
    758	0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
    759	0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
    760
    761	0xff, 0xda,	/* SOS: Start Of Scan */
    762	0x00, 0x0c,	/* length = 12 bytes (including this length field) */
    763	0x03,		/* number of components: 3 */
    764	0x01, 0x00,	/* selector 1, table 0x00 */
    765	0x02, 0x11,	/* selector 2, table 0x11 */
    766	0x03, 0x11,	/* selector 3, table 0x11 */
    767	0x00, 0x3f,	/* Spectral selection: 0 .. 63 */
    768	0x00		/* Successive approximation: 0 */
    769};
    770
    771/* this function is run at interrupt level */
    772static void sd_pkt_scan(struct gspca_dev *gspca_dev,
    773			u8 *data,			/* isoc packet */
    774			int len)			/* iso packet length */
    775{
    776	struct sd *sd = (struct sd *) gspca_dev;
    777	u8 *image;
    778	u8 *sof;
    779
    780	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
    781	if (sof) {
    782		int n, lum_offset, footer_length;
    783
    784		/*
    785		 * 6 bytes after the FF D9 EOF marker a number of lumination
    786		 * bytes are send corresponding to different parts of the
    787		 * image, the 14th and 15th byte after the EOF seem to
    788		 * correspond to the center of the image.
    789		 */
    790		lum_offset = 61 + sizeof pac_sof_marker;
    791		footer_length = 74;
    792
    793		/* Finish decoding current frame */
    794		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
    795		if (n < 0) {
    796			gspca_dev->image_len += n;
    797		} else {
    798			gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
    799		}
    800
    801		image = gspca_dev->image;
    802		if (image != NULL
    803		 && image[gspca_dev->image_len - 2] == 0xff
    804		 && image[gspca_dev->image_len - 1] == 0xd9)
    805			gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
    806
    807		n = sof - data;
    808		len -= n;
    809		data = sof;
    810
    811		/* Get average lumination */
    812		if (gspca_dev->last_packet_type == LAST_PACKET &&
    813				n >= lum_offset)
    814			atomic_set(&sd->avg_lum, data[-lum_offset] +
    815						data[-lum_offset + 1]);
    816
    817		/* Start the new frame with the jpeg header */
    818		/* The PAC7302 has the image rotated 90 degrees */
    819		gspca_frame_add(gspca_dev, FIRST_PACKET,
    820				jpeg_header, sizeof jpeg_header);
    821	}
    822	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
    823}
    824
    825#ifdef CONFIG_VIDEO_ADV_DEBUG
    826static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
    827			const struct v4l2_dbg_register *reg)
    828{
    829	u8 index;
    830	u8 value;
    831
    832	/*
    833	 * reg->reg: bit0..15: reserved for register index (wIndex is 16bit
    834	 *		       long on the USB bus)
    835	 */
    836	if (reg->match.addr == 0 &&
    837	    (reg->reg < 0x000000ff) &&
    838	    (reg->val <= 0x000000ff)
    839	) {
    840		/* Currently writing to page 0 is only supported. */
    841		/* reg_w() only supports 8bit index */
    842		index = reg->reg;
    843		value = reg->val;
    844
    845		/*
    846		 * Note that there shall be no access to other page
    847		 * by any other function between the page switch and
    848		 * the actual register write.
    849		 */
    850		reg_w(gspca_dev, 0xff, 0x00);		/* page 0 */
    851		reg_w(gspca_dev, index, value);
    852
    853		reg_w(gspca_dev, 0xdc, 0x01);
    854	}
    855	return gspca_dev->usb_err;
    856}
    857#endif
    858
    859#if IS_ENABLED(CONFIG_INPUT)
    860static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
    861			u8 *data,		/* interrupt packet data */
    862			int len)		/* interrupt packet length */
    863{
    864	int ret = -EINVAL;
    865	u8 data0, data1;
    866
    867	if (len == 2) {
    868		data0 = data[0];
    869		data1 = data[1];
    870		if ((data0 == 0x00 && data1 == 0x11) ||
    871		    (data0 == 0x22 && data1 == 0x33) ||
    872		    (data0 == 0x44 && data1 == 0x55) ||
    873		    (data0 == 0x66 && data1 == 0x77) ||
    874		    (data0 == 0x88 && data1 == 0x99) ||
    875		    (data0 == 0xaa && data1 == 0xbb) ||
    876		    (data0 == 0xcc && data1 == 0xdd) ||
    877		    (data0 == 0xee && data1 == 0xff)) {
    878			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
    879			input_sync(gspca_dev->input_dev);
    880			input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
    881			input_sync(gspca_dev->input_dev);
    882			ret = 0;
    883		}
    884	}
    885
    886	return ret;
    887}
    888#endif
    889
    890/* sub-driver description for pac7302 */
    891static const struct sd_desc sd_desc = {
    892	.name = KBUILD_MODNAME,
    893	.config = sd_config,
    894	.init = sd_init,
    895	.init_controls = sd_init_controls,
    896	.start = sd_start,
    897	.stopN = sd_stopN,
    898	.stop0 = sd_stop0,
    899	.pkt_scan = sd_pkt_scan,
    900	.dq_callback = do_autogain,
    901#ifdef CONFIG_VIDEO_ADV_DEBUG
    902	.set_register = sd_dbg_s_register,
    903#endif
    904#if IS_ENABLED(CONFIG_INPUT)
    905	.int_pkt_scan = sd_int_pkt_scan,
    906#endif
    907};
    908
    909/* -- module initialisation -- */
    910static const struct usb_device_id device_table[] = {
    911	{USB_DEVICE(0x06f8, 0x3009)},
    912	{USB_DEVICE(0x06f8, 0x301b)},
    913	{USB_DEVICE(0x093a, 0x2620)},
    914	{USB_DEVICE(0x093a, 0x2621)},
    915	{USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
    916	{USB_DEVICE(0x093a, 0x2623), .driver_info = FL_VFLIP},
    917	{USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
    918	{USB_DEVICE(0x093a, 0x2625)},
    919	{USB_DEVICE(0x093a, 0x2626)},
    920	{USB_DEVICE(0x093a, 0x2627), .driver_info = FL_VFLIP},
    921	{USB_DEVICE(0x093a, 0x2628)},
    922	{USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
    923	{USB_DEVICE(0x093a, 0x262a)},
    924	{USB_DEVICE(0x093a, 0x262c)},
    925	{USB_DEVICE(0x145f, 0x013c)},
    926	{USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */
    927	{}
    928};
    929MODULE_DEVICE_TABLE(usb, device_table);
    930
    931/* -- device connect -- */
    932static int sd_probe(struct usb_interface *intf,
    933			const struct usb_device_id *id)
    934{
    935	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
    936				THIS_MODULE);
    937}
    938
    939static struct usb_driver sd_driver = {
    940	.name = KBUILD_MODNAME,
    941	.id_table = device_table,
    942	.probe = sd_probe,
    943	.disconnect = gspca_disconnect,
    944#ifdef CONFIG_PM
    945	.suspend = gspca_suspend,
    946	.resume = gspca_resume,
    947	.reset_resume = gspca_resume,
    948#endif
    949};
    950
    951module_usb_driver(sd_driver);