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)  * Jeilinj subdriver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Supports some Jeilin dual-mode cameras which use bulk transport and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * download raw JPEG data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Copyright (C) 2009 Theodore Kilgore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * Sportscam DV15 support and control settings are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * Copyright (C) 2011 Patrice Chotard
^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) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #define MODULE_NAME "jeilinj"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "gspca.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "jpeg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) /* Default timeouts, in ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define JEILINJ_CMD_TIMEOUT 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define JEILINJ_CMD_DELAY 160
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define JEILINJ_DATA_TIMEOUT 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) /* Maximum transfer size to use. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define JEILINJ_MAX_TRANSFER 0x200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define FRAME_HEADER_LEN 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define FRAME_START 0xFFFFFFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	SAKAR_57379,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	SPORTSCAM_DV15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define CAMQUALITY_MIN 0	/* highest cam quality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define CAMQUALITY_MAX 97	/* lowest cam quality  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /* Structure to hold all of our device specific stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) struct sd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct gspca_dev gspca_dev;	/* !! must be the first item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	int blocks_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	const struct v4l2_pix_format *cap_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct v4l2_ctrl *freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	struct v4l2_ctrl *jpegqual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	/* Driver stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	u8 quality;				 /* image quality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define QUALITY_MIN 35
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define QUALITY_MAX 85
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define QUALITY_DEF 85
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	u8 jpeg_hdr[JPEG_HDR_SZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) struct jlj_command {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	unsigned char instruction[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	unsigned char ack_wanted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	unsigned char delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) /* AFAICT these cameras will only do 320x240. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static struct v4l2_pix_format jlj_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	{ 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		.bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		.sizeimage = 320 * 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		.colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		.priv = 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	{ 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		.bytesperline = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		.sizeimage = 640 * 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		.colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		.priv = 0}
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * and 0x82 for bulk transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) /* All commands are two bytes only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	memcpy(gspca_dev->usb_buf, command, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	retval = usb_bulk_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 			usb_sndbulkpipe(gspca_dev->dev, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			gspca_dev->usb_buf, 2, NULL, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		pr_err("command write [%02x] error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		       gspca_dev->usb_buf[0], retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		gspca_dev->usb_err = retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Responses are one byte only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char *response)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	retval = usb_bulk_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	usb_rcvbulkpipe(gspca_dev->dev, 0x84),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				gspca_dev->usb_buf, 1, NULL, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	*response = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	if (retval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		pr_err("read command [%02x] error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		       gspca_dev->usb_buf[0], retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		gspca_dev->usb_err = retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void setfreq(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	u8 freq_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		{0x71, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		{0x70, 0x07}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	freq_commands[0][1] |= val >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	jlj_write2(gspca_dev, freq_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	jlj_write2(gspca_dev, freq_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void setcamquality(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	u8 quality_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		{0x71, 0x1E},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		{0x70, 0x06}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	u8 camquality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	/* adapt camera quality from jpeg quality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		/ (QUALITY_MAX - QUALITY_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	quality_commands[0][1] += camquality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	jlj_write2(gspca_dev, quality_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	jlj_write2(gspca_dev, quality_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static void setautogain(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	u8 autogain_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		{0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		{0xcf, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	autogain_commands[1][1] = val << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	jlj_write2(gspca_dev, autogain_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	jlj_write2(gspca_dev, autogain_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void setred(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	u8 setred_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		{0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		{0xe6, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	setred_commands[1][1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	jlj_write2(gspca_dev, setred_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	jlj_write2(gspca_dev, setred_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void setgreen(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	u8 setgreen_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		{0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		{0xe7, 0x00}
^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) 	setgreen_commands[1][1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	jlj_write2(gspca_dev, setgreen_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	jlj_write2(gspca_dev, setgreen_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static void setblue(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	u8 setblue_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		{0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		{0xe9, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	setblue_commands[1][1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	jlj_write2(gspca_dev, setblue_commands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	jlj_write2(gspca_dev, setblue_commands[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static int jlj_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	int start_commands_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	u8 response = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	struct jlj_command start_commands[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		{{0x71, 0x81}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		{{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		{{0x95, 0x70}, 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		{{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		{{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		{{0x95, 0x70}, 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		{{0x71, 0x00}, 0, 0},   /* start streaming ??*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		{{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		{{0x95, 0x70}, 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #define SPORTSCAM_DV15_CMD_SIZE 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		{{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		{{0xde, 0x24}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		{{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		{{0xdd, 0xf0}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		{{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		{{0xe3, 0x2c}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		{{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		{{0xe4, 0x00}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		{{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		{{0xe5, 0x00}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		{{0x94, 0x02}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		{{0xe6, 0x2c}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		{{0x94, 0x03}, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		{{0xaa, 0x00}, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	sd->blocks_left = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	/* Under Windows, USB spy shows that only the 9 first start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	 * commands are used for SPORTSCAM_DV15 webcam
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	if (sd->type == SPORTSCAM_DV15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		start_commands_size = SPORTSCAM_DV15_CMD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		start_commands_size = ARRAY_SIZE(start_commands);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	for (i = 0; i < start_commands_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		jlj_write2(gspca_dev, start_commands[i].instruction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		if (start_commands[i].delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			msleep(start_commands[i].delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		if (start_commands[i].ack_wanted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 			jlj_read1(gspca_dev, &response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	msleep(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		gspca_err(gspca_dev, "Start streaming command failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void sd_pkt_scan(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			u8 *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	int packet_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	u32 header_marker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	gspca_dbg(gspca_dev, D_STREAM, "Got %d bytes out of %d for Block 0\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		  len, JEILINJ_MAX_TRANSFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	if (len != JEILINJ_MAX_TRANSFER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		gspca_dbg(gspca_dev, D_PACK, "bad length\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	/* check if it's start of frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	header_marker = ((u32 *)data)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (header_marker == FRAME_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		sd->blocks_left = data[0x0a] - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		gspca_dbg(gspca_dev, D_STREAM, "blocks_left = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 			  sd->blocks_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		/* Start a new frame, and add the JPEG header, first thing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		gspca_frame_add(gspca_dev, FIRST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 				sd->jpeg_hdr, JPEG_HDR_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		/* Toss line 0 of data block 0, keep the rest. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		gspca_frame_add(gspca_dev, INTER_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 				data + FRAME_HEADER_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 				JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	} else if (sd->blocks_left > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		gspca_dbg(gspca_dev, D_STREAM, "%d blocks remaining for frame\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 			  sd->blocks_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		sd->blocks_left -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		if (sd->blocks_left == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 			packet_type = LAST_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			packet_type = INTER_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		gspca_frame_add(gspca_dev, packet_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 				data, JEILINJ_MAX_TRANSFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) discard:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	/* Discard data until a new frame starts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	gspca_dev->last_packet_type = DISCARD_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* This function is called at probe time just before sd_init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int sd_config(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	struct cam *cam = &gspca_dev->cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	struct sd *dev  = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	dev->type = id->driver_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	dev->quality = QUALITY_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	cam->cam_mode = jlj_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	cam->nmodes = ARRAY_SIZE(jlj_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	cam->bulk = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	cam->bulk_nurbs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	cam->bulk_size = JEILINJ_MAX_TRANSFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static void sd_stopN(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	static u8 stop_commands[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		{0x71, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		{0x70, 0x09},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		{0x71, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		{0x70, 0x05}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		/* get the image remaining blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		usb_bulk_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 				gspca_dev->urb[0]->pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 				gspca_dev->urb[0]->transfer_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 				JEILINJ_MAX_TRANSFER, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 				JEILINJ_DATA_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		/* search for 0xff 0xd9  (EOF for JPEG) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		buf = gspca_dev->urb[0]->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 			((buf[i] != 0xff) || (buf[i+1] != 0xd9)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 			i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		if (i != (JEILINJ_MAX_TRANSFER - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			/* last remaining block found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			break;
^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) 	for (i = 0; i < ARRAY_SIZE(stop_commands); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		jlj_write2(gspca_dev, stop_commands[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* this function is called at probe and resume time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static int sd_init(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Set up for getting frames. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static int sd_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	struct sd *dev = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	/* create the JPEG header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	jpeg_define(dev->jpeg_hdr, gspca_dev->pixfmt.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			gspca_dev->pixfmt.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			0x21);          /* JPEG 422 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	jpeg_set_qual(dev->jpeg_hdr, dev->quality);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	gspca_dbg(gspca_dev, D_STREAM, "Start streaming at %dx%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		  gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	jlj_start(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* Table of supported USB devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static const struct usb_device_id device_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	{USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	{USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) MODULE_DEVICE_TABLE(usb, device_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	struct gspca_dev *gspca_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	gspca_dev->usb_err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	if (!gspca_dev->streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	case V4L2_CID_POWER_LINE_FREQUENCY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		setfreq(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	case V4L2_CID_RED_BALANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		setred(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	case V4L2_CID_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		setgreen(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	case V4L2_CID_BLUE_BALANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		setblue(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		setautogain(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		setcamquality(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static const struct v4l2_ctrl_ops sd_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	.s_ctrl = sd_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int sd_init_controls(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	static const struct v4l2_ctrl_config custom_autogain = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		.ops = &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		.id = V4L2_CID_AUTOGAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		.type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		.name = "Automatic Gain (and Exposure)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		.max = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		.step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		.def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	gspca_dev->vdev.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	v4l2_ctrl_handler_init(hdl, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 			V4L2_CID_POWER_LINE_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			V4L2_CID_POWER_LINE_FREQUENCY_60HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 			V4L2_CID_RED_BALANCE, 0, 3, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 			V4L2_CID_GAIN, 0, 3, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 			V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			V4L2_CID_JPEG_COMPRESSION_QUALITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 			QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		pr_err("Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static int sd_set_jcomp(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 			const struct v4l2_jpegcompression *jcomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static int sd_get_jcomp(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			struct v4l2_jpegcompression *jcomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	memset(jcomp, 0, sizeof *jcomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 			| V4L2_JPEG_MARKER_DQT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	return 0;
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static const struct sd_desc sd_desc_sakar_57379 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	.name   = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	.config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	.init   = sd_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	.start  = sd_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	.stopN  = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	.pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static const struct sd_desc sd_desc_sportscam_dv15 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	.name   = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	.config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	.init   = sd_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	.init_controls = sd_init_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	.start  = sd_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	.stopN  = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	.pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	.get_jcomp = sd_get_jcomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	.set_jcomp = sd_set_jcomp,
^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) static const struct sd_desc *sd_desc[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	&sd_desc_sakar_57379,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	&sd_desc_sportscam_dv15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* -- device connect -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int sd_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	return gspca_dev_probe(intf, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 			sd_desc[id->driver_info],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 			sizeof(struct sd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 			THIS_MODULE);
^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) static struct usb_driver sd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	.name       = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	.id_table   = device_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	.probe      = sd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	.disconnect = gspca_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	.suspend = gspca_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	.resume  = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	.reset_resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) module_usb_driver(sd_driver);