^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) * cpia CPiA (1) gspca driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This module is adapted from the in kernel v4l1 cpia driver which is :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * (C) Copyright 1999-2000 Peter Pregler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * (C) Copyright 1999-2000 Scott J. Bertin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * (C) Copyright 2000 STMicroelectronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define MODULE_NAME "cpia1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "gspca.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) MODULE_DESCRIPTION("Vision CPiA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* constant value's */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MAGIC_0 0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MAGIC_1 0x68
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DATA_IN 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DATA_OUT 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define VIDEOSIZE_QCIF 0 /* 176x144 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define VIDEOSIZE_CIF 1 /* 352x288 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SUBSAMPLE_420 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SUBSAMPLE_422 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define YUVORDER_YUYV 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define YUVORDER_UYVY 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define NOT_COMPRESSED 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define COMPRESSED 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define NO_DECIMATION 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define DECIMATION_ENAB 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define EOI 0xff /* End Of Image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define EOL 0xfd /* End Of Line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define FRAME_HEADER_SIZE 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Image grab modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define CPIA_GRAB_SINGLE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define CPIA_GRAB_CONTINEOUS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Compression parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CPIA_COMPRESSION_NONE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define CPIA_COMPRESSION_AUTO 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define CPIA_COMPRESSION_MANUAL 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define CPIA_COMPRESSION_TARGET_QUALITY 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CPIA_COMPRESSION_TARGET_FRAMERATE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Return offsets for GetCameraState */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define SYSTEMSTATE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define GRABSTATE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define STREAMSTATE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define FATALERROR 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define CMDERROR 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define DEBUGFLAGS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define VPSTATUS 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define ERRORCODE 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* SystemState */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define UNINITIALISED_STATE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define PASS_THROUGH_STATE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define LO_POWER_STATE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define HI_POWER_STATE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define WARM_BOOT_STATE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* GrabState */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define GRAB_IDLE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define GRAB_ACTIVE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define GRAB_DONE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* StreamState */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define STREAM_NOT_READY 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define STREAM_READY 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define STREAM_OPEN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define STREAM_PAUSED 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define STREAM_FINISHED 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Fatal Error, CmdError, and DebugFlags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define CPIA_FLAG 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SYSTEM_FLAG 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define INT_CTRL_FLAG 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define PROCESS_FLAG 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define COM_FLAG 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define VP_CTRL_FLAG 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define CAPTURE_FLAG 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define DEBUG_FLAG 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* VPStatus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define VP_STATE_OK 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define VP_STATE_FAILED_VIDEOINIT 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define VP_STATE_FAILED_AECACBINIT 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define VP_STATE_AEC_MAX 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define VP_STATE_ACB_BMAX 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define VP_STATE_ACB_RMIN 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define VP_STATE_ACB_GMIN 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define VP_STATE_ACB_RMAX 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define VP_STATE_ACB_GMAX 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* default (minimum) compensation values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define COMP_RED 220
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define COMP_GREEN1 214
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define COMP_GREEN2 COMP_GREEN1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define COMP_BLUE 230
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* exposure status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define EXPOSURE_VERY_LIGHT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define EXPOSURE_LIGHT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define EXPOSURE_NORMAL 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define EXPOSURE_DARK 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define EXPOSURE_VERY_DARK 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define CPIA_MODULE_CPIA (0 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define CPIA_MODULE_SYSTEM (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define CPIA_MODULE_VP_CTRL (5 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define CPIA_MODULE_CAPTURE (6 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define CPIA_MODULE_DEBUG (7 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define INPUT (DATA_IN << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define OUTPUT (DATA_OUT << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define ROUND_UP_EXP_FOR_FLICKER 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* Constants for automatic frame rate adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define MAX_EXP 302
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define MAX_EXP_102 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #define LOW_EXP 140
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #define VERY_LOW_EXP 70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #define TC 94
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define EXP_ACC_DARK 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #define EXP_ACC_LIGHT 90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #define HIGH_COMP_102 160
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) #define MAX_COMP 239
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #define DARK_TIME 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #define LIGHT_TIME 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) sd->params.version.firmwareRevision == (y))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #define CPIA1_CID_COMP_TARGET (V4L2_CTRL_CLASS_USER + 0x1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define BRIGHTNESS_DEF 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) #define CONTRAST_DEF 48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #define SATURATION_DEF 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #define FREQ_DEF V4L2_CID_POWER_LINE_FREQUENCY_50HZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #define ILLUMINATORS_1_DEF 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define ILLUMINATORS_2_DEF 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* Developer's Guide Table 5 p 3-34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static u8 flicker_jumps[2][2][4] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct cam_params {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) u8 firmwareVersion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u8 firmwareRevision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u8 vcVersion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u8 vcRevision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) } version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) u16 vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) u16 product;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) u16 deviceRevision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) } pnpID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) u8 vpVersion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) u8 vpRevision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) u16 cameraHeadID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) } vpVersion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) u8 systemState;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u8 grabState;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u8 streamState;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u8 fatalError;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) u8 cmdError;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) u8 debugFlags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u8 vpStatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u8 errorCode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) } status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) u8 brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u8 contrast;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) u8 saturation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) } colourParams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u8 gainMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) u8 expMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) u8 compMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) u8 centreWeight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u8 gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u8 fineExp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) u8 coarseExpLo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) u8 coarseExpHi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) u8 redComp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) u8 green1Comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) u8 green2Comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u8 blueComp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) } exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u8 balanceMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u8 redGain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u8 greenGain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) u8 blueGain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) } colourBalance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u8 divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) u8 baserate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) } sensorFps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) u8 gain1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) u8 gain2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u8 gain4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) u8 gain8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) } apcor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) u8 disabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) u8 flickerMode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) u8 coarseJump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) u8 allowableOverExposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) } flickerControl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) u8 gain1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u8 gain2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u8 gain4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u8 gain8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) } vlOffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) u8 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) u8 decimation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) } compression;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) u8 frTargeting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u8 targetFR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) u8 targetQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) } compressionTarget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) u8 yThreshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) u8 uvThreshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) } yuvThreshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) u8 hysteresis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) u8 threshMax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) u8 smallStep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) u8 largeStep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) u8 decimationHysteresis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u8 frDiffStepThresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u8 qDiffStepThresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) u8 decimationThreshMod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) } compressionParams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u8 videoSize; /* CIF/QCIF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) u8 subSample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u8 yuvOrder;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct { /* Intel QX3 specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u8 qx3_detected; /* a QX3 is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) u8 toplight; /* top light lit , R/W */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) u8 bottomlight; /* bottom light lit, R/W */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) u8 button; /* snapshot button pressed (R/O) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) u8 cradled; /* microscope is in cradle (R/O) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) } qx3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u8 colStart; /* skip first 8*colStart pixels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u8 colEnd; /* finish at 8*colEnd pixels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) u8 rowStart; /* skip first 4*rowStart lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) u8 rowEnd; /* finish at 4*rowEnd lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) } roi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) u8 ecpTiming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) u8 streamStartLine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* specific webcam descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct sd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct gspca_dev gspca_dev; /* !! must be the first item */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct cam_params params; /* camera settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) atomic_t cam_exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) atomic_t fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) u8 exposure_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct v4l2_ctrl *freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) u8 first_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static const struct v4l2_pix_format mode[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* The sizeimage is trial and error, as with low framerates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) the camera will pad out usb frames, making the image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) data larger then strictly necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) .bytesperline = 160,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .sizeimage = 65536,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .priv = 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) .bytesperline = 172,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .sizeimage = 65536,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .priv = 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .bytesperline = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .sizeimage = 262144,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .priv = 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) .bytesperline = 352,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .sizeimage = 262144,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .priv = 0},
^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) /**********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * General functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) **********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) u8 requesttype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) unsigned int pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int ret, databytes = command[6] | (command[7] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Sometimes we see spurious EPIPE errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int retries = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (command[0] == DATA_IN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) } else if (command[0] == DATA_OUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) gspca_err(gspca_dev, "Unexpected first byte of command: %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) command[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ret = usb_control_msg(gspca_dev->dev, pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) command[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) requesttype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) command[2] | (command[3] << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) command[4] | (command[5] << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) gspca_dev->usb_buf, databytes, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pr_err("usb_control_msg %02x, error %d\n", command[1], ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (ret == -EPIPE && retries > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) retries--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return (ret < 0) ? ret : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* send an arbitrary command to the camera */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static int do_command(struct gspca_dev *gspca_dev, u16 command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) u8 a, u8 b, u8 c, u8 d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) int ret, datasize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) u8 cmd[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) switch (command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case CPIA_COMMAND_GetCPIAVersion:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case CPIA_COMMAND_GetPnPID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) case CPIA_COMMAND_GetCameraStatus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) case CPIA_COMMAND_GetVPVersion:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) case CPIA_COMMAND_GetColourParams:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case CPIA_COMMAND_GetColourBalance:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) case CPIA_COMMAND_GetExposure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) datasize = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) case CPIA_COMMAND_ReadMCPorts:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) case CPIA_COMMAND_ReadVCRegs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) datasize = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) datasize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) cmd[0] = command >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) cmd[1] = command & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) cmd[2] = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) cmd[3] = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) cmd[4] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) cmd[5] = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) cmd[6] = datasize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) cmd[7] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ret = cpia_usb_transferCmd(gspca_dev, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) switch (command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case CPIA_COMMAND_GetCPIAVersion:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) sd->params.version.firmwareVersion = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) sd->params.version.firmwareRevision = gspca_dev->usb_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) sd->params.version.vcVersion = gspca_dev->usb_buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) sd->params.version.vcRevision = gspca_dev->usb_buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) case CPIA_COMMAND_GetPnPID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) sd->params.pnpID.vendor =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) sd->params.pnpID.product =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) sd->params.pnpID.deviceRevision =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) case CPIA_COMMAND_GetCameraStatus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) sd->params.status.systemState = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) sd->params.status.grabState = gspca_dev->usb_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) sd->params.status.streamState = gspca_dev->usb_buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) sd->params.status.fatalError = gspca_dev->usb_buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) sd->params.status.cmdError = gspca_dev->usb_buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) sd->params.status.debugFlags = gspca_dev->usb_buf[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) sd->params.status.vpStatus = gspca_dev->usb_buf[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) sd->params.status.errorCode = gspca_dev->usb_buf[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) case CPIA_COMMAND_GetVPVersion:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) sd->params.vpVersion.cameraHeadID =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) case CPIA_COMMAND_GetColourParams:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) sd->params.colourParams.brightness = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) sd->params.colourParams.contrast = gspca_dev->usb_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) sd->params.colourParams.saturation = gspca_dev->usb_buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case CPIA_COMMAND_GetColourBalance:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) sd->params.colourBalance.redGain = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) case CPIA_COMMAND_GetExposure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) sd->params.exposure.gain = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) sd->params.exposure.fineExp = gspca_dev->usb_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) sd->params.exposure.redComp = gspca_dev->usb_buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) sd->params.exposure.green1Comp = gspca_dev->usb_buf[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) sd->params.exposure.green2Comp = gspca_dev->usb_buf[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) sd->params.exposure.blueComp = gspca_dev->usb_buf[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case CPIA_COMMAND_ReadMCPorts:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* test button press */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) a = ((gspca_dev->usb_buf[1] & 0x02) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (a != sd->params.qx3.button) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) #if IS_ENABLED(CONFIG_INPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) input_report_key(gspca_dev->input_dev, KEY_CAMERA, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) input_sync(gspca_dev->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) sd->params.qx3.button = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (sd->params.qx3.button) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* button pressed - unlock the latch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) ret = do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 3, 0xdf, 0xdf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ret = do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 3, 0xff, 0xff, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* test whether microscope is cradled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* send a command to the camera with an additional data transaction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static int do_command_extended(struct gspca_dev *gspca_dev, u16 command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) u8 a, u8 b, u8 c, u8 d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) u8 e, u8 f, u8 g, u8 h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) u8 i, u8 j, u8 k, u8 l)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) u8 cmd[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) cmd[0] = command >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) cmd[1] = command & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) cmd[2] = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) cmd[3] = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) cmd[4] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) cmd[5] = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) cmd[6] = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) cmd[7] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) gspca_dev->usb_buf[0] = e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) gspca_dev->usb_buf[1] = f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) gspca_dev->usb_buf[2] = g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) gspca_dev->usb_buf[3] = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) gspca_dev->usb_buf[4] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) gspca_dev->usb_buf[5] = j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) gspca_dev->usb_buf[6] = k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) gspca_dev->usb_buf[7] = l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return cpia_usb_transferCmd(gspca_dev, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* find_over_exposure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * Finds a suitable value of OverExposure for use with SetFlickerCtrl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * Some calculation is required because this value changes with the brightness
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * set with SetColourParameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * Parameters: Brightness - last brightness value set with SetColourParameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * Returns: OverExposure value to use with SetFlickerCtrl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) #define FLICKER_MAX_EXPOSURE 250
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) #define FLICKER_ALLOWABLE_OVER_EXPOSURE 146
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) #define FLICKER_BRIGHTNESS_CONSTANT 59
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static int find_over_exposure(int brightness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int MaxAllowableOverExposure, OverExposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) FLICKER_BRIGHTNESS_CONSTANT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) OverExposure = MaxAllowableOverExposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return OverExposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) #undef FLICKER_MAX_EXPOSURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) #undef FLICKER_ALLOWABLE_OVER_EXPOSURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) #undef FLICKER_BRIGHTNESS_CONSTANT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* initialise cam_data structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static void reset_camera_params(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct cam_params *params = &sd->params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* The following parameter values are the defaults from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * "Software Developer's Guide for CPiA Cameras". Any changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * to the defaults are noted in comments. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) params->colourParams.brightness = BRIGHTNESS_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) params->colourParams.contrast = CONTRAST_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) params->colourParams.saturation = SATURATION_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) params->exposure.gainMode = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) params->exposure.expMode = 2; /* AEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) params->exposure.compMode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) params->exposure.centreWeight = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) params->exposure.gain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) params->exposure.fineExp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) params->exposure.coarseExpLo = 185;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) params->exposure.coarseExpHi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) params->exposure.redComp = COMP_RED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) params->exposure.green1Comp = COMP_GREEN1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) params->exposure.green2Comp = COMP_GREEN2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) params->exposure.blueComp = COMP_BLUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) params->colourBalance.balanceMode = 2; /* ACB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) params->colourBalance.redGain = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) params->colourBalance.greenGain = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) params->colourBalance.blueGain = 92;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) params->apcor.gain1 = 0x18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) params->apcor.gain2 = 0x16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) params->apcor.gain4 = 0x24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) params->apcor.gain8 = 0x34;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) params->vlOffset.gain1 = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) params->vlOffset.gain2 = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) params->vlOffset.gain4 = 26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) params->vlOffset.gain8 = 26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) params->compressionParams.hysteresis = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) params->compressionParams.threshMax = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) params->compressionParams.smallStep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) params->compressionParams.largeStep = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) params->compressionParams.decimationHysteresis = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) params->compressionParams.frDiffStepThresh = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) params->compressionParams.qDiffStepThresh = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) params->compressionParams.decimationThreshMod = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /* End of default values from Software Developer's Guide */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /* Set Sensor FPS to 15fps. This seems better than 30fps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * for indoor lighting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) params->sensorFps.divisor = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) params->sensorFps.baserate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) params->flickerControl.flickerMode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) params->flickerControl.disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) params->flickerControl.coarseJump =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) flicker_jumps[sd->mainsFreq]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) [params->sensorFps.baserate]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) [params->sensorFps.divisor];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) params->flickerControl.allowableOverExposure =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) find_over_exposure(params->colourParams.brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) params->yuvThreshold.yThreshold = 6; /* From windows driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) params->yuvThreshold.uvThreshold = 6; /* From windows driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) params->format.subSample = SUBSAMPLE_420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) params->format.yuvOrder = YUVORDER_YUYV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) params->compression.mode = CPIA_COMPRESSION_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) params->compression.decimation = NO_DECIMATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) params->compressionTarget.frTargeting = COMP_TARGET_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) params->compressionTarget.targetFR = 15; /* From windows driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) params->compressionTarget.targetQ = 5; /* From windows driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) params->qx3.qx3_detected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) params->qx3.toplight = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) params->qx3.bottomlight = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) params->qx3.button = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) params->qx3.cradled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static void printstatus(struct gspca_dev *gspca_dev, struct cam_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) gspca_dbg(gspca_dev, D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) params->status.systemState, params->status.grabState,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) params->status.streamState, params->status.fatalError,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) params->status.cmdError, params->status.debugFlags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) params->status.vpStatus, params->status.errorCode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static int goto_low_power(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (sd->params.status.systemState != LO_POWER_STATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (sd->params.status.systemState != WARM_BOOT_STATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) gspca_err(gspca_dev, "unexpected state after lo power cmd: %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) sd->params.status.systemState);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) printstatus(gspca_dev, &sd->params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) gspca_dbg(gspca_dev, D_CONF, "camera now in LOW power state\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static int goto_high_power(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) msleep_interruptible(40); /* windows driver does it too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (sd->params.status.systemState != HI_POWER_STATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) gspca_err(gspca_dev, "unexpected state after hi power cmd: %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) sd->params.status.systemState);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) printstatus(gspca_dev, &sd->params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) gspca_dbg(gspca_dev, D_CONF, "camera now in HIGH power state\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static int get_version_information(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* GetCPIAVersion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* GetPnPID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static int save_camera_state(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static int command_setformat(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) sd->params.format.videoSize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) sd->params.format.subSample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) sd->params.format.yuvOrder, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return do_command(gspca_dev, CPIA_COMMAND_SetROI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) sd->params.roi.colStart, sd->params.roi.colEnd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) sd->params.roi.rowStart, sd->params.roi.rowEnd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static int command_setcolourparams(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return do_command(gspca_dev, CPIA_COMMAND_SetColourParams,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) sd->params.colourParams.brightness,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) sd->params.colourParams.contrast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) sd->params.colourParams.saturation, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static int command_setapcor(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) return do_command(gspca_dev, CPIA_COMMAND_SetApcor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) sd->params.apcor.gain1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) sd->params.apcor.gain2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) sd->params.apcor.gain4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) sd->params.apcor.gain8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int command_setvloffset(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) sd->params.vlOffset.gain1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) sd->params.vlOffset.gain2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) sd->params.vlOffset.gain4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) sd->params.vlOffset.gain8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static int command_setexposure(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) sd->params.exposure.gainMode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) sd->params.exposure.compMode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) sd->params.exposure.centreWeight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) sd->params.exposure.gain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) sd->params.exposure.fineExp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) sd->params.exposure.coarseExpLo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) sd->params.exposure.coarseExpHi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) sd->params.exposure.redComp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) sd->params.exposure.green1Comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) sd->params.exposure.green2Comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) sd->params.exposure.blueComp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (sd->params.exposure.expMode != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) sd->params.exposure.expMode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) sd->params.exposure.gain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) sd->params.exposure.fineExp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) sd->params.exposure.coarseExpLo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) sd->params.exposure.coarseExpHi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return ret;
^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) static int command_setcolourbalance(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (sd->params.colourBalance.balanceMode == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) sd->params.colourBalance.redGain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) sd->params.colourBalance.greenGain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) sd->params.colourBalance.blueGain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 3, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (sd->params.colourBalance.balanceMode == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 2, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (sd->params.colourBalance.balanceMode == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 3, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) static int command_setcompressiontarget(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) sd->params.compressionTarget.frTargeting,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) sd->params.compressionTarget.targetFR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) sd->params.compressionTarget.targetQ, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static int command_setyuvtresh(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) sd->params.yuvThreshold.yThreshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) sd->params.yuvThreshold.uvThreshold, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) static int command_setcompressionparams(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return do_command_extended(gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) CPIA_COMMAND_SetCompressionParams,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) sd->params.compressionParams.hysteresis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) sd->params.compressionParams.threshMax,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) sd->params.compressionParams.smallStep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) sd->params.compressionParams.largeStep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) sd->params.compressionParams.decimationHysteresis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) sd->params.compressionParams.frDiffStepThresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) sd->params.compressionParams.qDiffStepThresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) sd->params.compressionParams.decimationThreshMod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static int command_setcompression(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return do_command(gspca_dev, CPIA_COMMAND_SetCompression,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) sd->params.compression.mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) sd->params.compression.decimation, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int command_setsensorfps(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) sd->params.sensorFps.divisor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) sd->params.sensorFps.baserate, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static int command_setflickerctrl(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) sd->params.flickerControl.flickerMode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) sd->params.flickerControl.coarseJump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) sd->params.flickerControl.allowableOverExposure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static int command_setecptiming(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) sd->params.ecpTiming, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static int command_pause(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static int command_resume(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) 0, sd->params.streamStartLine, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static int command_setlights(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) int ret, p1, p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) p1 = (sd->params.qx3.bottomlight == 0) << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) p2 = (sd->params.qx3.toplight == 0) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) 0x90, 0x8f, 0x50, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) p1 | p2 | 0xe0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /* Everything in here is from the Windows driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) /* define for compgain calculation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) #define COMPGAIN(base, curexp, newexp) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) #define EXP_FROM_COMP(basecomp, curcomp, curexp) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) (u16)((float)curexp * (float)(u8)(curcomp + 128) / \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) (float)(u8)(basecomp - 128))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /* equivalent functions without floating point math */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) #define COMPGAIN(base, curexp, newexp) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) #define EXP_FROM_COMP(basecomp, curcomp, curexp) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) int currentexp = sd->params.exposure.coarseExpLo +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) sd->params.exposure.coarseExpHi * 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) int ret, startexp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) int cj = sd->params.flickerControl.coarseJump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) sd->params.flickerControl.flickerMode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) sd->params.flickerControl.disabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (sd->params.exposure.expMode != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) sd->params.exposure.expMode = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) sd->exposure_status = EXPOSURE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) currentexp = currentexp << sd->params.exposure.gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) sd->params.exposure.gain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) /* round down current exposure to nearest value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (startexp < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) startexp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) startexp = (startexp * cj) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (FIRMWARE_VERSION(1, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) while (startexp > MAX_EXP_102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) startexp -= cj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) while (startexp > MAX_EXP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) startexp -= cj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) sd->params.exposure.coarseExpLo = startexp & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) sd->params.exposure.coarseExpHi = startexp >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (currentexp > startexp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (currentexp > (2 * startexp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) currentexp = 2 * startexp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) sd->params.exposure.redComp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) COMPGAIN(COMP_RED, currentexp, startexp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) sd->params.exposure.green1Comp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) COMPGAIN(COMP_GREEN1, currentexp, startexp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) sd->params.exposure.green2Comp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) COMPGAIN(COMP_GREEN2, currentexp, startexp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) sd->params.exposure.blueComp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) COMPGAIN(COMP_BLUE, currentexp, startexp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) sd->params.exposure.redComp = COMP_RED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) sd->params.exposure.green1Comp = COMP_GREEN1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) sd->params.exposure.green2Comp = COMP_GREEN2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) sd->params.exposure.blueComp = COMP_BLUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (FIRMWARE_VERSION(1, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) sd->params.exposure.compMode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) sd->params.exposure.compMode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) sd->params.apcor.gain1 = 0x18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) sd->params.apcor.gain2 = 0x18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) sd->params.apcor.gain4 = 0x16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) sd->params.apcor.gain8 = 0x14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) sd->params.flickerControl.flickerMode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) sd->params.flickerControl.disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* Average equivalent coarse for each comp channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) startexp = EXP_FROM_COMP(COMP_RED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) sd->params.exposure.redComp, currentexp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) startexp += EXP_FROM_COMP(COMP_GREEN1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) sd->params.exposure.green1Comp, currentexp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) startexp += EXP_FROM_COMP(COMP_GREEN2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) sd->params.exposure.green2Comp, currentexp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) startexp += EXP_FROM_COMP(COMP_BLUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) sd->params.exposure.blueComp, currentexp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) startexp = startexp >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) while (startexp > MAX_EXP && sd->params.exposure.gain <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) sd->params.exposure.gainMode - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) startexp = startexp >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) ++sd->params.exposure.gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) startexp = MAX_EXP_102;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (startexp > MAX_EXP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) startexp = MAX_EXP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) sd->params.exposure.coarseExpLo = startexp & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) sd->params.exposure.coarseExpHi = startexp >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) sd->params.exposure.redComp = COMP_RED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) sd->params.exposure.green1Comp = COMP_GREEN1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) sd->params.exposure.green2Comp = COMP_GREEN2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) sd->params.exposure.blueComp = COMP_BLUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) sd->params.exposure.compMode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) sd->params.apcor.gain1 = 0x18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) sd->params.apcor.gain2 = 0x16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) sd->params.apcor.gain4 = 0x24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) sd->params.apcor.gain8 = 0x34;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) sd->params.vlOffset.gain1 = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) sd->params.vlOffset.gain2 = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) sd->params.vlOffset.gain4 = 26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) sd->params.vlOffset.gain8 = 26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (apply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) ret = command_setexposure(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) ret = command_setapcor(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) ret = command_setvloffset(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) ret = command_setflickerctrl(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) #undef EXP_FROM_COMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) #undef COMPGAIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* monitor the exposure and adjust the sensor frame rate if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) static void monitor_exposure(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) u8 exp_acc, bcomp, cmd[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) int ret, light_exp, dark_exp, very_dark_exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) int old_exposure, new_exposure, framerate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) int setfps = 0, setexp = 0, setflicker = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) /* get necessary stats and register settings from camera */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* do_command can't handle this, so do it ourselves */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) cmd[2] = 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) cmd[3] = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) cmd[4] = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) cmd[5] = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) cmd[6] = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) cmd[7] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) ret = cpia_usb_transferCmd(gspca_dev, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) exp_acc = gspca_dev->usb_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) bcomp = gspca_dev->usb_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) light_exp = sd->params.colourParams.brightness +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) TC - 50 + EXP_ACC_LIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (light_exp > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) light_exp = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) dark_exp = sd->params.colourParams.brightness +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) TC - 50 - EXP_ACC_DARK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (dark_exp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) dark_exp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) very_dark_exp = dark_exp / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) old_exposure = sd->params.exposure.coarseExpHi * 256 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) sd->params.exposure.coarseExpLo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (!sd->params.flickerControl.disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* Flicker control on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) HIGH_COMP_102;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) bcomp += 128; /* decode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (bcomp >= max_comp && exp_acc < dark_exp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) /* dark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (exp_acc < very_dark_exp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) /* very dark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (sd->exposure_status == EXPOSURE_VERY_DARK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ++sd->exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) sd->exposure_status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) EXPOSURE_VERY_DARK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) sd->exposure_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /* just dark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (sd->exposure_status == EXPOSURE_DARK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) ++sd->exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) sd->exposure_status = EXPOSURE_DARK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) sd->exposure_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (old_exposure <= VERY_LOW_EXP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) /* very light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) ++sd->exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) sd->exposure_status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) EXPOSURE_VERY_LIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) sd->exposure_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) /* just light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (sd->exposure_status == EXPOSURE_LIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) ++sd->exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) sd->exposure_status = EXPOSURE_LIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) sd->exposure_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /* not dark or light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) sd->exposure_status = EXPOSURE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /* Flicker control off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (old_exposure >= MAX_EXP && exp_acc < dark_exp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /* dark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (exp_acc < very_dark_exp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /* very dark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (sd->exposure_status == EXPOSURE_VERY_DARK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) ++sd->exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) sd->exposure_status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) EXPOSURE_VERY_DARK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) sd->exposure_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) /* just dark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (sd->exposure_status == EXPOSURE_DARK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) ++sd->exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) sd->exposure_status = EXPOSURE_DARK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) sd->exposure_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) /* light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (old_exposure <= VERY_LOW_EXP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) /* very light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) ++sd->exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) sd->exposure_status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) EXPOSURE_VERY_LIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) sd->exposure_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* just light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (sd->exposure_status == EXPOSURE_LIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) ++sd->exposure_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) sd->exposure_status = EXPOSURE_LIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) sd->exposure_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) /* not dark or light */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) sd->exposure_status = EXPOSURE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) framerate = atomic_read(&sd->fps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (framerate > 30 || framerate < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) framerate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (!sd->params.flickerControl.disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /* Flicker control on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) sd->exposure_status == EXPOSURE_DARK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) sd->exposure_count >= DARK_TIME * framerate &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) sd->params.sensorFps.divisor < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) /* dark for too long */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) ++sd->params.sensorFps.divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) setfps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) sd->params.flickerControl.coarseJump =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) flicker_jumps[sd->mainsFreq]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) [sd->params.sensorFps.baserate]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) [sd->params.sensorFps.divisor];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) setflicker = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) new_exposure = sd->params.flickerControl.coarseJump-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) while (new_exposure < old_exposure / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) new_exposure +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) sd->params.flickerControl.coarseJump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) sd->params.exposure.coarseExpLo = new_exposure & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) sd->params.exposure.coarseExpHi = new_exposure >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) setexp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) sd->exposure_status = EXPOSURE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) gspca_dbg(gspca_dev, D_CONF, "Automatically decreasing sensor_fps\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) sd->exposure_status == EXPOSURE_LIGHT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) sd->exposure_count >= LIGHT_TIME * framerate &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) sd->params.sensorFps.divisor > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) /* light for too long */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) MAX_EXP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) --sd->params.sensorFps.divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) setfps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) sd->params.flickerControl.coarseJump =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) flicker_jumps[sd->mainsFreq]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) [sd->params.sensorFps.baserate]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) [sd->params.sensorFps.divisor];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) setflicker = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) new_exposure = sd->params.flickerControl.coarseJump-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) while (new_exposure < 2 * old_exposure &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) new_exposure +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) sd->params.flickerControl.coarseJump < max_exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) new_exposure +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) sd->params.flickerControl.coarseJump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) sd->params.exposure.coarseExpLo = new_exposure & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) sd->params.exposure.coarseExpHi = new_exposure >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) setexp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) sd->exposure_status = EXPOSURE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) gspca_dbg(gspca_dev, D_CONF, "Automatically increasing sensor_fps\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) /* Flicker control off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) sd->exposure_status == EXPOSURE_DARK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) sd->exposure_count >= DARK_TIME * framerate &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) sd->params.sensorFps.divisor < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) /* dark for too long */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) ++sd->params.sensorFps.divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) setfps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (sd->params.exposure.gain > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) --sd->params.exposure.gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) setexp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) sd->exposure_status = EXPOSURE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) gspca_dbg(gspca_dev, D_CONF, "Automatically decreasing sensor_fps\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) sd->exposure_status == EXPOSURE_LIGHT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) sd->exposure_count >= LIGHT_TIME * framerate &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) sd->params.sensorFps.divisor > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) /* light for too long */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) --sd->params.sensorFps.divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) setfps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (sd->params.exposure.gain <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) sd->params.exposure.gainMode - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) ++sd->params.exposure.gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) setexp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) sd->exposure_status = EXPOSURE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) gspca_dbg(gspca_dev, D_CONF, "Automatically increasing sensor_fps\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (setexp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) command_setexposure(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) if (setfps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) command_setsensorfps(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (setflicker)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) command_setflickerctrl(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) /*-----------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* if flicker is switched off, this function switches it back on.It checks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) however, that conditions are suitable before restarting it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) This should only be called for firmware version 1.2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) It also adjust the colour balance when an exposure step is detected - as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) long as flicker is running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) static void restart_flicker(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) int cam_exposure, old_exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (!FIRMWARE_VERSION(1, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) cam_exposure = atomic_read(&sd->cam_exposure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) if (sd->params.flickerControl.flickerMode == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) cam_exposure == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) old_exp = sd->params.exposure.coarseExpLo +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) sd->params.exposure.coarseExpHi*256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) see how far away camera exposure is from a valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) flicker exposure value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) cam_exposure %= sd->params.flickerControl.coarseJump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (!sd->params.flickerControl.disabled &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) cam_exposure <= sd->params.flickerControl.coarseJump - 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) /* Flicker control auto-disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) sd->params.flickerControl.disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (sd->params.flickerControl.disabled &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) old_exp > sd->params.flickerControl.coarseJump +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) ROUND_UP_EXP_FOR_FLICKER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) /* exposure is now high enough to switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) flicker control back on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) set_flicker(gspca_dev, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) /* this function is called at probe time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) static int sd_config(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) struct cam *cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) reset_camera_params(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) gspca_dbg(gspca_dev, D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) id->idVendor, id->idProduct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) cam = &gspca_dev->cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) cam->cam_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) cam->nmodes = ARRAY_SIZE(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) goto_low_power(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) /* Check the firmware version. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) sd->params.version.firmwareVersion = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) get_version_information(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (sd->params.version.firmwareVersion != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) gspca_err(gspca_dev, "only firmware version 1 is supported (got: %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) sd->params.version.firmwareVersion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) /* A bug in firmware 1-02 limits gainMode to 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if (sd->params.version.firmwareRevision <= 2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) sd->params.exposure.gainMode > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) sd->params.exposure.gainMode = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) /* set QX3 detected flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) sd->params.pnpID.product == 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) /* -- start the camera -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) static int sd_start(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) int priv, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) /* Start the camera in low power mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (goto_low_power(gspca_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (sd->params.status.systemState != WARM_BOOT_STATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) gspca_err(gspca_dev, "unexpected systemstate: %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) sd->params.status.systemState);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) printstatus(gspca_dev, &sd->params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) /* FIXME: this is just dirty trial and error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) ret = goto_high_power(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) ret = goto_low_power(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) /* procedure described in developer's guide p3-28 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) /* Check the firmware version. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) sd->params.version.firmwareVersion = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) get_version_information(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) /* The fatal error checking should be done after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) * the camera powers up (developer's guide p 3-38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) /* Set streamState before transition to high power to avoid bug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) * in firmware 1-02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) STREAMSTATE, 0, STREAM_NOT_READY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) /* GotoHiPower */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) ret = goto_high_power(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) /* Check the camera status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) if (sd->params.status.fatalError) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) gspca_err(gspca_dev, "fatal_error: %04x, vp_status: %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) sd->params.status.fatalError,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) sd->params.status.vpStatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /* VPVersion can't be retrieved before the camera is in HiPower,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * so get it here instead of in get_version_information. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) /* Determine video mode settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) sd->params.streamStartLine = 120;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) if (priv & 0x01) { /* crop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) sd->params.roi.colStart = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) sd->params.roi.rowStart = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) sd->params.roi.colStart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) sd->params.roi.rowStart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) if (priv & 0x02) { /* quarter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) sd->params.format.videoSize = VIDEOSIZE_QCIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) sd->params.roi.colStart /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) sd->params.roi.rowStart /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) sd->params.streamStartLine /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) sd->params.format.videoSize = VIDEOSIZE_CIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) sd->params.roi.colEnd = sd->params.roi.colStart +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) (gspca_dev->pixfmt.width >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) sd->params.roi.rowEnd = sd->params.roi.rowStart +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) (gspca_dev->pixfmt.height >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) /* And now set the camera to a known state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) CPIA_GRAB_CONTINEOUS, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) /* We start with compression disabled, as we need one uncompressed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) frame to handle later compressed frames */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) CPIA_COMPRESSION_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) NO_DECIMATION, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) ret = command_setcompressiontarget(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) ret = command_setcolourparams(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) ret = command_setformat(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) ret = command_setyuvtresh(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) ret = command_setecptiming(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) ret = command_setcompressionparams(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) ret = command_setexposure(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) ret = command_setcolourbalance(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) ret = command_setsensorfps(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) ret = command_setapcor(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) ret = command_setflickerctrl(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) ret = command_setvloffset(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) /* Start stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) ret = command_resume(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) /* Wait 6 frames before turning compression on for the sensor to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) all settings and AEC/ACB to settle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) sd->first_frame = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) sd->exposure_status = EXPOSURE_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) sd->exposure_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) atomic_set(&sd->cam_exposure, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) atomic_set(&sd->fps, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) static void sd_stopN(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) struct sd *sd __maybe_unused = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) command_pause(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) /* save camera state for later open (developers guide ch 3.5.3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) save_camera_state(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) /* GotoLoPower */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) goto_low_power(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) /* Update the camera status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) #if IS_ENABLED(CONFIG_INPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) /* If the last button state is pressed, release it now! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (sd->params.qx3.button) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) /* The camera latch will hold the pressed state until we reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) the latch, so we do not reset sd->params.qx3.button now, to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) avoid a false keypress being reported the next sd_start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) input_sync(gspca_dev->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) /* this function is called at probe and resume time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) static int sd_init(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) /* Start / Stop the camera to make sure we are talking to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) a supported camera, and to get some information from it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) to print. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) ret = sd_start(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /* Ensure the QX3 illuminators' states are restored upon resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) or disable the illuminator controls, if this isn't a QX3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) if (sd->params.qx3.qx3_detected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) command_setlights(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) sd_stopN(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) gspca_dbg(gspca_dev, D_PROBE, "CPIA Version: %d.%02d (%d.%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) sd->params.version.firmwareVersion,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) sd->params.version.firmwareRevision,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) sd->params.version.vcVersion,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) sd->params.version.vcRevision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) gspca_dbg(gspca_dev, D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) sd->params.pnpID.vendor, sd->params.pnpID.product,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) sd->params.pnpID.deviceRevision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) gspca_dbg(gspca_dev, D_PROBE, "VP-Version: %d.%d %04x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) sd->params.vpVersion.vpVersion,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) sd->params.vpVersion.vpRevision,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) sd->params.vpVersion.cameraHeadID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) static void sd_pkt_scan(struct gspca_dev *gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) /* Check for SOF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) if (len >= 64 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) data[0] == MAGIC_0 && data[1] == MAGIC_1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) data[16] == sd->params.format.videoSize &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) data[17] == sd->params.format.subSample &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) data[18] == sd->params.format.yuvOrder &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) data[24] == sd->params.roi.colStart &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) data[25] == sd->params.roi.colEnd &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) data[26] == sd->params.roi.rowStart &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) data[27] == sd->params.roi.rowEnd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) u8 *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) atomic_set(&sd->cam_exposure, data[39] * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) atomic_set(&sd->fps, data[41]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) /* Check for proper EOF for last frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) image = gspca_dev->image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) if (image != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) gspca_dev->image_len > 4 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) image[gspca_dev->image_len - 4] == 0xff &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) image[gspca_dev->image_len - 3] == 0xff &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) image[gspca_dev->image_len - 2] == 0xff &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) image[gspca_dev->image_len - 1] == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) gspca_frame_add(gspca_dev, LAST_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) static void sd_dq_callback(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) struct sd *sd = (struct sd *) gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) /* Set the normal compression settings once we have captured a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) few uncompressed frames (and AEC has hopefully settled) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) if (sd->first_frame) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) sd->first_frame--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) if (sd->first_frame == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) command_setcompression(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) /* Switch flicker control back on if it got turned off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) restart_flicker(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) /* If AEC is enabled, monitor the exposure and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) adjust the sensor frame rate if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (sd->params.exposure.expMode == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) monitor_exposure(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) /* Update our knowledge of the camera state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) struct gspca_dev *gspca_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) gspca_dev->usb_err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) if (!gspca_dev->streaming && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) sd->params.colourParams.brightness = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) sd->params.flickerControl.allowableOverExposure =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) find_over_exposure(sd->params.colourParams.brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) gspca_dev->usb_err = command_setcolourparams(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) if (!gspca_dev->usb_err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) gspca_dev->usb_err = command_setflickerctrl(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) sd->params.colourParams.contrast = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) gspca_dev->usb_err = command_setcolourparams(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) sd->params.colourParams.saturation = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) gspca_dev->usb_err = command_setcolourparams(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) case V4L2_CID_POWER_LINE_FREQUENCY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) sd->mainsFreq = ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) sd->params.flickerControl.coarseJump =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) flicker_jumps[sd->mainsFreq]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) [sd->params.sensorFps.baserate]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) [sd->params.sensorFps.divisor];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) gspca_dev->usb_err = set_flicker(gspca_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) ctrl->val != V4L2_CID_POWER_LINE_FREQUENCY_DISABLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) gspca_dev->streaming);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) case V4L2_CID_ILLUMINATORS_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) sd->params.qx3.bottomlight = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) gspca_dev->usb_err = command_setlights(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) case V4L2_CID_ILLUMINATORS_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) sd->params.qx3.toplight = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) gspca_dev->usb_err = command_setlights(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) case CPIA1_CID_COMP_TARGET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) sd->params.compressionTarget.frTargeting = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) gspca_dev->usb_err = command_setcompressiontarget(gspca_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) return gspca_dev->usb_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) static const struct v4l2_ctrl_ops sd_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) .s_ctrl = sd_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) static int sd_init_controls(struct gspca_dev *gspca_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) struct sd *sd = (struct sd *)gspca_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) static const char * const comp_target_menu[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) "Quality",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) "Framerate",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) static const struct v4l2_ctrl_config comp_target = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) .ops = &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) .id = CPIA1_CID_COMP_TARGET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) .type = V4L2_CTRL_TYPE_MENU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) .name = "Compression Target",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) .qmenu = comp_target_menu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) .max = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) .def = COMP_TARGET_DEF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) gspca_dev->vdev.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) v4l2_ctrl_handler_init(hdl, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) V4L2_CID_BRIGHTNESS, 0, 100, 1, BRIGHTNESS_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) V4L2_CID_CONTRAST, 0, 96, 8, CONTRAST_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) V4L2_CID_SATURATION, 0, 100, 1, SATURATION_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) V4L2_CID_POWER_LINE_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) FREQ_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (sd->params.qx3.qx3_detected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) V4L2_CID_ILLUMINATORS_1, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) ILLUMINATORS_1_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) V4L2_CID_ILLUMINATORS_2, 0, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) ILLUMINATORS_2_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) v4l2_ctrl_new_custom(hdl, &comp_target, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) pr_err("Could not initialize controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) /* sub-driver description */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) static const struct sd_desc sd_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) .config = sd_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) .init = sd_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) .init_controls = sd_init_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) .start = sd_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) .stopN = sd_stopN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) .dq_callback = sd_dq_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) .pkt_scan = sd_pkt_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) #if IS_ENABLED(CONFIG_INPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) .other_input = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) /* -- module initialisation -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) static const struct usb_device_id device_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) {USB_DEVICE(0x0553, 0x0002)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) {USB_DEVICE(0x0813, 0x0001)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) MODULE_DEVICE_TABLE(usb, device_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) /* -- device connect -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) static int sd_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) static struct usb_driver sd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) .name = MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) .id_table = device_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) .probe = sd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) .disconnect = gspca_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) .suspend = gspca_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) .resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) .reset_resume = gspca_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) module_usb_driver(sd_driver);