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)  * Syntek DV4000 (STK014) subdriver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #define MODULE_NAME "stk014"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "gspca.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "jpeg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define QUALITY 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /* specific webcam descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) struct sd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	struct gspca_dev gspca_dev;	/* !! must be the first item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	u8 jpeg_hdr[JPEG_HDR_SZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static const struct v4l2_pix_format vga_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		.bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		.sizeimage = 320 * 240 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		.colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		.priv = 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		.bytesperline = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		.sizeimage = 640 * 480 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		.colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		.priv = 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /* -- read a register -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static u8 reg_r(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 			__u16 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct usb_device *dev = gspca_dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 			0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 			0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 			index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 			gspca_dev->usb_buf, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 			500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		pr_err("reg_r err %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		gspca_dev->usb_err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	return gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) /* -- write a register -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) static void reg_w(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			__u16 index, __u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct usb_device *dev = gspca_dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 			value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 			0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 			500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		pr_err("reg_w err %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		gspca_dev->usb_err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) /* -- get a bulk value (4 bytes) -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static void rcv_val(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			int ads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	struct usb_device *dev = gspca_dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	int alen, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	reg_w(gspca_dev, 0x636, ads & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	reg_w(gspca_dev, 0x637, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	reg_w(gspca_dev, 0x638, 4);	/* len & 0xff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	reg_w(gspca_dev, 0x639, 0);	/* len >> 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	reg_w(gspca_dev, 0x63a, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	reg_w(gspca_dev, 0x63b, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	reg_w(gspca_dev, 0x630, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	ret = usb_bulk_msg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			usb_rcvbulkpipe(dev, 0x05),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			gspca_dev->usb_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			4,		/* length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			&alen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			500);		/* timeout in milliseconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		pr_err("rcv_val err %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		gspca_dev->usb_err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* -- send a bulk value -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void snd_val(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			int ads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	struct usb_device *dev = gspca_dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	int alen, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	__u8 seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	if (ads == 0x003f08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		reg_r(gspca_dev, 0x0704);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		seq = reg_r(gspca_dev, 0x0705);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		reg_r(gspca_dev, 0x0650);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		reg_w(gspca_dev, 0x654, seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	reg_w(gspca_dev, 0x656, ads & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	reg_w(gspca_dev, 0x657, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	reg_w(gspca_dev, 0x658, 0x04);	/* size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	reg_w(gspca_dev, 0x659, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	reg_w(gspca_dev, 0x65a, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	reg_w(gspca_dev, 0x65b, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	reg_w(gspca_dev, 0x650, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	gspca_dev->usb_buf[0] = val >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	gspca_dev->usb_buf[1] = val >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	gspca_dev->usb_buf[2] = val >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	gspca_dev->usb_buf[3] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	ret = usb_bulk_msg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			usb_sndbulkpipe(dev, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			gspca_dev->usb_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			&alen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 			500);	/* timeout in milliseconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		pr_err("snd_val err %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		gspca_dev->usb_err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		if (ads == 0x003f08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			seq += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			seq &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			reg_w(gspca_dev, 0x705, seq);
^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) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* set a camera parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static void set_par(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		   int parval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	snd_val(gspca_dev, 0x003f08, parval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	int parval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	parval = 0x06000000		/* whiteness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		+ (val << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	set_par(gspca_dev, parval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	int parval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	parval = 0x07000000		/* contrast */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		+ (val << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	set_par(gspca_dev, parval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void setcolors(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	int parval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	parval = 0x08000000		/* saturation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		+ (val << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	set_par(gspca_dev, parval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	set_par(gspca_dev, val == 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			? 0x33640000		/* 50 Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			: 0x33780000);		/* 60 Hz */
^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) /* this function is called at probe time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int sd_config(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	gspca_dev->cam.cam_mode = vga_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* this function is called at probe and resume time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int sd_init(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	u8 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	/* check if the device responds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	ret = reg_r(gspca_dev, 0x0740);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	if (gspca_dev->usb_err >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		if (ret != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			pr_err("init reg: 0x%02x\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			gspca_dev->usb_err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* -- start the camera -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int sd_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	int ret, value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	/* create the JPEG header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			gspca_dev->pixfmt.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 			0x22);		/* JPEG 411 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	jpeg_set_qual(sd->jpeg_hdr, QUALITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	/* work on alternate 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	set_par(gspca_dev, 0x10000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	set_par(gspca_dev, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	set_par(gspca_dev, 0x8002e001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	set_par(gspca_dev, 0x14000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	if (gspca_dev->pixfmt.width > 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		value = 0x8002e001;		/* 640x480 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		value = 0x4001f000;		/* 320x240 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	set_par(gspca_dev, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	ret = usb_set_interface(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 					gspca_dev->iface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 					gspca_dev->alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		pr_err("set intf %d %d failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		       gspca_dev->iface, gspca_dev->alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		gspca_dev->usb_err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	reg_r(gspca_dev, 0x0630);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	rcv_val(gspca_dev, 0x000020);	/* << (value ff ff ff ff) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	reg_r(gspca_dev, 0x0650);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	snd_val(gspca_dev, 0x000020, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	reg_w(gspca_dev, 0x0620, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	reg_w(gspca_dev, 0x0630, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	reg_w(gspca_dev, 0x0640, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	reg_w(gspca_dev, 0x0650, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	reg_w(gspca_dev, 0x0660, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	set_par(gspca_dev, 0x09800000);		/* Red ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	set_par(gspca_dev, 0x0a800000);		/* Green ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	set_par(gspca_dev, 0x0b800000);		/* Blue ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	set_par(gspca_dev, 0x0d030000);		/* Gamma ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	/* start the video flow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	set_par(gspca_dev, 0x01000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	set_par(gspca_dev, 0x01000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (gspca_dev->usb_err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		gspca_dbg(gspca_dev, D_STREAM, "camera started alt: 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			  gspca_dev->alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static void sd_stopN(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	struct usb_device *dev = gspca_dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	set_par(gspca_dev, 0x02000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	set_par(gspca_dev, 0x02000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	usb_set_interface(dev, gspca_dev->iface, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	reg_r(gspca_dev, 0x0630);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	rcv_val(gspca_dev, 0x000020);	/* << (value ff ff ff ff) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	reg_r(gspca_dev, 0x0650);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	snd_val(gspca_dev, 0x000020, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	reg_w(gspca_dev, 0x0620, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	reg_w(gspca_dev, 0x0630, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	reg_w(gspca_dev, 0x0640, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	reg_w(gspca_dev, 0x0650, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	reg_w(gspca_dev, 0x0660, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	gspca_dbg(gspca_dev, D_STREAM, "camera stopped\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static void sd_pkt_scan(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			u8 *data,			/* isoc packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			int len)			/* iso packet length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	static unsigned char ffd9[] = {0xff, 0xd9};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	/* a frame starts with:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	 *	- 0xff 0xfe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	 *	- 0x08 0x00	- length (little endian ?!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	 *	- 4 bytes = size of whole frame (BE - including header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	 *	- 0x00 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	 *	- 0xff 0xd8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	 *	- ..	JPEG image with escape sequences (ff 00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	 *		(without ending - ff d9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	if (data[0] == 0xff && data[1] == 0xfe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		gspca_frame_add(gspca_dev, LAST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 				ffd9, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		/* put the JPEG 411 header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		gspca_frame_add(gspca_dev, FIRST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 			sd->jpeg_hdr, JPEG_HDR_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		/* beginning of the frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) #define STKHDRSZ 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		data += STKHDRSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		len -= STKHDRSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	struct gspca_dev *gspca_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	gspca_dev->usb_err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	if (!gspca_dev->streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		setbrightness(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		setcontrast(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		setcolors(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	case V4L2_CID_POWER_LINE_FREQUENCY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		setlightfreq(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static const struct v4l2_ctrl_ops sd_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	.s_ctrl = sd_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static int sd_init_controls(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	gspca_dev->vdev.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	v4l2_ctrl_handler_init(hdl, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 			V4L2_CID_CONTRAST, 0, 255, 1, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 			V4L2_CID_SATURATION, 0, 255, 1, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 			V4L2_CID_POWER_LINE_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 			V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		pr_err("Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static const struct sd_desc sd_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	.name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	.config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	.init = sd_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	.init_controls = sd_init_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	.start = sd_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	.stopN = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	.pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* -- module initialisation -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static const struct usb_device_id device_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	{USB_DEVICE(0x05e1, 0x0893)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) MODULE_DEVICE_TABLE(usb, device_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* -- device connect -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static int sd_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 			const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 				THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static struct usb_driver sd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	.name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	.id_table = device_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	.probe = sd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	.disconnect = gspca_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	.suspend = gspca_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	.resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	.reset_resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) module_usb_driver(sd_driver);