// SPDX-License-Identifier: GPL-2.0-or-later /* * Pixart PAC7311 library * Copyright (C) 2005 Thomas Kaiser [email protected] * * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> */ /* Some documentation about various registers as determined by trial and error. * * Register page 1: * * Address Description * 0x08 Unknown compressor related, must always be 8 except when not * in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! * 0x1b Auto white balance related, bit 0 is AWB enable (inverted) * bits 345 seem to toggle per color gains on/off (inverted) * 0x78 Global control, bit 6 controls the LED (inverted) * 0x80 Compression balance, interesting settings: * 0x01 Use this to allow the camera to switch to higher compr. * on the fly. Needed to stay within bandwidth @ 640x480@30 * 0x1c From usb captures under Windows for 640x480 * 0x2a Values >= this switch the camera to a lower compression, * using the same table for both luminance and chrominance. * This gives a sharper picture. Usable only at 640x480@ < * 15 fps or 320x240 / 160x120. Note currently the driver * does not use this as the quality gain is small and the * generated JPG-s are only understood by v4l-utils >= 0.8.9 * 0x3f From usb captures under Windows for 320x240 * 0x69 From usb captures under Windows for 160x120 * * Register page 4: * * Address Description * 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? * 0x0f Master gain 1-245, low value = high gain * 0x10 Another gain 0-15, limited influence (1-2x gain I guess) * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused * Note setting vflip disabled leads to a much lower image quality, * so we always vflip, and tell userspace to flip it back * 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to * completely disable the analog amplification block. Set to 0x68 * for max gain, 0x14 for minimal gain. */ #define pr_fmt(fmt) … #define MODULE_NAME … #include <linux/input.h> #include "gspca.h" /* Include pac common sof detection functions */ #include "pac_common.h" #define PAC7311_GAIN_DEFAULT … #define PAC7311_EXPOSURE_DEFAULT … MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; struct sd { … }; static const struct v4l2_pix_format vga_mode[] = …; #define LOAD_PAGE4 … #define END_OF_SEQUENCE … static const __u8 init_7311[] = …; static const __u8 start_7311[] = …; #define SKIP … /* page 4 - the value SKIP says skip the index - see reg_w_page() */ static const __u8 page4_7311[] = …; static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, const u8 *buffer, int len) { … } static void reg_w(struct gspca_dev *gspca_dev, __u8 index, __u8 value) { … } static void reg_w_seq(struct gspca_dev *gspca_dev, const __u8 *seq, int len) { … } /* load the beginning of a page */ static void reg_w_page(struct gspca_dev *gspca_dev, const __u8 *page, int len) { … } /* output a variable sequence */ static void reg_w_var(struct gspca_dev *gspca_dev, const __u8 *seq, const __u8 *page4, unsigned int page4_len) { … } /* this function is called at probe time for pac7311 */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { … } static void setcontrast(struct gspca_dev *gspca_dev, s32 val) { … } static void setgain(struct gspca_dev *gspca_dev, s32 val) { … } static void setexposure(struct gspca_dev *gspca_dev, s32 val) { … } static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) { … } /* this function is called at probe and resume time for pac7311 */ 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 void do_autogain(struct gspca_dev *gspca_dev) { … } /* JPEG header, part 1 */ static const unsigned char pac_jpeg_header1[] = …; /* JPEG header, continued */ static const unsigned char pac_jpeg_header2[] = …; static void pac_start_frame(struct gspca_dev *gspca_dev, __u16 lines, __u16 samples_per_line) { … } /* this function is run at interrupt level */ 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 static const struct sd_desc sd_desc = …; /* -- module initialisation -- */ 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(…) …;