// SPDX-License-Identifier: GPL-2.0-or-later /* * sonix sn9c102 (bayer) library * * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr> * Copyright (C) 2003 2004 Michel Xhaard [email protected] * Add Pas106 Stefano Mozzi (C) 2004 */ /* Some documentation on known sonixb registers: Reg Use sn9c101 / sn9c102: 0x10 high nibble red gain low nibble blue gain 0x11 low nibble green gain sn9c103: 0x05 red gain 0-127 0x06 blue gain 0-127 0x07 green gain 0-127 all: 0x08-0x0f i2c / 3wire registers 0x12 hstart 0x13 vstart 0x15 hsize (hsize = register-value * 16) 0x16 vsize (vsize = register-value * 16) 0x17 bit 0 toggle compression quality (according to sn9c102 driver) 0x18 bit 7 enables compression, bit 4-5 set image down scaling: 00 scale 1, 01 scale 1/2, 10, scale 1/4 0x19 high-nibble is sensor clock divider, changes exposure on sensors which use a clock generated by the bridge. Some sensors have their own clock. 0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32) 0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32) 0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32) 0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32) */ #define MODULE_NAME … #include <linux/input.h> #include "gspca.h" MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; /* specific webcam descriptor */ struct sd { … }; sensor_init_t; struct sensor_data { … }; /* sensor_data flags */ #define F_SIF … /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ #define MODE_RAW … #define MODE_REDUCED_SIF … #define COMP … #define COMP1 … #define MCK_INIT … #define MCK_INIT1 … #define SYS_CLK … #define SENS(bridge, sensor, _flags, _sensor_addr) … /* We calculate the autogain at the end of the transfer of a frame, at this moment a frame with the old settings is being captured and transmitted. So if we adjust the gain or exposure we must ignore at least the next frame for the new settings to come into effect before doing any other adjustments. */ #define AUTOGAIN_IGNORE_FRAMES … static const struct v4l2_pix_format vga_mode[] = …; static const struct v4l2_pix_format sif_mode[] = …; static const __u8 initHv7131d[] = …; static const __u8 hv7131d_sensor_init[][8] = …; static const __u8 initHv7131r[] = …; static const __u8 hv7131r_sensor_init[][8] = …; static const __u8 initOv6650[] = …; static const __u8 ov6650_sensor_init[][8] = …; static const __u8 initOv7630[] = …; static const __u8 ov7630_sensor_init[][8] = …; static const __u8 initPas106[] = …; /* compression 0x86 mckinit1 0x2b */ /* "Known" PAS106B registers: 0x02 clock divider 0x03 Variable framerate bits 4-11 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !! The variable framerate control must never be set lower then 300, which sets the framerate at 90 / reg02, otherwise vsync is lost. 0x05 Shutter Time Line Offset, this can be used as an exposure control: 0 = use full frame time, 255 = no exposure at all Note this may never be larger then "var-framerate control" / 2 - 2. When var-framerate control is < 514, no exposure is reached at the max allowed value for the framerate control value, rather then at 255. 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but only a very little bit, leave at 0xcd 0x07 offset sign bit (bit0 1 > negative offset) 0x08 offset 0x09 Blue Gain 0x0a Green1 Gain 0x0b Green2 Gain 0x0c Red Gain 0x0e Global gain 0x13 Write 1 to commit settings to sensor */ static const __u8 pas106_sensor_init[][8] = …; static const __u8 initPas202[] = …; /* "Known" PAS202BCB registers: 0x02 clock divider 0x04 Variable framerate bits 6-11 (*) 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !! 0x07 Blue Gain 0x08 Green Gain 0x09 Red Gain 0x0b offset sign bit (bit0 1 > negative offset) 0x0c offset 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too, leave at 1 otherwise we get a jump in our exposure control 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all 0x10 Master gain 0 - 31 0x11 write 1 to apply changes (*) The variable framerate control must never be set lower then 500 which sets the framerate at 30 / reg02, otherwise vsync is lost. */ static const __u8 pas202_sensor_init[][8] = …; static const __u8 initTas5110c[] = …; /* Same as above, except a different hstart */ static const __u8 initTas5110d[] = …; /* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */ static const __u8 tas5110c_sensor_init[][8] = …; /* Known TAS5110D registers * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted) * Note: writing reg03 seems to only work when written together with 02 */ static const __u8 tas5110d_sensor_init[][8] = …; static const __u8 initTas5130[] = …; static const __u8 tas5130_sensor_init[][8] = …; static const struct sensor_data sensor_data[] = …; /* get one byte in gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, __u16 value) { … } static void reg_w(struct gspca_dev *gspca_dev, __u16 value, const __u8 *buffer, int len) { … } static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf) { … } static void i2c_w_vector(struct gspca_dev *gspca_dev, const __u8 buffer[][8], int len) { … } static void setbrightness(struct gspca_dev *gspca_dev) { … } static void setgain(struct gspca_dev *gspca_dev) { … } static void setexposure(struct gspca_dev *gspca_dev) { … } static void setfreq(struct gspca_dev *gspca_dev) { … } static void do_autogain(struct gspca_dev *gspca_dev) { … } /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { … } /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { … } static int sd_s_ctrl(struct v4l2_ctrl *ctrl) { … } static const struct v4l2_ctrl_ops sd_ctrl_ops = …; /* this function is called at probe time */ static int sd_init_controls(struct gspca_dev *gspca_dev) { … } /* -- start the camera -- */ static int sd_start(struct gspca_dev *gspca_dev) { … } static void sd_stopN(struct gspca_dev *gspca_dev) { … } static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) { … } static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* isoc packet */ int len) /* iso packet length */ { … } #if IS_ENABLED(CONFIG_INPUT) static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* interrupt packet data */ int len) /* interrupt packet length */ { … } #endif /* sub-driver description */ static const struct sd_desc sd_desc = …; /* -- module initialisation -- */ #define SB(sensor, bridge) … static const struct usb_device_id device_table[] = …; MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { … } static struct usb_driver sd_driver = …; module_usb_driver(…) …;