^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) * Sunplus spca561 subdriver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define MODULE_NAME "spca561"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "gspca.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define EXPOSURE_MAX (2047 + 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* specific webcam descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct sd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct gspca_dev gspca_dev; /* !! must be the first item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct { /* hue/contrast control cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct v4l2_ctrl *contrast;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct v4l2_ctrl *hue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct v4l2_ctrl *autogain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define EXPO12A_DEF 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) __u8 expo12a; /* expo/gain? for rev 12a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) __u8 chip_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define Rev012A 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define Rev072A 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) signed char ag_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define AG_CNT_START 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const struct v4l2_pix_format sif_012a_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .bytesperline = 160,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .sizeimage = 160 * 120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .priv = 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .bytesperline = 176,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .sizeimage = 176 * 144,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .priv = 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .sizeimage = 320 * 240 * 4 / 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .priv = 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .bytesperline = 352,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .sizeimage = 352 * 288 * 4 / 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .priv = 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const struct v4l2_pix_format sif_072a_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .bytesperline = 160,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .sizeimage = 160 * 120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .priv = 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .bytesperline = 176,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .sizeimage = 176 * 144,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .priv = 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .sizeimage = 320 * 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .priv = 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .bytesperline = 352,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .sizeimage = 352 * 288,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .priv = 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Initialization data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * I'm not very sure how to split initialization from open data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * chunks. For now, we'll consider everything as initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* Frame packet header offsets for the spca561 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define SPCA561_OFFSET_SNAP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define SPCA561_OFFSET_TYPE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define SPCA561_OFFSET_COMPRESS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SPCA561_OFFSET_FRAMSEQ 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define SPCA561_OFFSET_GPIO 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define SPCA561_OFFSET_USBBUFF 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define SPCA561_OFFSET_WIN2GRAVE 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define SPCA561_OFFSET_WIN2RAVE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define SPCA561_OFFSET_WIN2BAVE 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define SPCA561_OFFSET_WIN2GBAVE 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define SPCA561_OFFSET_WIN1GRAVE 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define SPCA561_OFFSET_WIN1RAVE 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define SPCA561_OFFSET_WIN1BAVE 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define SPCA561_OFFSET_WIN1GBAVE 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define SPCA561_OFFSET_FREQ 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define SPCA561_OFFSET_VSYNC 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define SPCA561_INDEX_I2C_BASE 0x8800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define SPCA561_SNAPBIT 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define SPCA561_SNAPCTRL 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static const u16 rev72a_reset[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {0x0000, 0x8114}, /* Software GPIO output data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {0x0001, 0x8114}, /* Software GPIO output data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {0x0000, 0x8112}, /* Some kind of reset */
^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) static const __u16 rev72a_init_data1[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {0x0003, 0x8701}, /* PCLK clock delay adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {0x0001, 0x8703}, /* HSYNC from cmos inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {0x0011, 0x8118}, /* Enable and conf sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {0x0001, 0x8118}, /* Conf sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {0x0092, 0x8804}, /* I know nothing about these */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {0x0010, 0x8802}, /* 0x88xx registers, so I won't */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static const u16 rev72a_init_sensor1[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {0x0001, 0x000d},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {0x0002, 0x0018},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {0x0004, 0x0165},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {0x0005, 0x0021},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {0x0007, 0x00aa},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {0x0020, 0x1504},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {0x0039, 0x0002},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {0x0035, 0x0010},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {0x0009, 0x1049},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {0x0028, 0x000b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {0x003b, 0x000f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {0x003c, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static const __u16 rev72a_init_data2[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {0x0018, 0x8601}, /* Pixel/line selection for color separation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {0x0000, 0x8602}, /* Optical black level for user setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {0x0060, 0x8604}, /* Optical black horizontal offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {0x0002, 0x8605}, /* Optical black vertical offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {0x0000, 0x8603}, /* Non-automatic optical black level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {0x0000, 0x865f}, /* Vertical valid pixels window (x2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {0x00b0, 0x865d}, /* Horizontal valid pixels window (x2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {0x0090, 0x865e}, /* Vertical valid lines window (x2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {0x00e0, 0x8406}, /* Memory buffer threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {0x0000, 0x8660}, /* Compensation memory stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {0x0002, 0x8201}, /* Output address for r/w serial EEPROM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {0x0001, 0x8200}, /* OprMode to be executed by hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* from ms-win */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {0x0000, 0x8611}, /* R offset for white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {0x00fd, 0x8612}, /* Gr offset for white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {0x0003, 0x8613}, /* B offset for white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {0x0000, 0x8614}, /* Gb offset for white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* from ms-win */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {0x0035, 0x8651}, /* R gain for white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {0x0040, 0x8652}, /* Gr gain for white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {0x005f, 0x8653}, /* B gain for white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {0x0040, 0x8654}, /* Gb gain for white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {0x0002, 0x8502}, /* Maximum average bit rate stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {0x0011, 0x8802},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {0x0087, 0x8700}, /* Set master clock (96Mhz????) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {0x0081, 0x8702}, /* Master clock output enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {0x0000, 0x8500}, /* Set image type (352x288 no compression) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* Originally was 0x0010 (352x288 compression) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {0x0003, 0x865c}, /* Vertical offset for valid lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static const u16 rev72a_init_sensor2[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {0x0003, 0x0121},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {0x0004, 0x0165},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {0x0005, 0x002f}, /* blanking control column */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {0x0006, 0x0000}, /* blanking mode row*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {0x000a, 0x0002},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {0x0009, 0x1061}, /* setexposure times && pixel clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * 0001 0 | 000 0110 0001 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {0x0035, 0x0014},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /******************** QC Express etch2 stuff ********************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static const __u16 Pb100_1map8300[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* reg, value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {0x8320, 0x3304},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {0x8303, 0x0125}, /* image area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {0x8304, 0x0169},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {0x8328, 0x000b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {0x833c, 0x0001}, /*fixme: win:07*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {0x832f, 0x1904}, /*fixme: was 0419*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {0x8307, 0x00aa},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {0x8301, 0x0003},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {0x8302, 0x000e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static const __u16 Pb100_2map8300[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* reg, value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {0x8339, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {0x8307, 0x00aa},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static const __u16 spca561_161rev12A_data1[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {0x29, 0x8118}, /* Control register (various enable bits) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {0x08, 0x8114}, /* GPIO: Led off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {0x0e, 0x8112}, /* 0x0e stream off 0x3e stream on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {0x00, 0x8102}, /* white balance - new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {0x92, 0x8804},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {0x04, 0x8802}, /* windows uses 08 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static const __u16 spca561_161rev12A_data2[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {0x21, 0x8118},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {0x10, 0x8500},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {0x07, 0x8601},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {0x07, 0x8602},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {0x04, 0x8501},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {0x07, 0x8201}, /* windows uses 02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {0x08, 0x8200},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {0x01, 0x8200},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {0x90, 0x8604},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {0x00, 0x8605},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {0xb0, 0x8603},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* sensor gains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {0x07, 0x8601}, /* white balance - new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {0x07, 0x8602}, /* white balance - new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {0x00, 0x8610}, /* *red */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {0x00, 0x8611}, /* 3f *green */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {0x00, 0x8612}, /* green *blue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {0x00, 0x8613}, /* blue *green */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {0x43, 0x8614}, /* green *red - white balance - was 0x35 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {0x40, 0x8615}, /* 40 *green - white balance - was 0x35 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {0x71, 0x8616}, /* 7a *blue - white balance - was 0x35 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {0x40, 0x8617}, /* 40 *green - white balance - was 0x35 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {0x0c, 0x8620}, /* 0c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {0xc8, 0x8631}, /* c8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {0xc8, 0x8634}, /* c8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {0x23, 0x8635}, /* 23 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {0x1f, 0x8636}, /* 1f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {0xdd, 0x8637}, /* dd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {0xe1, 0x8638}, /* e1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {0x1d, 0x8639}, /* 1d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {0x21, 0x863a}, /* 21 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {0xe3, 0x863b}, /* e3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {0xdf, 0x863c}, /* df */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {0xf0, 0x8505},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {0x32, 0x850a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* {0x99, 0x8700}, * - white balance - new (removed) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* HDG we used to do this in stop0, making the init state and the state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) after a start / stop different, so do this here instead. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {0x29, 0x8118},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static void reg_w_val(struct gspca_dev *gspca_dev, __u16 index, __u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct usb_device *dev = gspca_dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 0, /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) value, index, NULL, 0, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) gspca_dbg(gspca_dev, D_USBO, "reg write: 0x%02x:0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) index, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) pr_err("reg write: error %d\n", ret);
^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 write_vector(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) const __u16 data[][2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) while (data[i][1] != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) reg_w_val(gspca_dev, data[i][1], data[i][0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /* read 'len' bytes to gspca_dev->usb_buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static void reg_r(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) __u16 index, __u16 length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) usb_control_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) usb_rcvctrlpipe(gspca_dev->dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 0, /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 0, /* value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) index, gspca_dev->usb_buf, length, 500);
^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) /* write 'len' bytes from gspca_dev->usb_buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static void reg_w_buf(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) __u16 index, __u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) usb_control_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) usb_sndctrlpipe(gspca_dev->dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 0, /* request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 0, /* value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) index, gspca_dev->usb_buf, len, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int retry = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) reg_w_val(gspca_dev, 0x8801, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) reg_w_val(gspca_dev, 0x8805, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) reg_w_val(gspca_dev, 0x8800, value >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) reg_r(gspca_dev, 0x8803, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!gspca_dev->usb_buf[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) } while (--retry);
^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 i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int retry = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) __u8 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) reg_w_val(gspca_dev, 0x8804, 0x92);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) reg_w_val(gspca_dev, 0x8801, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) reg_w_val(gspca_dev, 0x8802, mode | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) reg_r(gspca_dev, 0x8803, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!gspca_dev->usb_buf[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) reg_r(gspca_dev, 0x8800, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) value = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) reg_r(gspca_dev, 0x8805, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return ((int) value << 8) | gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) } while (--retry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static void sensor_mapwrite(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) const __u16 (*sensormap)[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) while ((*sensormap)[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) gspca_dev->usb_buf[0] = (*sensormap)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) reg_w_buf(gspca_dev, (*sensormap)[0], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) sensormap++;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static void write_sensor_72a(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) const __u16 (*sensor)[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) while ((*sensor)[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) sensor++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static void init_161rev12A(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) write_vector(gspca_dev, spca561_161rev12A_data1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) sensor_mapwrite(gspca_dev, Pb100_1map8300);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /*fixme: should be in sd_start*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) write_vector(gspca_dev, spca561_161rev12A_data2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) sensor_mapwrite(gspca_dev, Pb100_2map8300);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* this function is called at probe time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int sd_config(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct cam *cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) __u16 vendor, product;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) __u8 data1, data2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* Read frm global register the USB product and vendor IDs, just to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * prove that we can communicate with the device. This works, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * confirms at we are communicating properly and that the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * is a 561. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) reg_r(gspca_dev, 0x8104, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) data1 = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) reg_r(gspca_dev, 0x8105, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) data2 = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) vendor = (data2 << 8) | data1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) reg_r(gspca_dev, 0x8106, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) data1 = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) reg_r(gspca_dev, 0x8107, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) data2 = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) product = (data2 << 8) | data1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (vendor != id->idVendor || product != id->idProduct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) gspca_dbg(gspca_dev, D_PROBE, "Bad vendor / product from device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) cam = &gspca_dev->cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) cam->needs_full_bandwidth = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) sd->chip_revision = id->driver_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (sd->chip_revision == Rev012A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) cam->cam_mode = sif_012a_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) cam->nmodes = ARRAY_SIZE(sif_012a_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) cam->cam_mode = sif_072a_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) cam->nmodes = ARRAY_SIZE(sif_072a_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) sd->expo12a = EXPO12A_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return 0;
^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) /* this function is called at probe and resume time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static int sd_init_12a(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) gspca_dbg(gspca_dev, D_STREAM, "Chip revision: 012a\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) init_161rev12A(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static int sd_init_72a(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) gspca_dbg(gspca_dev, D_STREAM, "Chip revision: 072a\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) write_vector(gspca_dev, rev72a_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) msleep(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) write_vector(gspca_dev, rev72a_init_data1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) write_sensor_72a(gspca_dev, rev72a_init_sensor1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) write_vector(gspca_dev, rev72a_init_data2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) write_sensor_72a(gspca_dev, rev72a_init_sensor2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) reg_w_val(gspca_dev, 0x8112, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) __u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (sd->chip_revision == Rev012A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) reg = 0x8610;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) reg = 0x8611;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) reg_w_val(gspca_dev, reg + 0, val); /* R */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) reg_w_val(gspca_dev, reg + 1, val); /* Gr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) reg_w_val(gspca_dev, reg + 2, val); /* B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) reg_w_val(gspca_dev, reg + 3, val); /* Gb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) __u8 blue, red;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) __u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* try to emulate MS-win as possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) red = 0x20 + white * 3 / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) blue = 0x90 - white * 5 / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (sd->chip_revision == Rev012A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) reg = 0x8614;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) reg = 0x8651;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) red += contrast - 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) blue += contrast - 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) reg_w_val(gspca_dev, 0x8652, contrast + 0x20); /* Gr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) reg_w_val(gspca_dev, 0x8654, contrast + 0x20); /* Gb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) reg_w_val(gspca_dev, reg, red);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) reg_w_val(gspca_dev, reg + 2, blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* rev 12a only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static void setexposure(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int i, expo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* Register 0x8309 controls exposure for the spca561,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) the basic exposure setting goes from 1-2047, where 1 is completely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) dark and 2047 is very bright. It not only influences exposure but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) also the framerate (to allow for longer exposure) from 1 - 300 it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) only raises the exposure time then from 300 - 600 it halves the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) framerate to be able to further raise the exposure time and for every
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 300 more it halves the framerate again. This allows for a maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) configure a divider for the base framerate which us used at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) exposure setting of 1-300. These bits configure the base framerate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) according to the following formula: fps = 60 / (value + 2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* We choose to use the high bits setting the fixed framerate divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) asap, as setting high basic exposure setting without the fixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) divider in combination with high gains makes the cam stop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) int table[] = { 0, 450, 550, 625, EXPOSURE_MAX };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (val <= table[i + 1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) expo = val - table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) expo += 300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) expo |= i << 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) gspca_dev->usb_buf[0] = expo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) gspca_dev->usb_buf[1] = expo >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) reg_w_buf(gspca_dev, 0x8309, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* rev 12a only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static void setgain(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /* gain reg low 6 bits 0-63 gain, bit 6 and 7, both double the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) sensitivity when set, so 31 + one of them set == 63, and 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) with both of them set == 63 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (val < 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) gspca_dev->usb_buf[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) else if (val < 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) gspca_dev->usb_buf[0] = (val / 2) | 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) gspca_dev->usb_buf[0] = (val / 4) | 0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) gspca_dev->usb_buf[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) reg_w_buf(gspca_dev, 0x8335, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static void setautogain(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) sd->ag_cnt = AG_CNT_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) sd->ag_cnt = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int sd_start_12a(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static const __u8 Reg8391[8] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (mode <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* Use compression on 320x240 and above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) reg_w_val(gspca_dev, 0x8500, 0x10 | mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /* I couldn't get the compression to work below 320x240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * Fortunately at these resolutions the bandwidth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * is sufficient to push raw frames at ~20fps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) reg_w_val(gspca_dev, 0x8500, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) } /* -- qq@kuku.eu.org */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) gspca_dev->usb_buf[0] = 0xaa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) gspca_dev->usb_buf[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) reg_w_buf(gspca_dev, 0x8307, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* clock - lower 0x8X values lead to fps > 30 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) reg_w_val(gspca_dev, 0x8700, 0x8a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /* 0x8f 0x85 0x27 clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) reg_w_val(gspca_dev, 0x8112, 0x1e | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) reg_w_val(gspca_dev, 0x850b, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) memcpy(gspca_dev->usb_buf, Reg8391, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) reg_w_buf(gspca_dev, 0x8391, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) reg_w_buf(gspca_dev, 0x8390, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* Led ON (bit 3 -> 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) reg_w_val(gspca_dev, 0x8114, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static int sd_start_72a(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int Clck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) write_vector(gspca_dev, rev72a_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) msleep(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) write_vector(gspca_dev, rev72a_init_data1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) write_sensor_72a(gspca_dev, rev72a_init_sensor1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) Clck = 0x27; /* ms-win 0x87 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) Clck = 0x25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) Clck = 0x22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) Clck = 0x21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) reg_w_val(gspca_dev, 0x8700, Clck); /* 0x27 clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) reg_w_val(gspca_dev, 0x8702, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) reg_w_val(gspca_dev, 0x8500, mode); /* mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) write_sensor_72a(gspca_dev, rev72a_init_sensor2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) v4l2_ctrl_g_ctrl(sd->contrast));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* setbrightness(gspca_dev); * fixme: bad values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) reg_w_val(gspca_dev, 0x8112, 0x10 | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static void sd_stopN(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (sd->chip_revision == Rev012A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) reg_w_val(gspca_dev, 0x8112, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* Led Off (bit 3 -> 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) reg_w_val(gspca_dev, 0x8114, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) reg_w_val(gspca_dev, 0x8112, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /* reg_w_val(gspca_dev, 0x8102, 0x00); ?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static void do_autogain(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int expotimes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int pixelclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int gainG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) __u8 R, Gr, Gb, B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) int y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) __u8 luma_mean = 110;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) __u8 luma_delta = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) __u8 spring = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (sd->ag_cnt < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (--sd->ag_cnt >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) sd->ag_cnt = AG_CNT_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) switch (sd->chip_revision) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) case Rev072A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) reg_r(gspca_dev, 0x8621, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) Gr = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) reg_r(gspca_dev, 0x8622, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) R = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) reg_r(gspca_dev, 0x8623, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) B = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) reg_r(gspca_dev, 0x8624, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) Gb = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (y < luma_mean - luma_delta ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) y > luma_mean + luma_delta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) expotimes = i2c_read(gspca_dev, 0x09, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) pixelclk = 0x0800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) expotimes = expotimes & 0x07ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) gainG = i2c_read(gspca_dev, 0x35, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) expotimes += (luma_mean - y) >> spring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) gainG += (luma_mean - y) / 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (gainG > 0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) gainG = 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) else if (gainG < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) gainG = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) i2c_write(gspca_dev, gainG, 0x35);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (expotimes > 0x0256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) expotimes = 0x0256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) else if (expotimes < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) expotimes = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static void sd_pkt_scan(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) u8 *data, /* isoc packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int len) /* iso packet length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) switch (*data++) { /* sequence number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) case 0: /* start of frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /* This should never happen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (len < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) gspca_err(gspca_dev, "Short SOF packet, ignoring\n\n\n\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) gspca_dev->last_packet_type = DISCARD_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) #if IS_ENABLED(CONFIG_INPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (data[0] & 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) input_sync(gspca_dev->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) input_sync(gspca_dev->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (data[1] & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* compressed bayer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) /* raw bayer (with a header, which we skip) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (sd->chip_revision == Rev012A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) data += 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) len -= 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) data += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) len -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) case 0xff: /* drop (empty mpackets) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct gspca_dev *gspca_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) gspca_dev->usb_err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (!gspca_dev->streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) setbrightness(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* hue/contrast control cluster for 72a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) setwhite(gspca_dev, sd->hue->val, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) case V4L2_CID_HUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* just plain hue control for 12a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) setwhite(gspca_dev, ctrl->val, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case V4L2_CID_EXPOSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) setexposure(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) case V4L2_CID_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) setgain(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) setautogain(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) static const struct v4l2_ctrl_ops sd_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .s_ctrl = sd_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static int sd_init_controls_12a(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) gspca_dev->vdev.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) v4l2_ctrl_handler_init(hdl, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) V4L2_CID_EXPOSURE, 1, EXPOSURE_MAX, 1, 700);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) V4L2_CID_GAIN, 0, 255, 1, 63);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) pr_err("Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static int sd_init_controls_72a(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) gspca_dev->vdev.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) v4l2_ctrl_handler_init(hdl, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) V4L2_CID_BRIGHTNESS, 0, 0x3f, 1, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) pr_err("Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) v4l2_ctrl_cluster(2, &sd->contrast);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static const struct sd_desc sd_desc_12a = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) .init_controls = sd_init_controls_12a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .init = sd_init_12a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) .start = sd_start_12a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) .stopN = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) .pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) #if IS_ENABLED(CONFIG_INPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .other_input = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static const struct sd_desc sd_desc_72a = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) .init_controls = sd_init_controls_72a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) .init = sd_init_72a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) .start = sd_start_72a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .stopN = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .dq_callback = do_autogain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) #if IS_ENABLED(CONFIG_INPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .other_input = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static const struct sd_desc *sd_desc[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) &sd_desc_12a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) &sd_desc_72a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /* -- module initialisation -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) static const struct usb_device_id device_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) {USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) MODULE_DEVICE_TABLE(usb, device_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* -- device connect -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static int sd_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return gspca_dev_probe(intf, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) sd_desc[id->driver_info],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) sizeof(struct sd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) static struct usb_driver sd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) .id_table = device_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) .probe = sd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .disconnect = gspca_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .suspend = gspca_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) .resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) .reset_resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) module_usb_driver(sd_driver);