^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);