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