// SPDX-License-Identifier: GPL-2.0-or-later /* * Pixart PAC7302 driver * * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr> * Copyright (C) 2005 Thomas Kaiser [email protected] * * Separated from Pixart PAC7311 library by Márton Németh * Camera button input handling by Márton Németh <[email protected]> * Copyright (C) 2009-2010 Márton Németh <[email protected]> */ /* * Some documentation about various registers as determined by trial and error. * * Register page 0: * * Address Description * 0x01 Red balance control * 0x02 Green balance control * 0x03 Blue balance control * The Windows driver uses a quadratic approach to map * the settable values (0-200) on register values: * min=0x20, default=0x40, max=0x80 * 0x0f-0x20 Color and saturation control * 0xa2-0xab Brightness, contrast and gamma control * 0xb6 Sharpness control (bits 0-4) * * Register page 1: * * Address Description * 0x78 Global control, bit 6 controls the LED (inverted) * 0x80 Compression balance, 2 interesting settings: * 0x0f Default * 0x50 Values >= this switch the camera to a lower compression, * using the same table for both luminance and chrominance. * This gives a sharper picture. Only usable when running * at < 15 fps! 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 * * Register page 3: * * Address Description * 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? * 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps * 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps, * 63 -> ~27 fps, the 2 msb's must always be 1 !! * 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0: * 1 -> ~30 fps, 2 -> ~20 fps * 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time * 0x0f Exposure bit 8, 0-448, 448 = no exposure at all * 0x10 Gain 0-31 * 0x12 Another gain 0-31, unlike 0x10 this one seems to start with an * amplification value of 1 rather then 0 at its lowest setting * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused * 0x80 Another framerate control, best left at 1, moving it from 1 to * 2 causes the framerate to become 3/4th of what it was, and * also seems to cause pixel averaging, resulting in an effective * resolution of 320x240 and thus a much blockier image * * The registers are accessed in the following functions: * * Page | Register | Function * -----+------------+--------------------------------------------------- * 0 | 0x01 | setredbalance() * 0 | 0x03 | setbluebalance() * 0 | 0x0f..0x20 | setcolors() * 0 | 0xa2..0xab | setbrightcont() * 0 | 0xb6 | setsharpness() * 0 | 0xc6 | setwhitebalance() * 0 | 0xdc | setbrightcont(), setcolors() * 3 | 0x02 | setexposure() * 3 | 0x10, 0x12 | setgain() * 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip() * 3 | 0x21 | sethvflip() */ #define pr_fmt(fmt) … #include <linux/input.h> #include "gspca.h" /* Include pac common sof detection functions */ #include "pac_common.h" #define PAC7302_RGB_BALANCE_MIN … #define PAC7302_RGB_BALANCE_MAX … #define PAC7302_RGB_BALANCE_DEFAULT … #define PAC7302_GAIN_DEFAULT … #define PAC7302_GAIN_KNEE … #define PAC7302_EXPOSURE_DEFAULT … #define PAC7302_EXPOSURE_KNEE … MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; struct sd { … }; static const struct v4l2_pix_format vga_mode[] = …; #define LOAD_PAGE3 … #define END_OF_SEQUENCE … static const u8 init_7302[] = …; static const u8 start_7302[] = …; #define SKIP … /* page 3 - the value SKIP says skip the index - see reg_w_page() */ static const u8 page3_7302[] = …; 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 *page3, unsigned int page3_len) { … } /* this function is called at probe time for pac7302 */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { … } static void setbrightcont(struct gspca_dev *gspca_dev) { … } static void setcolors(struct gspca_dev *gspca_dev) { … } static void setwhitebalance(struct gspca_dev *gspca_dev) { … } static u8 rgbbalance_ctrl_to_reg_value(s32 rgb_ctrl_val) { … } static void setredbalance(struct gspca_dev *gspca_dev) { … } static void setbluebalance(struct gspca_dev *gspca_dev) { … } static void setgain(struct gspca_dev *gspca_dev) { … } static void setexposure(struct gspca_dev *gspca_dev) { … } static void sethvflip(struct gspca_dev *gspca_dev) { … } static void setsharpness(struct gspca_dev *gspca_dev) { … } /* this function is called at probe and resume time for pac7302 */ 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) { … } /* called on streamoff with alt 0 and on disconnect for pac7302 */ static void sd_stop0(struct gspca_dev *gspca_dev) { … } static void do_autogain(struct gspca_dev *gspca_dev) { … } /* JPEG header */ static const u8 jpeg_header[] = …; /* 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 */ { … } #ifdef CONFIG_VIDEO_ADV_DEBUG static int sd_dbg_s_register(struct gspca_dev *gspca_dev, const struct v4l2_dbg_register *reg) { … } #endif #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 for pac7302 */ 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(…) …;