Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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