^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 spca504(abc) spca533 spca536 library
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define MODULE_NAME "sunplus"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "gspca.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "jpeg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define QUALITY 85
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* specific webcam descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct sd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct gspca_dev gspca_dev; /* !! must be the first item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) bool autogain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u8 bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define BRIDGE_SPCA504 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define BRIDGE_SPCA504B 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define BRIDGE_SPCA504C 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define BRIDGE_SPCA533 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define BRIDGE_SPCA536 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u8 subtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define AiptekMiniPenCam13 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define LogitechClickSmart420 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define LogitechClickSmart820 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MegapixV4 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MegaImageVI 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u8 jpeg_hdr[JPEG_HDR_SZ];
^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 vga_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .sizeimage = 320 * 240 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .priv = 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .bytesperline = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .sizeimage = 640 * 480 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .priv = 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static const struct v4l2_pix_format custom_mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .sizeimage = 320 * 240 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .priv = 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .bytesperline = 464,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .sizeimage = 464 * 480 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .priv = 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static const struct v4l2_pix_format vga_mode2[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .bytesperline = 176,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .sizeimage = 176 * 144 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .priv = 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .sizeimage = 320 * 240 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .priv = 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .bytesperline = 352,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .sizeimage = 352 * 288 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .priv = 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .bytesperline = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .sizeimage = 640 * 480 * 3 / 8 + 590,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .colorspace = V4L2_COLORSPACE_JPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .priv = 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define SPCA50X_OFFSET_DATA 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define SPCA504_PCCAM600_OFFSET_MODE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define SPCA504_PCCAM600_OFFSET_DATA 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* Frame packet header offsets for the spca533 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SPCA533_OFFSET_DATA 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define SPCA533_OFFSET_FRAMSEQ 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* Frame packet header offsets for the spca536 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define SPCA536_OFFSET_DATA 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define SPCA536_OFFSET_FRAMSEQ 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u8 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u16 idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Initialisation data for the Creative PC-CAM 600 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static const struct cmd spca504_pccam600_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* {0xa0, 0x0000, 0x0503}, * capture mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {0x00, 0x0000, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {0x00, 0x0013, 0x2301},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {0x00, 0x0003, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {0x00, 0x0001, 0x21ac},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {0x00, 0x0001, 0x21a6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {0x00, 0x0000, 0x21a7}, /* brightness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {0x00, 0x0020, 0x21a8}, /* contrast */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {0x00, 0x0001, 0x21ac}, /* sat/hue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {0x00, 0x0000, 0x21ad}, /* hue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {0x00, 0x001a, 0x21ae}, /* saturation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {0x00, 0x0002, 0x21a3}, /* gamma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {0x30, 0x0154, 0x0008},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {0x30, 0x0004, 0x0006},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {0x30, 0x0258, 0x0009},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {0x30, 0x0004, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {0x30, 0x0093, 0x0004},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {0x30, 0x0066, 0x0005},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {0x00, 0x0000, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {0x00, 0x0013, 0x2301},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {0x00, 0x0003, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {0x00, 0x0013, 0x2301},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {0x00, 0x0003, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Creative PC-CAM 600 specific open data, sent before using the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * generic initialisation data from spca504_open_data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static const struct cmd spca504_pccam600_open_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {0x00, 0x0001, 0x2501},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {0x20, 0x0500, 0x0001}, /* snapshot mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {0x00, 0x0003, 0x2880},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {0x00, 0x0001, 0x2881},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Initialisation data for the logitech clicksmart 420 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static const struct cmd spca504A_clicksmart420_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* {0xa0, 0x0000, 0x0503}, * capture mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {0x00, 0x0000, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {0x00, 0x0013, 0x2301},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {0x00, 0x0003, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {0x00, 0x0001, 0x21ac},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {0x00, 0x0001, 0x21a6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {0x00, 0x0000, 0x21a7}, /* brightness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {0x00, 0x0020, 0x21a8}, /* contrast */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {0x00, 0x0001, 0x21ac}, /* sat/hue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {0x00, 0x0000, 0x21ad}, /* hue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {0x00, 0x001a, 0x21ae}, /* saturation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {0x00, 0x0002, 0x21a3}, /* gamma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {0x30, 0x0004, 0x000a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {0xb0, 0x0001, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {0xa1, 0x0080, 0x0001},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {0x30, 0x0049, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {0x30, 0x0060, 0x0005},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {0x0c, 0x0004, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {0x00, 0x0000, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {0x00, 0x0000, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {0x00, 0x0013, 0x2301},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {0x00, 0x0003, 0x2000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* clicksmart 420 open data ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static const struct cmd spca504A_clicksmart420_open_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {0x00, 0x0001, 0x2501},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {0x20, 0x0502, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {0x06, 0x0000, 0x0000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {0x00, 0x0004, 0x2880},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {0x00, 0x0001, 0x2881},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {0xa0, 0x0000, 0x0503},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static const u8 qtable_creative_pccam[2][64] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { /* Q-table Y-components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) { /* Q-table C-components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* FIXME: This Q-table is identical to the Creative PC-CAM one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * except for one byte. Possibly a typo?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * NWG: 18/05/2003.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static const u8 qtable_spca504_default[2][64] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) { /* Q-table Y-components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) { /* Q-table C-components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* read <len> bytes to gspca_dev->usb_buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void reg_r(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u8 req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u16 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (len > USB_BUF_SZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) gspca_err(gspca_dev, "reg_r: buffer overflow\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) gspca_err(gspca_dev, "reg_r: zero-length read\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ret = usb_control_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) usb_rcvctrlpipe(gspca_dev->dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 0, /* value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) gspca_dev->usb_buf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) pr_err("reg_r err %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) gspca_dev->usb_err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * Make sure the buffer is zeroed to avoid uninitialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* write one byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static void reg_w_1(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) u8 req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) u16 value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) u16 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) u16 byte)
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) gspca_dev->usb_buf[0] = byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ret = usb_control_msg(gspca_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) usb_sndctrlpipe(gspca_dev->dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) value, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) gspca_dev->usb_buf, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) pr_err("reg_w_1 err %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) gspca_dev->usb_err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^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) /* write req / index / value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static void reg_w_riv(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) u8 req, u16 index, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct usb_device *dev = gspca_dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ret = usb_control_msg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) usb_sndctrlpipe(dev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) value, index, NULL, 0, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) pr_err("reg_w_riv err %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) gspca_dev->usb_err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) gspca_dbg(gspca_dev, D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) req, index, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static void write_vector(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) const struct cmd *data, int ncmds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) while (--ncmds >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) reg_w_riv(gspca_dev, data->req, data->idx, data->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) data++;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static void setup_qtable(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) const u8 qtable[2][64])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* loop over y components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) for (i = 0; i < 64; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* loop over c components */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) for (i = 0; i < 64; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
^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 void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u8 req, u16 idx, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) reg_w_riv(gspca_dev, req, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) reg_r(gspca_dev, 0x01, 0x0001, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) gspca_dbg(gspca_dev, D_FRAM, "before wait 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) gspca_dev->usb_buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) reg_w_riv(gspca_dev, req, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) msleep(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) reg_r(gspca_dev, 0x01, 0x0001, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) gspca_dbg(gspca_dev, D_FRAM, "after wait 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) gspca_dev->usb_buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void spca504_read_info(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) u8 info[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (gspca_debug < D_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) reg_r(gspca_dev, 0, i, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) info[i] = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) gspca_dbg(gspca_dev, D_STREAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) info[0], info[1], info[2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) info[3], info[4], info[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) u8 req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) u16 idx, u16 val, u8 endcode, u8 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) reg_w_riv(gspca_dev, req, idx, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) reg_r(gspca_dev, 0x01, 0x0001, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (gspca_dev->usb_err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) gspca_dbg(gspca_dev, D_FRAM, "Status 0x%02x Need 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) gspca_dev->usb_buf[0], endcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) count = 200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) while (--count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* gsmart mini2 write a each wait setting 1 ms is enough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* reg_w_riv(gspca_dev, req, idx, val); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) reg_r(gspca_dev, 0x01, 0x0001, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) status = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (status == endcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) gspca_dbg(gspca_dev, D_FRAM, "status 0x%04x after wait %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) status, 200 - count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int count = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) while (--count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) reg_r(gspca_dev, 0x21, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if ((gspca_dev->usb_buf[0] & 0x01) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int count = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) while (--count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) reg_r(gspca_dev, 0x21, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (gspca_dev->usb_buf[0] != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) reg_w_1(gspca_dev, 0x21, 0, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) reg_r(gspca_dev, 0x21, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) msleep(10);
^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) static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) u8 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (gspca_debug < D_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) data = gspca_dev->usb_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) reg_r(gspca_dev, 0x20, 0, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) gspca_dbg(gspca_dev, D_STREAM, "FirmWare: %d %d %d %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) data[0], data[1], data[2], data[3], data[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) reg_r(gspca_dev, 0x23, 0, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) reg_r(gspca_dev, 0x23, 1, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) u8 Size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) switch (sd->bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) case BRIDGE_SPCA533:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) reg_w_riv(gspca_dev, 0x31, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) spca504B_WaitCmdStatus(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) spca50x_GetFirmware(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) reg_r(gspca_dev, 0x24, 8, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) reg_w_1(gspca_dev, 0x25, 0, 4, Size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) reg_r(gspca_dev, 0x25, 4, 1); /* size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* Init the cam width height with some values get on init ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) spca504B_WaitCmdStatus(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* case BRIDGE_SPCA504B: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* case BRIDGE_SPCA536: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) reg_w_1(gspca_dev, 0x25, 0, 4, Size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) reg_r(gspca_dev, 0x25, 4, 1); /* size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) reg_w_1(gspca_dev, 0x27, 0, 0, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) reg_r(gspca_dev, 0x27, 0, 1); /* type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) case BRIDGE_SPCA504:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) Size += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (sd->subtype == AiptekMiniPenCam13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* spca504a aiptek */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) spca504A_acknowledged_command(gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 0x08, Size, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 0x80 | (Size & 0x0f), 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) spca504A_acknowledged_command(gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 1, 3, 0, 0x9f, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) case BRIDGE_SPCA504C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* capture mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static void spca504_wait_status(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) cnt = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) while (--cnt > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /* With this we get the status, when return 0 it's all ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) reg_r(gspca_dev, 0x06, 0x00, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (gspca_dev->usb_buf[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static void spca504B_setQtable(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) reg_w_1(gspca_dev, 0x26, 0, 0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) reg_r(gspca_dev, 0x26, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) reg_w_riv(gspca_dev, 0x00, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static void setcontrast(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) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) reg_w_riv(gspca_dev, 0x00, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static void setcolors(struct gspca_dev *gspca_dev, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) reg_w_riv(gspca_dev, 0x00, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static void init_ctl_reg(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) int pollreg = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) switch (sd->bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case BRIDGE_SPCA504:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) case BRIDGE_SPCA504C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) pollreg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* case BRIDGE_SPCA533: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* case BRIDGE_SPCA504B: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) case BRIDGE_SPCA536:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (pollreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* this function is called at probe time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) static int sd_config(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct cam *cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) cam = &gspca_dev->cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) sd->bridge = id->driver_info >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) sd->subtype = id->driver_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (sd->subtype == AiptekMiniPenCam13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* try to get the firmware as some cam answer 2.0.1.2.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * and should be a spca504b then overwrite that setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) reg_r(gspca_dev, 0x20, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) switch (gspca_dev->usb_buf[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) break; /* (right bridge/subtype) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) sd->bridge = BRIDGE_SPCA504B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) sd->subtype = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) switch (sd->bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* case BRIDGE_SPCA504B: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* case BRIDGE_SPCA504: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* case BRIDGE_SPCA536: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) cam->cam_mode = vga_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) cam->nmodes = ARRAY_SIZE(vga_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) case BRIDGE_SPCA533:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) cam->cam_mode = custom_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (sd->subtype == MegaImageVI) /* 320x240 only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) cam->nmodes = ARRAY_SIZE(custom_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) case BRIDGE_SPCA504C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) cam->cam_mode = vga_mode2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) cam->nmodes = ARRAY_SIZE(vga_mode2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* this function is called at probe and resume time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static int sd_init(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) switch (sd->bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) case BRIDGE_SPCA504B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) case BRIDGE_SPCA533:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) spca50x_GetFirmware(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) case BRIDGE_SPCA536:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) spca50x_GetFirmware(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) reg_r(gspca_dev, 0x00, 0x5002, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) reg_w_1(gspca_dev, 0x24, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) reg_r(gspca_dev, 0x24, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) reg_w_riv(gspca_dev, 0x34, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) spca504B_WaitCmdStatus(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) case BRIDGE_SPCA504C: /* pccam600 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504 (PC-CAM 600)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) spca504_wait_status(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (sd->subtype == LogitechClickSmart420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) write_vector(gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) spca504A_clicksmart420_open_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) ARRAY_SIZE(spca504A_clicksmart420_open_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) write_vector(gspca_dev, spca504_pccam600_open_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) ARRAY_SIZE(spca504_pccam600_open_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) setup_qtable(gspca_dev, qtable_creative_pccam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* case BRIDGE_SPCA504: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (sd->subtype == AiptekMiniPenCam13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) spca504_read_info(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) spca504A_acknowledged_command(gspca_dev, 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 8, 3, 0x9e, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* Twice sequential need status 0xff->0x9e->0x9d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) spca504A_acknowledged_command(gspca_dev, 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 8, 3, 0x9e, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) spca504A_acknowledged_command(gspca_dev, 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 0, 0, 0x9d, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /******************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* spca504a aiptek */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) spca504A_acknowledged_command(gspca_dev, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 6, 0, 0x86, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /* reg_write (dev, 0, 0x2000, 0); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* reg_write (dev, 0, 0x2883, 1); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /* spca504A_acknowledged_command (gspca_dev, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 6, 0, 0x86, 1); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* spca504A_acknowledged_command (gspca_dev, 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 0, 0, 0x9D, 1); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /* L92 sno1t.txt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) spca504A_acknowledged_command(gspca_dev, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 0x0f, 0, 0xff, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* setup qtable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) reg_w_riv(gspca_dev, 0, 0x2000, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) reg_w_riv(gspca_dev, 0, 0x2883, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) setup_qtable(gspca_dev, qtable_spca504_default);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static int sd_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) int enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* create the JPEG header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) gspca_dev->pixfmt.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 0x22); /* JPEG 411 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) jpeg_set_qual(sd->jpeg_hdr, QUALITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (sd->bridge == BRIDGE_SPCA504B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) spca504B_setQtable(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) spca504B_SetSizeType(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) switch (sd->bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* case BRIDGE_SPCA504B: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* case BRIDGE_SPCA533: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* case BRIDGE_SPCA536: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) switch (sd->subtype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) case MegapixV4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) case LogitechClickSmart820:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) case MegaImageVI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) reg_w_riv(gspca_dev, 0xf0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) spca504B_WaitCmdStatus(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) reg_w_riv(gspca_dev, 0xf0, 4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) spca504B_WaitCmdStatus(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) spca504B_WaitCmdStatus(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) case BRIDGE_SPCA504:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (sd->subtype == AiptekMiniPenCam13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) spca504_read_info(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) spca504A_acknowledged_command(gspca_dev, 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 8, 3, 0x9e, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* Twice sequential need status 0xff->0x9e->0x9d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) spca504A_acknowledged_command(gspca_dev, 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 8, 3, 0x9e, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) spca504A_acknowledged_command(gspca_dev, 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 0, 0, 0x9d, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) spca504_read_info(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) spca504B_SetSizeType(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* L92 sno1t.txt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) case BRIDGE_SPCA504C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (sd->subtype == LogitechClickSmart420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) write_vector(gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) spca504A_clicksmart420_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) ARRAY_SIZE(spca504A_clicksmart420_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) write_vector(gspca_dev, spca504_pccam600_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ARRAY_SIZE(spca504_pccam600_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) enable = (sd->autogain ? 0x04 : 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* auto exposure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* auto whiteness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /* set default exposure compensation and whiteness balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) spca504B_SetSizeType(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) init_ctl_reg(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) static void sd_stopN(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) switch (sd->bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* case BRIDGE_SPCA533: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* case BRIDGE_SPCA536: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /* case BRIDGE_SPCA504B: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) reg_w_riv(gspca_dev, 0x31, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) spca504B_WaitCmdStatus(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) spca504B_PollingDataReady(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) case BRIDGE_SPCA504:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) case BRIDGE_SPCA504C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (sd->subtype == AiptekMiniPenCam13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) /* spca504a aiptek */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* spca504A_acknowledged_command(gspca_dev, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 6, 0, 0x86, 1); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) spca504A_acknowledged_command(gspca_dev, 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 0x00, 0x00, 0x9d, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) spca504A_acknowledged_command(gspca_dev, 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 0x0f, 0x00, 0xff, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static void sd_pkt_scan(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) u8 *data, /* isoc packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) int len) /* iso packet length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) int i, sof = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static u8 ffd9[] = {0xff, 0xd9};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /* frames are jpeg 4.1.1 without 0xff escape */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) switch (sd->bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) case BRIDGE_SPCA533:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (data[0] == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (data[1] != 0x01) { /* drop packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /* gspca_dev->last_packet_type = DISCARD_PACKET; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) sof = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) data += SPCA533_OFFSET_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) len -= SPCA533_OFFSET_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) data += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) len -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) case BRIDGE_SPCA536:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (data[0] == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) sof = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) data += SPCA536_OFFSET_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) len -= SPCA536_OFFSET_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) data += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /* case BRIDGE_SPCA504: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* case BRIDGE_SPCA504B: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) switch (data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) case 0xfe: /* start of frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) sof = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) data += SPCA50X_OFFSET_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) len -= SPCA50X_OFFSET_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) case 0xff: /* drop packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /* gspca_dev->last_packet_type = DISCARD_PACKET; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) data += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) len -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) case BRIDGE_SPCA504C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) switch (data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) case 0xfe: /* start of frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) sof = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) data += SPCA504_PCCAM600_OFFSET_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) len -= SPCA504_PCCAM600_OFFSET_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) case 0xff: /* drop packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) /* gspca_dev->last_packet_type = DISCARD_PACKET; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) data += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) len -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (sof) { /* start of frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) gspca_frame_add(gspca_dev, LAST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) ffd9, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* put the JPEG header in the new frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) gspca_frame_add(gspca_dev, FIRST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) sd->jpeg_hdr, JPEG_HDR_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) /* add 0x00 after 0xff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (data[i] == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) gspca_frame_add(gspca_dev, INTER_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) data, i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) len -= i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) data += i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) *data = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) } while (i < len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct gspca_dev *gspca_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) gspca_dev->usb_err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (!gspca_dev->streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) setbrightness(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) setcontrast(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) setcolors(gspca_dev, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) sd->autogain = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) static const struct v4l2_ctrl_ops sd_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) .s_ctrl = sd_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static int sd_init_controls(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) gspca_dev->vdev.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) v4l2_ctrl_handler_init(hdl, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) pr_err("Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static const struct sd_desc sd_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .init = sd_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .init_controls = sd_init_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .start = sd_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .stopN = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /* -- module initialisation -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) #define BS(bridge, subtype) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) .driver_info = (BRIDGE_ ## bridge << 8) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) | (subtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) static const struct usb_device_id device_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) MODULE_DEVICE_TABLE(usb, device_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /* -- device connect -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) static int sd_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static struct usb_driver sd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) .id_table = device_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) .probe = sd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) .disconnect = gspca_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) .suspend = gspca_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) .resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) .reset_resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) module_usb_driver(sd_driver);