^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) * Mars MR97310A library
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * and for the routines for detecting and classifying these various cameras,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Support for the control settings for the CIF cameras is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Thomas Kaiser <thomas@kaiser-linux.li>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Support for the control settings for the VGA cameras is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Several previously unsupported cameras are owned and have been tested by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Hans de Goede <hdegoede@redhat.com> and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Thomas Kaiser <thomas@kaiser-linux.li> and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Theodore Kilgore <kilgota@auburn.edu> and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Edmond Rodriguez <erodrig_97@yahoo.com> and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Aurelien Jacobs <aurel@gnuage.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * The MR97311A support in gspca/mars.c has been helpful in understanding some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * of the registers in these cameras.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MODULE_NAME "mr97310a"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "gspca.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CAM_TYPE_CIF 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CAM_TYPE_VGA 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MR97310A_BRIGHTNESS_DEFAULT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MR97310A_EXPOSURE_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MR97310A_EXPOSURE_MAX 4095
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MR97310A_EXPOSURE_DEFAULT 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MR97310A_GAIN_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MR97310A_GAIN_MAX 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MR97310A_GAIN_DEFAULT 25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MR97310A_CONTRAST_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MR97310A_CONTRAST_MAX 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MR97310A_CONTRAST_DEFAULT 23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MR97310A_CS_GAIN_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MR97310A_CS_GAIN_MAX 0x7ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define MR97310A_CS_GAIN_DEFAULT 0x110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MR97310A_MIN_CLOCKDIV_MIN 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define MR97310A_MIN_CLOCKDIV_MAX 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define MR97310A_MIN_CLOCKDIV_DEFAULT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,Theodore Kilgore <kilgota@auburn.edu>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* global parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int force_sensor_type = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) module_param(force_sensor_type, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* specific webcam descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct sd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct gspca_dev gspca_dev; /* !! must be the first item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct { /* exposure/min_clockdiv control cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct v4l2_ctrl *exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct v4l2_ctrl *min_clockdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u8 sof_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u8 cam_type; /* 0 is CIF and 1 is VGA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u8 sensor_type; /* We use 0 and 1 here, too. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u8 do_lcd_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u8 adj_colors;
^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) struct sensor_w_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u8 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u8 data[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static void sd_stopN(struct gspca_dev *gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static const struct v4l2_pix_format vga_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .bytesperline = 160,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .sizeimage = 160 * 120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .priv = 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .bytesperline = 176,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .sizeimage = 176 * 144,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .priv = 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .sizeimage = 320 * 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .priv = 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .bytesperline = 352,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .sizeimage = 352 * 288,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .priv = 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .bytesperline = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .sizeimage = 640 * 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .priv = 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* the bytes to write are in gspca_dev->usb_buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int mr_write(struct gspca_dev *gspca_dev, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) rc = usb_bulk_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) usb_sndbulkpipe(gspca_dev->dev, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) gspca_dev->usb_buf, len, NULL, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) pr_err("reg write [%02x] error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) gspca_dev->usb_buf[0], rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* the bytes are read into gspca_dev->usb_buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int mr_read(struct gspca_dev *gspca_dev, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) rc = usb_bulk_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) usb_rcvbulkpipe(gspca_dev->dev, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) gspca_dev->usb_buf, len, NULL, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pr_err("reg read [%02x] error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) gspca_dev->usb_buf[0], rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) const u8 *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) gspca_dev->usb_buf[0] = 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) gspca_dev->usb_buf[1] = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) gspca_dev->usb_buf[2] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) memcpy(gspca_dev->usb_buf + 3, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return mr_write(gspca_dev, len + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int sensor_write_regs(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) const struct sensor_w_data *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) data[i].data, data[i].len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return rc;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u8 buf, confirm_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) buf = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (sd->cam_type == CAM_TYPE_CIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) confirm_reg = sd->sensor_type ? 0x13 : 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) confirm_reg = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) buf = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) gspca_dev->usb_buf[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) err_code = mr_write(gspca_dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) err_code = mr_read(gspca_dev, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) gspca_dbg(gspca_dev, D_PROBE, "Register: %02x reads %02x%02x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) gspca_dev->usb_buf[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) gspca_dev->usb_buf[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) gspca_dev->usb_buf[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static int zero_the_pointer(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) __u8 *data = gspca_dev->usb_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u8 status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int tries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) err_code = cam_get_response16(gspca_dev, 0x21, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) data[0] = 0x19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) data[1] = 0x51;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) err_code = mr_write(gspca_dev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) err_code = cam_get_response16(gspca_dev, 0x21, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) data[0] = 0x19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) data[1] = 0xba;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) err_code = mr_write(gspca_dev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) err_code = cam_get_response16(gspca_dev, 0x21, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) data[0] = 0x19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) data[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) err_code = mr_write(gspca_dev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) err_code = cam_get_response16(gspca_dev, 0x21, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) data[0] = 0x19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) data[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) err_code = mr_write(gspca_dev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) while (status != 0x0a && tries < 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) err_code = cam_get_response16(gspca_dev, 0x21, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) status = data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) tries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (status != 0x0a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) gspca_err(gspca_dev, "status is %02x\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) while (tries < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) data[0] = 0x19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) data[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) err_code = mr_write(gspca_dev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) err_code = cam_get_response16(gspca_dev, 0x21, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) tries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) data[0] = 0x19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) err_code = mr_write(gspca_dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) err_code = mr_read(gspca_dev, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static int stream_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) gspca_dev->usb_buf[0] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) gspca_dev->usb_buf[1] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return mr_write(gspca_dev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static void stream_stop(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) gspca_dev->usb_buf[0] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) gspca_dev->usb_buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (mr_write(gspca_dev, 2) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) gspca_err(gspca_dev, "Stream Stop failed\n");
^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 lcd_stop(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) gspca_dev->usb_buf[0] = 0x19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) gspca_dev->usb_buf[1] = 0x54;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (mr_write(gspca_dev, 2) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) gspca_err(gspca_dev, "LCD Stop failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static int isoc_enable(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) gspca_dev->usb_buf[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) gspca_dev->usb_buf[1] = 0x4d; /* ISOC transferring enable... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return mr_write(gspca_dev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* This function is called at probe time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) static int sd_config(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct cam *cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) cam = &gspca_dev->cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) cam->cam_mode = vga_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) cam->nmodes = ARRAY_SIZE(vga_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) sd->do_lcd_stop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* Several of the supported CIF cameras share the same USB ID but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * require different initializations and different control settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * The same is true of the VGA cameras. Therefore, we are forced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * to start the initialization process in order to determine which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * camera is present. Some of the supported cameras require the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * memory pointer to be set to 0 as the very first item of business
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * or else they will not stream. So we do that immediately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) err_code = zero_the_pointer(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) err_code = stream_start(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* Now, the query for sensor type. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) err_code = cam_get_response16(gspca_dev, 0x07, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) sd->cam_type = CAM_TYPE_CIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) cam->nmodes--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * All but one of the known CIF cameras share the same USB ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * but two different init routines are in use, and the control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * settings are different, too. We need to detect which camera
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * of the two known varieties is connected!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * A list of known CIF cameras follows. They all report either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * 0200 for type 0 or 0300 for type 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * If you have another to report, please do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * Name sd->sensor_type reported by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * Sakar 56379 Spy-shot 0 T. Kilgore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * Innovage 0 T. Kilgore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * Vivitar Mini 0 H. De Goede
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * Vivitar Mini 0 E. Rodriguez
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * Vivitar Mini 1 T. Kilgore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * Elta-Media 8212dc 1 T. Kaiser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * Philips dig. keych. 1 T. Kilgore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * Trust Spyc@m 100 1 A. Jacobs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) switch (gspca_dev->usb_buf[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) sd->sensor_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) sd->sensor_type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) pr_err("Unknown CIF Sensor id : %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) gspca_dev->usb_buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) gspca_dbg(gspca_dev, D_PROBE, "MR97310A CIF camera detected, sensor: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) sd->sensor_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) sd->cam_type = CAM_TYPE_VGA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * Here is a table of the responses to the query for sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * type, from the known MR97310A VGA cameras. Six different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * cameras of which five share the same USB ID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * Name gspca_dev->usb_buf[] sd->sensor_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * sd->do_lcd_stop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * Aiptek Pencam VGA+ 0300 0 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * ION digital 0300 0 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * Argus DC-1620 0450 1 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * Argus QuickClix 0420 1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * Sakar 77379 Digital 0350 0 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * Sakar 1638x CyberPix 0120 0 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * Based upon these results, we assume default settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * and then correct as necessary, as follows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) sd->sensor_type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) sd->do_lcd_stop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) sd->adj_colors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (gspca_dev->usb_buf[0] == 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) sd->sensor_type = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) } else if ((gspca_dev->usb_buf[0] != 0x03) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) (gspca_dev->usb_buf[0] != 0x04)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) gspca_dev->usb_buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) pr_err("Defaults assumed, may not work\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) pr_err("Please report this\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /* Sakar Digital color needs to be adjusted. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if ((gspca_dev->usb_buf[0] == 0x03) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) (gspca_dev->usb_buf[1] == 0x50))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) sd->adj_colors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (gspca_dev->usb_buf[0] == 0x04) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) sd->do_lcd_stop = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) switch (gspca_dev->usb_buf[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case 0x50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) sd->sensor_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) gspca_dbg(gspca_dev, D_PROBE, "sensor_type corrected to 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) case 0x20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* Nothing to do here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) gspca_dev->usb_buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) pr_err("Defaults assumed, may not work\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) pr_err("Please report this\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) gspca_dbg(gspca_dev, D_PROBE, "MR97310A VGA camera detected, sensor: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) sd->sensor_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Stop streaming as we've started it only to probe the sensor type. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) sd_stopN(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (force_sensor_type != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) sd->sensor_type = !!force_sensor_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) gspca_dbg(gspca_dev, D_PROBE, "Forcing sensor type to: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) sd->sensor_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* this function is called at probe and resume time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static int sd_init(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int start_cif_cam(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) __u8 *data = gspca_dev->usb_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static const __u8 startup_string[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 0x0d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 0x00, /* Hsize/8 for 352 or 320 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 0x00, /* Vsize/4 for 288 or 240 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 0x13, /* or 0xbb, depends on sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 0x00, /* Hstart, depends on res. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 0x00, /* reserved ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 0x00, /* Vstart, depends on res. and sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 0x50, /* 0x54 to get 176 or 160 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* Note: Some of the above descriptions guessed from MR97113A driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) memcpy(data, startup_string, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (sd->sensor_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) data[5] = 0xbb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) switch (gspca_dev->pixfmt.width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case 160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case 320:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) data[3] = 0x28; /* reg 2, H size/8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) data[4] = 0x3c; /* reg 3, V size/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) data[6] = 0x14; /* reg 5, H start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) case 176:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) case 352:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) data[3] = 0x2c; /* reg 2, H size/8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) data[4] = 0x48; /* reg 3, V size/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) data[6] = 0x06; /* reg 5, H start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) data[8] = 0x06 - sd->sensor_type; /* reg 7, V start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) err_code = mr_write(gspca_dev, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (!sd->sensor_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static const struct sensor_w_data cif_sensor0_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 0x0f, 0x14, 0x0f, 0x10}, 8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {0x12, 0x00, {0x07}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {0x1f, 0x00, {0x06}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {0x27, 0x00, {0x04}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {0x29, 0x00, {0x0c}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {0x40, 0x00, {0x40, 0x00, 0x04}, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {0x50, 0x00, {0x60}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {0x60, 0x00, {0x06}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {0x72, 0x00, {0x1e, 0x56}, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 0x31, 0x80, 0x00}, 9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {0x11, 0x00, {0x01}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {0, 0, {0}, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ARRAY_SIZE(cif_sensor0_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) } else { /* sd->sensor_type = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static const struct sensor_w_data cif_sensor1_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* Reg 3,4, 7,8 get set by the controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {0x02, 0x00, {0x10}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {0x06, 0x01, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {0x09, 0x02, {0x0e}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {0x0a, 0x02, {0x05}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {0x0b, 0x02, {0x05}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {0x0c, 0x02, {0x0f}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {0x0d, 0x02, {0x07}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {0x0e, 0x02, {0x0c}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {0x0f, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {0x10, 0x00, {0x06}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {0x11, 0x00, {0x07}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {0x12, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {0x13, 0x00, {0x01}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {0, 0, {0}, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /* Without this command the cam won't work with USB-UHCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) gspca_dev->usb_buf[0] = 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) gspca_dev->usb_buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) err_code = mr_write(gspca_dev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) ARRAY_SIZE(cif_sensor1_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static int start_vga_cam(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) __u8 *data = gspca_dev->usb_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static const __u8 startup_string[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 0x00, 0x50, 0xc0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* What some of these mean is explained in start_cif_cam(), above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) memcpy(data, startup_string, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (!sd->sensor_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) data[5] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) data[10] = 0x91;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (sd->sensor_type == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) data[5] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) data[10] = 0x18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) switch (gspca_dev->pixfmt.width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case 160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) data[9] |= 0x0c; /* reg 8, 4:1 scale down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) case 320:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) data[9] |= 0x04; /* reg 8, 2:1 scale down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) case 640:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) data[3] = 0x50; /* reg 2, H size/8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) data[4] = 0x78; /* reg 3, V size/4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) data[6] = 0x04; /* reg 5, H start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) data[8] = 0x03; /* reg 7, V start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (sd->sensor_type == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) data[6] = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) data[8] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (sd->do_lcd_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) data[8] = 0x04; /* Bayer tile shifted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) case 176:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) data[9] |= 0x04; /* reg 8, 2:1 scale down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) case 352:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) data[3] = 0x2c; /* reg 2, H size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) data[4] = 0x48; /* reg 3, V size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) data[6] = 0x94; /* reg 5, H start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) data[8] = 0x63; /* reg 7, V start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (sd->do_lcd_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) data[8] = 0x64; /* Bayer tile shifted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) err_code = mr_write(gspca_dev, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (!sd->sensor_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static const struct sensor_w_data vga_sensor0_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {0, 0, {0}, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ARRAY_SIZE(vga_sensor0_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) } else if (sd->sensor_type == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static const struct sensor_w_data color_adj[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* adjusted blue, green, red gain correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) too much blue from the Sakar Digital */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 0x05, 0x01, 0x04}, 8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static const struct sensor_w_data color_no_adj[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* default blue, green, red gain settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 0x07, 0x00, 0x01}, 8}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static const struct sensor_w_data vga_sensor1_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {0x11, 0x04, {0x01}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /* These settings may be better for some cameras */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 0x00, 0x0a}, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) {0x11, 0x04, {0x01}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {0x11, 0x04, {0x01}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {0, 0, {0}, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (sd->adj_colors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) err_code = sensor_write_regs(gspca_dev, color_adj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) ARRAY_SIZE(color_adj));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) err_code = sensor_write_regs(gspca_dev, color_no_adj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ARRAY_SIZE(color_no_adj));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) ARRAY_SIZE(vga_sensor1_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) } else { /* sensor type == 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static const struct sensor_w_data vga_sensor2_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {0x01, 0x00, {0x48}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {0x02, 0x00, {0x22}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /* Reg 3 msb and 4 is lsb of the exposure setting*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {0x05, 0x00, {0x10}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {0x06, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {0x07, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {0x08, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {0x09, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) /* The following are used in the gain control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * which is BTW completely borked in the OEM driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * The values for each color go from 0 to 0x7ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) *{0x0a, 0x00, {0x01}, 1}, green1 gain msb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) *{0x0c, 0x00, {0x01}, 1}, red gain msb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) *{0x0d, 0x00, {0x10}, 1}, red gain lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) *{0x0e, 0x00, {0x01}, 1}, blue gain msb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) *{0x0f, 0x00, {0x10}, 1}, blue gain lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) *{0x10, 0x00, {0x01}, 1}, green2 gain msb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {0x12, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) {0x14, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {0x15, 0x00, {0x06}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {0x16, 0x00, {0x01}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {0x18, 0x00, {0x02}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {0x19, 0x00, {0x82}, 1}, /* don't mess with */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {0x1a, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {0x1b, 0x00, {0x20}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* {0x1c, 0x00, {0x17}, 1}, contrast control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) {0x1f, 0x00, {0x0c}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {0x20, 0x00, {0x00}, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {0, 0, {0}, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) ARRAY_SIZE(vga_sensor2_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static int sd_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) sd->sof_read = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /* Some of the VGA cameras require the memory pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * to be set to 0 again. We have been forced to start the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * stream in sd_config() to detect the hardware, and closed it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * Thus, we need here to do a completely fresh and clean start. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) err_code = zero_the_pointer(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) err_code = stream_start(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (sd->cam_type == CAM_TYPE_CIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) err_code = start_cif_cam(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) err_code = start_vga_cam(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (err_code < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return isoc_enable(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static void sd_stopN(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) stream_stop(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /* Not all the cams need this, but even if not, probably a good idea */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) zero_the_pointer(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (sd->do_lcd_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) lcd_stop(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static const u8 quick_clix_table[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (sd->cam_type == CAM_TYPE_VGA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) sign_reg += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) value_reg += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (val > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) sensor_write1(gspca_dev, sign_reg, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) sensor_write1(gspca_dev, sign_reg, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) val = 257 - val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /* Use lookup table for funky Argus QuickClix brightness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (sd->do_lcd_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) val = quick_clix_table[val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) sensor_write1(gspca_dev, value_reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) int exposure = MR97310A_EXPOSURE_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) /* This cam does not like exposure settings < 300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) so scale 0 - 4095 to 300 - 4095 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) exposure = (expo * 9267) / 10000 + 300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) sensor_write1(gspca_dev, 3, exposure >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) sensor_write1(gspca_dev, 4, exposure & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) } else if (sd->sensor_type == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) exposure = expo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) exposure >>= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) sensor_write1(gspca_dev, 3, exposure >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) sensor_write1(gspca_dev, 4, exposure & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* We have both a clock divider and an exposure register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) We first calculate the clock divider, as that determines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) the maximum exposure and then we calculate the exposure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) register setting (which goes from 0 - 511).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) Note our 0 - 4095 exposure is mapped to 0 - 511
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) milliseconds exposure time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) u8 clockdiv = (60 * expo + 7999) / 8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* Limit framerate to not exceed usb bandwidth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (clockdiv < min_clockdiv && gspca_dev->pixfmt.width >= 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) clockdiv = min_clockdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) else if (clockdiv < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) clockdiv = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) clockdiv = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /* Frame exposure time in ms = 1000 * clockdiv / 60 ->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) exposure = (60 * 511 * expo) / (8000 * clockdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (exposure > 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) exposure = 511;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) /* exposure register value is reversed! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) exposure = 511 - exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) buf[0] = exposure & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) buf[1] = exposure >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) sensor_write1(gspca_dev, 0x02, clockdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static void setgain(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) u8 gainreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) sensor_write1(gspca_dev, 0x0e, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) sensor_write1(gspca_dev, gainreg, val >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) sensor_write1(gspca_dev, gainreg + 1, val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) sensor_write1(gspca_dev, 0x10, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) sensor_write1(gspca_dev, 0x1c, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct gspca_dev *gspca_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) gspca_dev->usb_err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (!gspca_dev->streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) setbrightness(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) setcontrast(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) case V4L2_CID_EXPOSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) setexposure(gspca_dev, sd->exposure->val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) sd->min_clockdiv ? sd->min_clockdiv->val : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) case V4L2_CID_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) setgain(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static const struct v4l2_ctrl_ops sd_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) .s_ctrl = sd_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static int sd_init_controls(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) static const struct v4l2_ctrl_config clockdiv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .ops = &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .id = MR97310A_CID_CLOCKDIV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .name = "Minimum Clock Divider",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .min = MR97310A_MIN_CLOCKDIV_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .max = MR97310A_MIN_CLOCKDIV_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .def = MR97310A_MIN_CLOCKDIV_DEFAULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) bool has_brightness = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) bool has_argus_brightness = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) bool has_contrast = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) bool has_gain = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) bool has_cs_gain = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) bool has_exposure = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) bool has_clockdiv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) gspca_dev->vdev.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) v4l2_ctrl_handler_init(hdl, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* Setup controls depending on camera type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (sd->cam_type == CAM_TYPE_CIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /* No brightness for sensor_type 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (sd->sensor_type == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) has_exposure = has_gain = has_clockdiv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) has_exposure = has_gain = has_brightness = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /* All controls need to be disabled if VGA sensor_type is 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (sd->sensor_type == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ; /* no controls! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) else if (sd->sensor_type == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) has_exposure = has_cs_gain = has_contrast = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) else if (sd->do_lcd_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) has_exposure = has_gain = has_argus_brightness =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) has_clockdiv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) has_exposure = has_gain = has_brightness =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) has_clockdiv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /* Separate brightness control description for Argus QuickClix as it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * different limits from the other mr97310a cameras, and separate gain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * control for Sakar CyberPix camera. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * This control is disabled for CIF type 1 and VGA type 0 cameras.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * It does not quite act linearly for the Argus QuickClix camera,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * but it does control brightness. The values are 0 - 15 only, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * the table above makes them act consecutively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (has_brightness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) V4L2_CID_BRIGHTNESS, -254, 255, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) MR97310A_BRIGHTNESS_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) else if (has_argus_brightness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) V4L2_CID_BRIGHTNESS, 0, 15, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) MR97310A_BRIGHTNESS_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (has_contrast)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (has_gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) 1, MR97310A_GAIN_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) else if (has_cs_gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) 1, MR97310A_CS_GAIN_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (has_exposure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (has_clockdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) pr_err("Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (has_exposure && has_clockdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) v4l2_ctrl_cluster(2, &sd->exposure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /* Include pac common sof detection functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) #include "pac_common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) static void sd_pkt_scan(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) u8 *data, /* isoc packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) int len) /* iso packet length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) unsigned char *sof;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (sof) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /* finish decoding current frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) n = sof - data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (n > sizeof pac_sof_marker)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) n -= sizeof pac_sof_marker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) gspca_frame_add(gspca_dev, LAST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) data, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /* Start next frame. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) gspca_frame_add(gspca_dev, FIRST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) pac_sof_marker, sizeof pac_sof_marker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) len -= sof - data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) data = sof;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) static const struct sd_desc sd_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) .config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) .init = sd_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) .init_controls = sd_init_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) .start = sd_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) .stopN = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) .pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) /* -- module initialisation -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) static const struct usb_device_id device_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) MODULE_DEVICE_TABLE(usb, device_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /* -- device connect -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static int sd_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static struct usb_driver sd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) .id_table = device_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) .probe = sd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) .disconnect = gspca_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) .suspend = gspca_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) .resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) .reset_resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) module_usb_driver(sd_driver);