162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Sonix sn9c201 sn9c202 library 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr> 662306a36Sopenharmony_ci * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com> 762306a36Sopenharmony_ci * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/input.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "gspca.h" 1562306a36Sopenharmony_ci#include "jpeg.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/dmi.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciMODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, microdia project <microdia@googlegroups.com>"); 2062306a36Sopenharmony_ciMODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver"); 2162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* 2462306a36Sopenharmony_ci * Pixel format private data 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci#define SCALE_MASK 0x0f 2762306a36Sopenharmony_ci#define SCALE_160x120 0 2862306a36Sopenharmony_ci#define SCALE_320x240 1 2962306a36Sopenharmony_ci#define SCALE_640x480 2 3062306a36Sopenharmony_ci#define SCALE_1280x1024 3 3162306a36Sopenharmony_ci#define MODE_RAW 0x10 3262306a36Sopenharmony_ci#define MODE_JPEG 0x20 3362306a36Sopenharmony_ci#define MODE_SXGA 0x80 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define SENSOR_OV9650 0 3662306a36Sopenharmony_ci#define SENSOR_OV9655 1 3762306a36Sopenharmony_ci#define SENSOR_SOI968 2 3862306a36Sopenharmony_ci#define SENSOR_OV7660 3 3962306a36Sopenharmony_ci#define SENSOR_OV7670 4 4062306a36Sopenharmony_ci#define SENSOR_MT9V011 5 4162306a36Sopenharmony_ci#define SENSOR_MT9V111 6 4262306a36Sopenharmony_ci#define SENSOR_MT9V112 7 4362306a36Sopenharmony_ci#define SENSOR_MT9M001 8 4462306a36Sopenharmony_ci#define SENSOR_MT9M111 9 4562306a36Sopenharmony_ci#define SENSOR_MT9M112 10 4662306a36Sopenharmony_ci#define SENSOR_HV7131R 11 4762306a36Sopenharmony_ci#define SENSOR_MT9VPRB 12 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* camera flags */ 5062306a36Sopenharmony_ci#define HAS_NO_BUTTON 0x1 5162306a36Sopenharmony_ci#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ 5262306a36Sopenharmony_ci#define FLIP_DETECT 0x4 5362306a36Sopenharmony_ci#define HAS_LED_TORCH 0x8 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* specific webcam descriptor */ 5662306a36Sopenharmony_cistruct sd { 5762306a36Sopenharmony_ci struct gspca_dev gspca_dev; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci struct { /* color control cluster */ 6062306a36Sopenharmony_ci struct v4l2_ctrl *brightness; 6162306a36Sopenharmony_ci struct v4l2_ctrl *contrast; 6262306a36Sopenharmony_ci struct v4l2_ctrl *saturation; 6362306a36Sopenharmony_ci struct v4l2_ctrl *hue; 6462306a36Sopenharmony_ci }; 6562306a36Sopenharmony_ci struct { /* blue/red balance control cluster */ 6662306a36Sopenharmony_ci struct v4l2_ctrl *blue; 6762306a36Sopenharmony_ci struct v4l2_ctrl *red; 6862306a36Sopenharmony_ci }; 6962306a36Sopenharmony_ci struct { /* h/vflip control cluster */ 7062306a36Sopenharmony_ci struct v4l2_ctrl *hflip; 7162306a36Sopenharmony_ci struct v4l2_ctrl *vflip; 7262306a36Sopenharmony_ci }; 7362306a36Sopenharmony_ci struct v4l2_ctrl *gamma; 7462306a36Sopenharmony_ci struct { /* autogain and exposure or gain control cluster */ 7562306a36Sopenharmony_ci struct v4l2_ctrl *autogain; 7662306a36Sopenharmony_ci struct v4l2_ctrl *exposure; 7762306a36Sopenharmony_ci struct v4l2_ctrl *gain; 7862306a36Sopenharmony_ci }; 7962306a36Sopenharmony_ci struct v4l2_ctrl *jpegqual; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci struct v4l2_ctrl *led_mode; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci struct work_struct work; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci u32 pktsz; /* (used by pkt_scan) */ 8662306a36Sopenharmony_ci u16 npkt; 8762306a36Sopenharmony_ci s8 nchg; 8862306a36Sopenharmony_ci u8 fmt; /* (used for JPEG QTAB update */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci#define MIN_AVG_LUM 80 9162306a36Sopenharmony_ci#define MAX_AVG_LUM 130 9262306a36Sopenharmony_ci atomic_t avg_lum; 9362306a36Sopenharmony_ci u8 old_step; 9462306a36Sopenharmony_ci u8 older_step; 9562306a36Sopenharmony_ci u8 exposure_step; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci u8 i2c_addr; 9862306a36Sopenharmony_ci u8 i2c_intf; 9962306a36Sopenharmony_ci u8 sensor; 10062306a36Sopenharmony_ci u8 hstart; 10162306a36Sopenharmony_ci u8 vstart; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci u8 jpeg_hdr[JPEG_HDR_SZ]; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci u8 flags; 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic void qual_upd(struct work_struct *work); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistruct i2c_reg_u8 { 11162306a36Sopenharmony_ci u8 reg; 11262306a36Sopenharmony_ci u8 val; 11362306a36Sopenharmony_ci}; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistruct i2c_reg_u16 { 11662306a36Sopenharmony_ci u8 reg; 11762306a36Sopenharmony_ci u16 val; 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic const struct dmi_system_id flip_dmi_table[] = { 12162306a36Sopenharmony_ci { 12262306a36Sopenharmony_ci .ident = "MSI MS-1034", 12362306a36Sopenharmony_ci .matches = { 12462306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."), 12562306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"), 12662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_VERSION, "0341") 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci }, 12962306a36Sopenharmony_ci { 13062306a36Sopenharmony_ci .ident = "MSI MS-1039", 13162306a36Sopenharmony_ci .matches = { 13262306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."), 13362306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "MS-1039"), 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci }, 13662306a36Sopenharmony_ci { 13762306a36Sopenharmony_ci .ident = "MSI MS-1632", 13862306a36Sopenharmony_ci .matches = { 13962306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), 14062306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "MS-1632") 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci }, 14362306a36Sopenharmony_ci { 14462306a36Sopenharmony_ci .ident = "MSI MS-1633X", 14562306a36Sopenharmony_ci .matches = { 14662306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), 14762306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "MS-1633X") 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci }, 15062306a36Sopenharmony_ci { 15162306a36Sopenharmony_ci .ident = "MSI MS-1635X", 15262306a36Sopenharmony_ci .matches = { 15362306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), 15462306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "MS-1635X") 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci }, 15762306a36Sopenharmony_ci { 15862306a36Sopenharmony_ci .ident = "ASUSTeK W7J", 15962306a36Sopenharmony_ci .matches = { 16062306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), 16162306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "W7J ") 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci }, 16462306a36Sopenharmony_ci {} 16562306a36Sopenharmony_ci}; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = { 16862306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 16962306a36Sopenharmony_ci .bytesperline = 160, 17062306a36Sopenharmony_ci .sizeimage = 160 * 120 * 4 / 8 + 590, 17162306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 17262306a36Sopenharmony_ci .priv = SCALE_160x120 | MODE_JPEG}, 17362306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 17462306a36Sopenharmony_ci .bytesperline = 160, 17562306a36Sopenharmony_ci .sizeimage = 160 * 120, 17662306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 17762306a36Sopenharmony_ci .priv = SCALE_160x120 | MODE_RAW}, 17862306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 17962306a36Sopenharmony_ci .bytesperline = 160, 18062306a36Sopenharmony_ci .sizeimage = 240 * 120, 18162306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 18262306a36Sopenharmony_ci .priv = SCALE_160x120}, 18362306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 18462306a36Sopenharmony_ci .bytesperline = 320, 18562306a36Sopenharmony_ci .sizeimage = 320 * 240 * 4 / 8 + 590, 18662306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 18762306a36Sopenharmony_ci .priv = SCALE_320x240 | MODE_JPEG}, 18862306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 18962306a36Sopenharmony_ci .bytesperline = 320, 19062306a36Sopenharmony_ci .sizeimage = 320 * 240 , 19162306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 19262306a36Sopenharmony_ci .priv = SCALE_320x240 | MODE_RAW}, 19362306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 19462306a36Sopenharmony_ci .bytesperline = 320, 19562306a36Sopenharmony_ci .sizeimage = 480 * 240 , 19662306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 19762306a36Sopenharmony_ci .priv = SCALE_320x240}, 19862306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 19962306a36Sopenharmony_ci .bytesperline = 640, 20062306a36Sopenharmony_ci .sizeimage = 640 * 480 * 4 / 8 + 590, 20162306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 20262306a36Sopenharmony_ci .priv = SCALE_640x480 | MODE_JPEG}, 20362306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 20462306a36Sopenharmony_ci .bytesperline = 640, 20562306a36Sopenharmony_ci .sizeimage = 640 * 480, 20662306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 20762306a36Sopenharmony_ci .priv = SCALE_640x480 | MODE_RAW}, 20862306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 20962306a36Sopenharmony_ci .bytesperline = 640, 21062306a36Sopenharmony_ci .sizeimage = 960 * 480, 21162306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 21262306a36Sopenharmony_ci .priv = SCALE_640x480}, 21362306a36Sopenharmony_ci}; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic const struct v4l2_pix_format sxga_mode[] = { 21662306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 21762306a36Sopenharmony_ci .bytesperline = 160, 21862306a36Sopenharmony_ci .sizeimage = 160 * 120 * 4 / 8 + 590, 21962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 22062306a36Sopenharmony_ci .priv = SCALE_160x120 | MODE_JPEG}, 22162306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 22262306a36Sopenharmony_ci .bytesperline = 160, 22362306a36Sopenharmony_ci .sizeimage = 160 * 120, 22462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 22562306a36Sopenharmony_ci .priv = SCALE_160x120 | MODE_RAW}, 22662306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 22762306a36Sopenharmony_ci .bytesperline = 160, 22862306a36Sopenharmony_ci .sizeimage = 240 * 120, 22962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 23062306a36Sopenharmony_ci .priv = SCALE_160x120}, 23162306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 23262306a36Sopenharmony_ci .bytesperline = 320, 23362306a36Sopenharmony_ci .sizeimage = 320 * 240 * 4 / 8 + 590, 23462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 23562306a36Sopenharmony_ci .priv = SCALE_320x240 | MODE_JPEG}, 23662306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 23762306a36Sopenharmony_ci .bytesperline = 320, 23862306a36Sopenharmony_ci .sizeimage = 320 * 240 , 23962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 24062306a36Sopenharmony_ci .priv = SCALE_320x240 | MODE_RAW}, 24162306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 24262306a36Sopenharmony_ci .bytesperline = 320, 24362306a36Sopenharmony_ci .sizeimage = 480 * 240 , 24462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 24562306a36Sopenharmony_ci .priv = SCALE_320x240}, 24662306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 24762306a36Sopenharmony_ci .bytesperline = 640, 24862306a36Sopenharmony_ci .sizeimage = 640 * 480 * 4 / 8 + 590, 24962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 25062306a36Sopenharmony_ci .priv = SCALE_640x480 | MODE_JPEG}, 25162306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 25262306a36Sopenharmony_ci .bytesperline = 640, 25362306a36Sopenharmony_ci .sizeimage = 640 * 480, 25462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 25562306a36Sopenharmony_ci .priv = SCALE_640x480 | MODE_RAW}, 25662306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 25762306a36Sopenharmony_ci .bytesperline = 640, 25862306a36Sopenharmony_ci .sizeimage = 960 * 480, 25962306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 26062306a36Sopenharmony_ci .priv = SCALE_640x480}, 26162306a36Sopenharmony_ci {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 26262306a36Sopenharmony_ci .bytesperline = 1280, 26362306a36Sopenharmony_ci .sizeimage = 1280 * 1024, 26462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 26562306a36Sopenharmony_ci .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, 26662306a36Sopenharmony_ci}; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic const struct v4l2_pix_format mono_mode[] = { 26962306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, 27062306a36Sopenharmony_ci .bytesperline = 160, 27162306a36Sopenharmony_ci .sizeimage = 160 * 120, 27262306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 27362306a36Sopenharmony_ci .priv = SCALE_160x120 | MODE_RAW}, 27462306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, 27562306a36Sopenharmony_ci .bytesperline = 320, 27662306a36Sopenharmony_ci .sizeimage = 320 * 240 , 27762306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 27862306a36Sopenharmony_ci .priv = SCALE_320x240 | MODE_RAW}, 27962306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, 28062306a36Sopenharmony_ci .bytesperline = 640, 28162306a36Sopenharmony_ci .sizeimage = 640 * 480, 28262306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 28362306a36Sopenharmony_ci .priv = SCALE_640x480 | MODE_RAW}, 28462306a36Sopenharmony_ci {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, 28562306a36Sopenharmony_ci .bytesperline = 1280, 28662306a36Sopenharmony_ci .sizeimage = 1280 * 1024, 28762306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 28862306a36Sopenharmony_ci .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, 28962306a36Sopenharmony_ci}; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistatic const s16 hsv_red_x[] = { 29262306a36Sopenharmony_ci 41, 44, 46, 48, 50, 52, 54, 56, 29362306a36Sopenharmony_ci 58, 60, 62, 64, 66, 68, 70, 72, 29462306a36Sopenharmony_ci 74, 76, 78, 80, 81, 83, 85, 87, 29562306a36Sopenharmony_ci 88, 90, 92, 93, 95, 97, 98, 100, 29662306a36Sopenharmony_ci 101, 102, 104, 105, 107, 108, 109, 110, 29762306a36Sopenharmony_ci 112, 113, 114, 115, 116, 117, 118, 119, 29862306a36Sopenharmony_ci 120, 121, 122, 123, 123, 124, 125, 125, 29962306a36Sopenharmony_ci 126, 127, 127, 128, 128, 129, 129, 129, 30062306a36Sopenharmony_ci 130, 130, 130, 130, 131, 131, 131, 131, 30162306a36Sopenharmony_ci 131, 131, 131, 131, 130, 130, 130, 130, 30262306a36Sopenharmony_ci 129, 129, 129, 128, 128, 127, 127, 126, 30362306a36Sopenharmony_ci 125, 125, 124, 123, 122, 122, 121, 120, 30462306a36Sopenharmony_ci 119, 118, 117, 116, 115, 114, 112, 111, 30562306a36Sopenharmony_ci 110, 109, 107, 106, 105, 103, 102, 101, 30662306a36Sopenharmony_ci 99, 98, 96, 94, 93, 91, 90, 88, 30762306a36Sopenharmony_ci 86, 84, 83, 81, 79, 77, 75, 74, 30862306a36Sopenharmony_ci 72, 70, 68, 66, 64, 62, 60, 58, 30962306a36Sopenharmony_ci 56, 54, 52, 49, 47, 45, 43, 41, 31062306a36Sopenharmony_ci 39, 36, 34, 32, 30, 28, 25, 23, 31162306a36Sopenharmony_ci 21, 19, 16, 14, 12, 9, 7, 5, 31262306a36Sopenharmony_ci 3, 0, -1, -3, -6, -8, -10, -12, 31362306a36Sopenharmony_ci -15, -17, -19, -22, -24, -26, -28, -30, 31462306a36Sopenharmony_ci -33, -35, -37, -39, -41, -44, -46, -48, 31562306a36Sopenharmony_ci -50, -52, -54, -56, -58, -60, -62, -64, 31662306a36Sopenharmony_ci -66, -68, -70, -72, -74, -76, -78, -80, 31762306a36Sopenharmony_ci -81, -83, -85, -87, -88, -90, -92, -93, 31862306a36Sopenharmony_ci -95, -97, -98, -100, -101, -102, -104, -105, 31962306a36Sopenharmony_ci -107, -108, -109, -110, -112, -113, -114, -115, 32062306a36Sopenharmony_ci -116, -117, -118, -119, -120, -121, -122, -123, 32162306a36Sopenharmony_ci -123, -124, -125, -125, -126, -127, -127, -128, 32262306a36Sopenharmony_ci -128, -128, -128, -128, -128, -128, -128, -128, 32362306a36Sopenharmony_ci -128, -128, -128, -128, -128, -128, -128, -128, 32462306a36Sopenharmony_ci -128, -128, -128, -128, -128, -128, -128, -128, 32562306a36Sopenharmony_ci -128, -127, -127, -126, -125, -125, -124, -123, 32662306a36Sopenharmony_ci -122, -122, -121, -120, -119, -118, -117, -116, 32762306a36Sopenharmony_ci -115, -114, -112, -111, -110, -109, -107, -106, 32862306a36Sopenharmony_ci -105, -103, -102, -101, -99, -98, -96, -94, 32962306a36Sopenharmony_ci -93, -91, -90, -88, -86, -84, -83, -81, 33062306a36Sopenharmony_ci -79, -77, -75, -74, -72, -70, -68, -66, 33162306a36Sopenharmony_ci -64, -62, -60, -58, -56, -54, -52, -49, 33262306a36Sopenharmony_ci -47, -45, -43, -41, -39, -36, -34, -32, 33362306a36Sopenharmony_ci -30, -28, -25, -23, -21, -19, -16, -14, 33462306a36Sopenharmony_ci -12, -9, -7, -5, -3, 0, 1, 3, 33562306a36Sopenharmony_ci 6, 8, 10, 12, 15, 17, 19, 22, 33662306a36Sopenharmony_ci 24, 26, 28, 30, 33, 35, 37, 39, 41 33762306a36Sopenharmony_ci}; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic const s16 hsv_red_y[] = { 34062306a36Sopenharmony_ci 82, 80, 78, 76, 74, 73, 71, 69, 34162306a36Sopenharmony_ci 67, 65, 63, 61, 58, 56, 54, 52, 34262306a36Sopenharmony_ci 50, 48, 46, 44, 41, 39, 37, 35, 34362306a36Sopenharmony_ci 32, 30, 28, 26, 23, 21, 19, 16, 34462306a36Sopenharmony_ci 14, 12, 10, 7, 5, 3, 0, -1, 34562306a36Sopenharmony_ci -3, -6, -8, -10, -13, -15, -17, -19, 34662306a36Sopenharmony_ci -22, -24, -26, -29, -31, -33, -35, -38, 34762306a36Sopenharmony_ci -40, -42, -44, -46, -48, -51, -53, -55, 34862306a36Sopenharmony_ci -57, -59, -61, -63, -65, -67, -69, -71, 34962306a36Sopenharmony_ci -73, -75, -77, -79, -81, -82, -84, -86, 35062306a36Sopenharmony_ci -88, -89, -91, -93, -94, -96, -98, -99, 35162306a36Sopenharmony_ci -101, -102, -104, -105, -106, -108, -109, -110, 35262306a36Sopenharmony_ci -112, -113, -114, -115, -116, -117, -119, -120, 35362306a36Sopenharmony_ci -120, -121, -122, -123, -124, -125, -126, -126, 35462306a36Sopenharmony_ci -127, -128, -128, -128, -128, -128, -128, -128, 35562306a36Sopenharmony_ci -128, -128, -128, -128, -128, -128, -128, -128, 35662306a36Sopenharmony_ci -128, -128, -128, -128, -128, -128, -128, -128, 35762306a36Sopenharmony_ci -128, -128, -128, -128, -128, -128, -128, -128, 35862306a36Sopenharmony_ci -127, -127, -126, -125, -125, -124, -123, -122, 35962306a36Sopenharmony_ci -121, -120, -119, -118, -117, -116, -115, -114, 36062306a36Sopenharmony_ci -113, -111, -110, -109, -107, -106, -105, -103, 36162306a36Sopenharmony_ci -102, -100, -99, -97, -96, -94, -92, -91, 36262306a36Sopenharmony_ci -89, -87, -85, -84, -82, -80, -78, -76, 36362306a36Sopenharmony_ci -74, -73, -71, -69, -67, -65, -63, -61, 36462306a36Sopenharmony_ci -58, -56, -54, -52, -50, -48, -46, -44, 36562306a36Sopenharmony_ci -41, -39, -37, -35, -32, -30, -28, -26, 36662306a36Sopenharmony_ci -23, -21, -19, -16, -14, -12, -10, -7, 36762306a36Sopenharmony_ci -5, -3, 0, 1, 3, 6, 8, 10, 36862306a36Sopenharmony_ci 13, 15, 17, 19, 22, 24, 26, 29, 36962306a36Sopenharmony_ci 31, 33, 35, 38, 40, 42, 44, 46, 37062306a36Sopenharmony_ci 48, 51, 53, 55, 57, 59, 61, 63, 37162306a36Sopenharmony_ci 65, 67, 69, 71, 73, 75, 77, 79, 37262306a36Sopenharmony_ci 81, 82, 84, 86, 88, 89, 91, 93, 37362306a36Sopenharmony_ci 94, 96, 98, 99, 101, 102, 104, 105, 37462306a36Sopenharmony_ci 106, 108, 109, 110, 112, 113, 114, 115, 37562306a36Sopenharmony_ci 116, 117, 119, 120, 120, 121, 122, 123, 37662306a36Sopenharmony_ci 124, 125, 126, 126, 127, 128, 128, 129, 37762306a36Sopenharmony_ci 129, 130, 130, 131, 131, 131, 131, 132, 37862306a36Sopenharmony_ci 132, 132, 132, 132, 132, 132, 132, 132, 37962306a36Sopenharmony_ci 132, 132, 132, 131, 131, 131, 130, 130, 38062306a36Sopenharmony_ci 130, 129, 129, 128, 127, 127, 126, 125, 38162306a36Sopenharmony_ci 125, 124, 123, 122, 121, 120, 119, 118, 38262306a36Sopenharmony_ci 117, 116, 115, 114, 113, 111, 110, 109, 38362306a36Sopenharmony_ci 107, 106, 105, 103, 102, 100, 99, 97, 38462306a36Sopenharmony_ci 96, 94, 92, 91, 89, 87, 85, 84, 82 38562306a36Sopenharmony_ci}; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic const s16 hsv_green_x[] = { 38862306a36Sopenharmony_ci -124, -124, -125, -125, -125, -125, -125, -125, 38962306a36Sopenharmony_ci -125, -126, -126, -125, -125, -125, -125, -125, 39062306a36Sopenharmony_ci -125, -124, -124, -124, -123, -123, -122, -122, 39162306a36Sopenharmony_ci -121, -121, -120, -120, -119, -118, -117, -117, 39262306a36Sopenharmony_ci -116, -115, -114, -113, -112, -111, -110, -109, 39362306a36Sopenharmony_ci -108, -107, -105, -104, -103, -102, -100, -99, 39462306a36Sopenharmony_ci -98, -96, -95, -93, -92, -91, -89, -87, 39562306a36Sopenharmony_ci -86, -84, -83, -81, -79, -77, -76, -74, 39662306a36Sopenharmony_ci -72, -70, -69, -67, -65, -63, -61, -59, 39762306a36Sopenharmony_ci -57, -55, -53, -51, -49, -47, -45, -43, 39862306a36Sopenharmony_ci -41, -39, -37, -35, -33, -30, -28, -26, 39962306a36Sopenharmony_ci -24, -22, -20, -18, -15, -13, -11, -9, 40062306a36Sopenharmony_ci -7, -4, -2, 0, 1, 3, 6, 8, 40162306a36Sopenharmony_ci 10, 12, 14, 17, 19, 21, 23, 25, 40262306a36Sopenharmony_ci 27, 29, 32, 34, 36, 38, 40, 42, 40362306a36Sopenharmony_ci 44, 46, 48, 50, 52, 54, 56, 58, 40462306a36Sopenharmony_ci 60, 62, 64, 66, 68, 70, 71, 73, 40562306a36Sopenharmony_ci 75, 77, 78, 80, 82, 83, 85, 87, 40662306a36Sopenharmony_ci 88, 90, 91, 93, 94, 96, 97, 98, 40762306a36Sopenharmony_ci 100, 101, 102, 104, 105, 106, 107, 108, 40862306a36Sopenharmony_ci 109, 111, 112, 113, 113, 114, 115, 116, 40962306a36Sopenharmony_ci 117, 118, 118, 119, 120, 120, 121, 122, 41062306a36Sopenharmony_ci 122, 123, 123, 124, 124, 124, 125, 125, 41162306a36Sopenharmony_ci 125, 125, 125, 125, 125, 126, 126, 125, 41262306a36Sopenharmony_ci 125, 125, 125, 125, 125, 124, 124, 124, 41362306a36Sopenharmony_ci 123, 123, 122, 122, 121, 121, 120, 120, 41462306a36Sopenharmony_ci 119, 118, 117, 117, 116, 115, 114, 113, 41562306a36Sopenharmony_ci 112, 111, 110, 109, 108, 107, 105, 104, 41662306a36Sopenharmony_ci 103, 102, 100, 99, 98, 96, 95, 93, 41762306a36Sopenharmony_ci 92, 91, 89, 87, 86, 84, 83, 81, 41862306a36Sopenharmony_ci 79, 77, 76, 74, 72, 70, 69, 67, 41962306a36Sopenharmony_ci 65, 63, 61, 59, 57, 55, 53, 51, 42062306a36Sopenharmony_ci 49, 47, 45, 43, 41, 39, 37, 35, 42162306a36Sopenharmony_ci 33, 30, 28, 26, 24, 22, 20, 18, 42262306a36Sopenharmony_ci 15, 13, 11, 9, 7, 4, 2, 0, 42362306a36Sopenharmony_ci -1, -3, -6, -8, -10, -12, -14, -17, 42462306a36Sopenharmony_ci -19, -21, -23, -25, -27, -29, -32, -34, 42562306a36Sopenharmony_ci -36, -38, -40, -42, -44, -46, -48, -50, 42662306a36Sopenharmony_ci -52, -54, -56, -58, -60, -62, -64, -66, 42762306a36Sopenharmony_ci -68, -70, -71, -73, -75, -77, -78, -80, 42862306a36Sopenharmony_ci -82, -83, -85, -87, -88, -90, -91, -93, 42962306a36Sopenharmony_ci -94, -96, -97, -98, -100, -101, -102, -104, 43062306a36Sopenharmony_ci -105, -106, -107, -108, -109, -111, -112, -113, 43162306a36Sopenharmony_ci -113, -114, -115, -116, -117, -118, -118, -119, 43262306a36Sopenharmony_ci -120, -120, -121, -122, -122, -123, -123, -124, -124 43362306a36Sopenharmony_ci}; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic const s16 hsv_green_y[] = { 43662306a36Sopenharmony_ci -100, -99, -98, -97, -95, -94, -93, -91, 43762306a36Sopenharmony_ci -90, -89, -87, -86, -84, -83, -81, -80, 43862306a36Sopenharmony_ci -78, -76, -75, -73, -71, -70, -68, -66, 43962306a36Sopenharmony_ci -64, -63, -61, -59, -57, -55, -53, -51, 44062306a36Sopenharmony_ci -49, -48, -46, -44, -42, -40, -38, -36, 44162306a36Sopenharmony_ci -34, -32, -30, -27, -25, -23, -21, -19, 44262306a36Sopenharmony_ci -17, -15, -13, -11, -9, -7, -4, -2, 44362306a36Sopenharmony_ci 0, 1, 3, 5, 7, 9, 11, 14, 44462306a36Sopenharmony_ci 16, 18, 20, 22, 24, 26, 28, 30, 44562306a36Sopenharmony_ci 32, 34, 36, 38, 40, 42, 44, 46, 44662306a36Sopenharmony_ci 48, 50, 52, 54, 56, 58, 59, 61, 44762306a36Sopenharmony_ci 63, 65, 67, 68, 70, 72, 74, 75, 44862306a36Sopenharmony_ci 77, 78, 80, 82, 83, 85, 86, 88, 44962306a36Sopenharmony_ci 89, 90, 92, 93, 95, 96, 97, 98, 45062306a36Sopenharmony_ci 100, 101, 102, 103, 104, 105, 106, 107, 45162306a36Sopenharmony_ci 108, 109, 110, 111, 112, 112, 113, 114, 45262306a36Sopenharmony_ci 115, 115, 116, 116, 117, 117, 118, 118, 45362306a36Sopenharmony_ci 119, 119, 119, 120, 120, 120, 120, 120, 45462306a36Sopenharmony_ci 121, 121, 121, 121, 121, 121, 120, 120, 45562306a36Sopenharmony_ci 120, 120, 120, 119, 119, 119, 118, 118, 45662306a36Sopenharmony_ci 117, 117, 116, 116, 115, 114, 114, 113, 45762306a36Sopenharmony_ci 112, 111, 111, 110, 109, 108, 107, 106, 45862306a36Sopenharmony_ci 105, 104, 103, 102, 100, 99, 98, 97, 45962306a36Sopenharmony_ci 95, 94, 93, 91, 90, 89, 87, 86, 46062306a36Sopenharmony_ci 84, 83, 81, 80, 78, 76, 75, 73, 46162306a36Sopenharmony_ci 71, 70, 68, 66, 64, 63, 61, 59, 46262306a36Sopenharmony_ci 57, 55, 53, 51, 49, 48, 46, 44, 46362306a36Sopenharmony_ci 42, 40, 38, 36, 34, 32, 30, 27, 46462306a36Sopenharmony_ci 25, 23, 21, 19, 17, 15, 13, 11, 46562306a36Sopenharmony_ci 9, 7, 4, 2, 0, -1, -3, -5, 46662306a36Sopenharmony_ci -7, -9, -11, -14, -16, -18, -20, -22, 46762306a36Sopenharmony_ci -24, -26, -28, -30, -32, -34, -36, -38, 46862306a36Sopenharmony_ci -40, -42, -44, -46, -48, -50, -52, -54, 46962306a36Sopenharmony_ci -56, -58, -59, -61, -63, -65, -67, -68, 47062306a36Sopenharmony_ci -70, -72, -74, -75, -77, -78, -80, -82, 47162306a36Sopenharmony_ci -83, -85, -86, -88, -89, -90, -92, -93, 47262306a36Sopenharmony_ci -95, -96, -97, -98, -100, -101, -102, -103, 47362306a36Sopenharmony_ci -104, -105, -106, -107, -108, -109, -110, -111, 47462306a36Sopenharmony_ci -112, -112, -113, -114, -115, -115, -116, -116, 47562306a36Sopenharmony_ci -117, -117, -118, -118, -119, -119, -119, -120, 47662306a36Sopenharmony_ci -120, -120, -120, -120, -121, -121, -121, -121, 47762306a36Sopenharmony_ci -121, -121, -120, -120, -120, -120, -120, -119, 47862306a36Sopenharmony_ci -119, -119, -118, -118, -117, -117, -116, -116, 47962306a36Sopenharmony_ci -115, -114, -114, -113, -112, -111, -111, -110, 48062306a36Sopenharmony_ci -109, -108, -107, -106, -105, -104, -103, -102, -100 48162306a36Sopenharmony_ci}; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic const s16 hsv_blue_x[] = { 48462306a36Sopenharmony_ci 112, 113, 114, 114, 115, 116, 117, 117, 48562306a36Sopenharmony_ci 118, 118, 119, 119, 120, 120, 120, 121, 48662306a36Sopenharmony_ci 121, 121, 122, 122, 122, 122, 122, 122, 48762306a36Sopenharmony_ci 122, 122, 122, 122, 122, 122, 121, 121, 48862306a36Sopenharmony_ci 121, 120, 120, 120, 119, 119, 118, 118, 48962306a36Sopenharmony_ci 117, 116, 116, 115, 114, 113, 113, 112, 49062306a36Sopenharmony_ci 111, 110, 109, 108, 107, 106, 105, 104, 49162306a36Sopenharmony_ci 103, 102, 100, 99, 98, 97, 95, 94, 49262306a36Sopenharmony_ci 93, 91, 90, 88, 87, 85, 84, 82, 49362306a36Sopenharmony_ci 80, 79, 77, 76, 74, 72, 70, 69, 49462306a36Sopenharmony_ci 67, 65, 63, 61, 60, 58, 56, 54, 49562306a36Sopenharmony_ci 52, 50, 48, 46, 44, 42, 40, 38, 49662306a36Sopenharmony_ci 36, 34, 32, 30, 28, 26, 24, 22, 49762306a36Sopenharmony_ci 19, 17, 15, 13, 11, 9, 7, 5, 49862306a36Sopenharmony_ci 2, 0, -1, -3, -5, -7, -9, -12, 49962306a36Sopenharmony_ci -14, -16, -18, -20, -22, -24, -26, -28, 50062306a36Sopenharmony_ci -31, -33, -35, -37, -39, -41, -43, -45, 50162306a36Sopenharmony_ci -47, -49, -51, -53, -54, -56, -58, -60, 50262306a36Sopenharmony_ci -62, -64, -66, -67, -69, -71, -73, -74, 50362306a36Sopenharmony_ci -76, -78, -79, -81, -83, -84, -86, -87, 50462306a36Sopenharmony_ci -89, -90, -92, -93, -94, -96, -97, -98, 50562306a36Sopenharmony_ci -99, -101, -102, -103, -104, -105, -106, -107, 50662306a36Sopenharmony_ci -108, -109, -110, -111, -112, -113, -114, -114, 50762306a36Sopenharmony_ci -115, -116, -117, -117, -118, -118, -119, -119, 50862306a36Sopenharmony_ci -120, -120, -120, -121, -121, -121, -122, -122, 50962306a36Sopenharmony_ci -122, -122, -122, -122, -122, -122, -122, -122, 51062306a36Sopenharmony_ci -122, -122, -121, -121, -121, -120, -120, -120, 51162306a36Sopenharmony_ci -119, -119, -118, -118, -117, -116, -116, -115, 51262306a36Sopenharmony_ci -114, -113, -113, -112, -111, -110, -109, -108, 51362306a36Sopenharmony_ci -107, -106, -105, -104, -103, -102, -100, -99, 51462306a36Sopenharmony_ci -98, -97, -95, -94, -93, -91, -90, -88, 51562306a36Sopenharmony_ci -87, -85, -84, -82, -80, -79, -77, -76, 51662306a36Sopenharmony_ci -74, -72, -70, -69, -67, -65, -63, -61, 51762306a36Sopenharmony_ci -60, -58, -56, -54, -52, -50, -48, -46, 51862306a36Sopenharmony_ci -44, -42, -40, -38, -36, -34, -32, -30, 51962306a36Sopenharmony_ci -28, -26, -24, -22, -19, -17, -15, -13, 52062306a36Sopenharmony_ci -11, -9, -7, -5, -2, 0, 1, 3, 52162306a36Sopenharmony_ci 5, 7, 9, 12, 14, 16, 18, 20, 52262306a36Sopenharmony_ci 22, 24, 26, 28, 31, 33, 35, 37, 52362306a36Sopenharmony_ci 39, 41, 43, 45, 47, 49, 51, 53, 52462306a36Sopenharmony_ci 54, 56, 58, 60, 62, 64, 66, 67, 52562306a36Sopenharmony_ci 69, 71, 73, 74, 76, 78, 79, 81, 52662306a36Sopenharmony_ci 83, 84, 86, 87, 89, 90, 92, 93, 52762306a36Sopenharmony_ci 94, 96, 97, 98, 99, 101, 102, 103, 52862306a36Sopenharmony_ci 104, 105, 106, 107, 108, 109, 110, 111, 112 52962306a36Sopenharmony_ci}; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cistatic const s16 hsv_blue_y[] = { 53262306a36Sopenharmony_ci -11, -13, -15, -17, -19, -21, -23, -25, 53362306a36Sopenharmony_ci -27, -29, -31, -33, -35, -37, -39, -41, 53462306a36Sopenharmony_ci -43, -45, -46, -48, -50, -52, -54, -55, 53562306a36Sopenharmony_ci -57, -59, -61, -62, -64, -66, -67, -69, 53662306a36Sopenharmony_ci -71, -72, -74, -75, -77, -78, -80, -81, 53762306a36Sopenharmony_ci -83, -84, -86, -87, -88, -90, -91, -92, 53862306a36Sopenharmony_ci -93, -95, -96, -97, -98, -99, -100, -101, 53962306a36Sopenharmony_ci -102, -103, -104, -105, -106, -106, -107, -108, 54062306a36Sopenharmony_ci -109, -109, -110, -111, -111, -112, -112, -113, 54162306a36Sopenharmony_ci -113, -114, -114, -114, -115, -115, -115, -115, 54262306a36Sopenharmony_ci -116, -116, -116, -116, -116, -116, -116, -116, 54362306a36Sopenharmony_ci -116, -115, -115, -115, -115, -114, -114, -114, 54462306a36Sopenharmony_ci -113, -113, -112, -112, -111, -111, -110, -110, 54562306a36Sopenharmony_ci -109, -108, -108, -107, -106, -105, -104, -103, 54662306a36Sopenharmony_ci -102, -101, -100, -99, -98, -97, -96, -95, 54762306a36Sopenharmony_ci -94, -93, -91, -90, -89, -88, -86, -85, 54862306a36Sopenharmony_ci -84, -82, -81, -79, -78, -76, -75, -73, 54962306a36Sopenharmony_ci -71, -70, -68, -67, -65, -63, -62, -60, 55062306a36Sopenharmony_ci -58, -56, -55, -53, -51, -49, -47, -45, 55162306a36Sopenharmony_ci -44, -42, -40, -38, -36, -34, -32, -30, 55262306a36Sopenharmony_ci -28, -26, -24, -22, -20, -18, -16, -14, 55362306a36Sopenharmony_ci -12, -10, -8, -6, -4, -2, 0, 1, 55462306a36Sopenharmony_ci 3, 5, 7, 9, 11, 13, 15, 17, 55562306a36Sopenharmony_ci 19, 21, 23, 25, 27, 29, 31, 33, 55662306a36Sopenharmony_ci 35, 37, 39, 41, 43, 45, 46, 48, 55762306a36Sopenharmony_ci 50, 52, 54, 55, 57, 59, 61, 62, 55862306a36Sopenharmony_ci 64, 66, 67, 69, 71, 72, 74, 75, 55962306a36Sopenharmony_ci 77, 78, 80, 81, 83, 84, 86, 87, 56062306a36Sopenharmony_ci 88, 90, 91, 92, 93, 95, 96, 97, 56162306a36Sopenharmony_ci 98, 99, 100, 101, 102, 103, 104, 105, 56262306a36Sopenharmony_ci 106, 106, 107, 108, 109, 109, 110, 111, 56362306a36Sopenharmony_ci 111, 112, 112, 113, 113, 114, 114, 114, 56462306a36Sopenharmony_ci 115, 115, 115, 115, 116, 116, 116, 116, 56562306a36Sopenharmony_ci 116, 116, 116, 116, 116, 115, 115, 115, 56662306a36Sopenharmony_ci 115, 114, 114, 114, 113, 113, 112, 112, 56762306a36Sopenharmony_ci 111, 111, 110, 110, 109, 108, 108, 107, 56862306a36Sopenharmony_ci 106, 105, 104, 103, 102, 101, 100, 99, 56962306a36Sopenharmony_ci 98, 97, 96, 95, 94, 93, 91, 90, 57062306a36Sopenharmony_ci 89, 88, 86, 85, 84, 82, 81, 79, 57162306a36Sopenharmony_ci 78, 76, 75, 73, 71, 70, 68, 67, 57262306a36Sopenharmony_ci 65, 63, 62, 60, 58, 56, 55, 53, 57362306a36Sopenharmony_ci 51, 49, 47, 45, 44, 42, 40, 38, 57462306a36Sopenharmony_ci 36, 34, 32, 30, 28, 26, 24, 22, 57562306a36Sopenharmony_ci 20, 18, 16, 14, 12, 10, 8, 6, 57662306a36Sopenharmony_ci 4, 2, 0, -1, -3, -5, -7, -9, -11 57762306a36Sopenharmony_ci}; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic const u16 bridge_init[][2] = { 58062306a36Sopenharmony_ci {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c}, 58162306a36Sopenharmony_ci {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40}, 58262306a36Sopenharmony_ci {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10}, 58362306a36Sopenharmony_ci {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00}, 58462306a36Sopenharmony_ci {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50}, 58562306a36Sopenharmony_ci {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50}, 58662306a36Sopenharmony_ci {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04}, 58762306a36Sopenharmony_ci {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05}, 58862306a36Sopenharmony_ci {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00}, 58962306a36Sopenharmony_ci {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d}, 59062306a36Sopenharmony_ci {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04}, 59162306a36Sopenharmony_ci {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8}, 59262306a36Sopenharmony_ci {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32}, 59362306a36Sopenharmony_ci {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd}, 59462306a36Sopenharmony_ci {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01}, 59562306a36Sopenharmony_ci {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f}, 59662306a36Sopenharmony_ci {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f}, 59762306a36Sopenharmony_ci {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01}, 59862306a36Sopenharmony_ci {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80}, 59962306a36Sopenharmony_ci {0x1007, 0x00} 60062306a36Sopenharmony_ci}; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */ 60362306a36Sopenharmony_cistatic const u8 ov_gain[] = { 60462306a36Sopenharmony_ci 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */, 60562306a36Sopenharmony_ci 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */, 60662306a36Sopenharmony_ci 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */, 60762306a36Sopenharmony_ci 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */, 60862306a36Sopenharmony_ci 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */, 60962306a36Sopenharmony_ci 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */, 61062306a36Sopenharmony_ci 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */, 61162306a36Sopenharmony_ci 0x70 /* 8x */ 61262306a36Sopenharmony_ci}; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */ 61562306a36Sopenharmony_cistatic const u16 micron1_gain[] = { 61662306a36Sopenharmony_ci /* 1x 1.25x 1.5x 1.75x */ 61762306a36Sopenharmony_ci 0x0020, 0x0028, 0x0030, 0x0038, 61862306a36Sopenharmony_ci /* 2x 2.25x 2.5x 2.75x */ 61962306a36Sopenharmony_ci 0x00a0, 0x00a4, 0x00a8, 0x00ac, 62062306a36Sopenharmony_ci /* 3x 3.25x 3.5x 3.75x */ 62162306a36Sopenharmony_ci 0x00b0, 0x00b4, 0x00b8, 0x00bc, 62262306a36Sopenharmony_ci /* 4x 4.25x 4.5x 4.75x */ 62362306a36Sopenharmony_ci 0x00c0, 0x00c4, 0x00c8, 0x00cc, 62462306a36Sopenharmony_ci /* 5x 5.25x 5.5x 5.75x */ 62562306a36Sopenharmony_ci 0x00d0, 0x00d4, 0x00d8, 0x00dc, 62662306a36Sopenharmony_ci /* 6x 6.25x 6.5x 6.75x */ 62762306a36Sopenharmony_ci 0x00e0, 0x00e4, 0x00e8, 0x00ec, 62862306a36Sopenharmony_ci /* 7x 7.25x 7.5x 7.75x */ 62962306a36Sopenharmony_ci 0x00f0, 0x00f4, 0x00f8, 0x00fc, 63062306a36Sopenharmony_ci /* 8x */ 63162306a36Sopenharmony_ci 0x01c0 63262306a36Sopenharmony_ci}; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci/* mt9m001 sensor uses a different gain formula then other micron sensors */ 63562306a36Sopenharmony_ci/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */ 63662306a36Sopenharmony_cistatic const u16 micron2_gain[] = { 63762306a36Sopenharmony_ci /* 1x 1.25x 1.5x 1.75x */ 63862306a36Sopenharmony_ci 0x0008, 0x000a, 0x000c, 0x000e, 63962306a36Sopenharmony_ci /* 2x 2.25x 2.5x 2.75x */ 64062306a36Sopenharmony_ci 0x0010, 0x0012, 0x0014, 0x0016, 64162306a36Sopenharmony_ci /* 3x 3.25x 3.5x 3.75x */ 64262306a36Sopenharmony_ci 0x0018, 0x001a, 0x001c, 0x001e, 64362306a36Sopenharmony_ci /* 4x 4.25x 4.5x 4.75x */ 64462306a36Sopenharmony_ci 0x0020, 0x0051, 0x0052, 0x0053, 64562306a36Sopenharmony_ci /* 5x 5.25x 5.5x 5.75x */ 64662306a36Sopenharmony_ci 0x0054, 0x0055, 0x0056, 0x0057, 64762306a36Sopenharmony_ci /* 6x 6.25x 6.5x 6.75x */ 64862306a36Sopenharmony_ci 0x0058, 0x0059, 0x005a, 0x005b, 64962306a36Sopenharmony_ci /* 7x 7.25x 7.5x 7.75x */ 65062306a36Sopenharmony_ci 0x005c, 0x005d, 0x005e, 0x005f, 65162306a36Sopenharmony_ci /* 8x */ 65262306a36Sopenharmony_ci 0x0060 65362306a36Sopenharmony_ci}; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci/* Gain = .5 + bit[7:0] / 16 */ 65662306a36Sopenharmony_cistatic const u8 hv7131r_gain[] = { 65762306a36Sopenharmony_ci 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */, 65862306a36Sopenharmony_ci 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */, 65962306a36Sopenharmony_ci 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */, 66062306a36Sopenharmony_ci 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */, 66162306a36Sopenharmony_ci 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */, 66262306a36Sopenharmony_ci 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */, 66362306a36Sopenharmony_ci 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */, 66462306a36Sopenharmony_ci 0x78 /* 8x */ 66562306a36Sopenharmony_ci}; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic const struct i2c_reg_u8 soi968_init[] = { 66862306a36Sopenharmony_ci {0x0c, 0x00}, {0x0f, 0x1f}, 66962306a36Sopenharmony_ci {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00}, 67062306a36Sopenharmony_ci {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c}, 67162306a36Sopenharmony_ci {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, 67262306a36Sopenharmony_ci {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20}, 67362306a36Sopenharmony_ci {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e}, 67462306a36Sopenharmony_ci {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13}, 67562306a36Sopenharmony_ci {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79}, 67662306a36Sopenharmony_ci {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40}, 67762306a36Sopenharmony_ci {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32}, 67862306a36Sopenharmony_ci {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80}, 67962306a36Sopenharmony_ci}; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_cistatic const struct i2c_reg_u8 ov7660_init[] = { 68262306a36Sopenharmony_ci {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3}, 68362306a36Sopenharmony_ci {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40}, 68462306a36Sopenharmony_ci {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a}, 68562306a36Sopenharmony_ci /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using 68662306a36Sopenharmony_ci 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */ 68762306a36Sopenharmony_ci {0x17, 0x10}, {0x18, 0x61}, 68862306a36Sopenharmony_ci {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43}, 68962306a36Sopenharmony_ci {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00}, 69062306a36Sopenharmony_ci {0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50}, 69162306a36Sopenharmony_ci}; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_cistatic const struct i2c_reg_u8 ov7670_init[] = { 69462306a36Sopenharmony_ci {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01}, 69562306a36Sopenharmony_ci {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00}, 69662306a36Sopenharmony_ci {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0}, 69762306a36Sopenharmony_ci {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00}, 69862306a36Sopenharmony_ci {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07}, 69962306a36Sopenharmony_ci {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75}, 70062306a36Sopenharmony_ci {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8}, 70162306a36Sopenharmony_ci {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5}, 70262306a36Sopenharmony_ci {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27}, 70362306a36Sopenharmony_ci {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b}, 70462306a36Sopenharmony_ci {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a}, 70562306a36Sopenharmony_ci {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00}, 70662306a36Sopenharmony_ci {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00}, 70762306a36Sopenharmony_ci {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80}, 70862306a36Sopenharmony_ci {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82}, 70962306a36Sopenharmony_ci {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20}, 71062306a36Sopenharmony_ci {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c}, 71162306a36Sopenharmony_ci {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66}, 71262306a36Sopenharmony_ci {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11}, 71362306a36Sopenharmony_ci {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40}, 71462306a36Sopenharmony_ci {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02}, 71562306a36Sopenharmony_ci {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a}, 71662306a36Sopenharmony_ci {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08}, 71762306a36Sopenharmony_ci {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04}, 71862306a36Sopenharmony_ci {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30}, 71962306a36Sopenharmony_ci {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88}, 72062306a36Sopenharmony_ci {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30}, 72162306a36Sopenharmony_ci {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99}, 72262306a36Sopenharmony_ci {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0}, 72362306a36Sopenharmony_ci {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e}, 72462306a36Sopenharmony_ci {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01}, 72562306a36Sopenharmony_ci {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20}, 72662306a36Sopenharmony_ci {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0}, 72762306a36Sopenharmony_ci {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30}, 72862306a36Sopenharmony_ci {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06}, 72962306a36Sopenharmony_ci {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a}, 73062306a36Sopenharmony_ci {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a}, 73162306a36Sopenharmony_ci {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84}, 73262306a36Sopenharmony_ci {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d}, 73362306a36Sopenharmony_ci {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d}, 73462306a36Sopenharmony_ci {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00}, 73562306a36Sopenharmony_ci {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, 73662306a36Sopenharmony_ci {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60}, 73762306a36Sopenharmony_ci {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, 73862306a36Sopenharmony_ci {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e}, 73962306a36Sopenharmony_ci {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56}, 74062306a36Sopenharmony_ci {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03}, 74162306a36Sopenharmony_ci {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47}, 74262306a36Sopenharmony_ci {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74}, 74362306a36Sopenharmony_ci {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2}, 74462306a36Sopenharmony_ci {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00}, 74562306a36Sopenharmony_ci {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a}, 74662306a36Sopenharmony_ci {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00}, 74762306a36Sopenharmony_ci {0x93, 0x00}, 74862306a36Sopenharmony_ci}; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_cistatic const struct i2c_reg_u8 ov9650_init[] = { 75162306a36Sopenharmony_ci {0x00, 0x00}, {0x01, 0x78}, 75262306a36Sopenharmony_ci {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03}, 75362306a36Sopenharmony_ci {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00}, 75462306a36Sopenharmony_ci {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00}, 75562306a36Sopenharmony_ci {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c}, 75662306a36Sopenharmony_ci {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2}, 75762306a36Sopenharmony_ci {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07}, 75862306a36Sopenharmony_ci {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00}, 75962306a36Sopenharmony_ci {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04}, 76062306a36Sopenharmony_ci {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68}, 76162306a36Sopenharmony_ci {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80}, 76262306a36Sopenharmony_ci {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00}, 76362306a36Sopenharmony_ci {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00}, 76462306a36Sopenharmony_ci {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30}, 76562306a36Sopenharmony_ci {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf}, 76662306a36Sopenharmony_ci {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00}, 76762306a36Sopenharmony_ci {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01}, 76862306a36Sopenharmony_ci {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19}, 76962306a36Sopenharmony_ci {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1}, 77062306a36Sopenharmony_ci {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80}, 77162306a36Sopenharmony_ci {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00}, 77262306a36Sopenharmony_ci {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20}, 77362306a36Sopenharmony_ci {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf}, 77462306a36Sopenharmony_ci {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88}, 77562306a36Sopenharmony_ci {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00}, 77662306a36Sopenharmony_ci {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8}, 77762306a36Sopenharmony_ci {0xaa, 0x92}, {0xab, 0x0a}, 77862306a36Sopenharmony_ci}; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_cistatic const struct i2c_reg_u8 ov9655_init[] = { 78162306a36Sopenharmony_ci {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba}, 78262306a36Sopenharmony_ci {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08}, 78362306a36Sopenharmony_ci {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d}, 78462306a36Sopenharmony_ci {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57}, 78562306a36Sopenharmony_ci {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19}, 78662306a36Sopenharmony_ci {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80}, 78762306a36Sopenharmony_ci {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c}, 78862306a36Sopenharmony_ci {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc}, 78962306a36Sopenharmony_ci {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05}, 79062306a36Sopenharmony_ci {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e}, 79162306a36Sopenharmony_ci {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, 79262306a36Sopenharmony_ci {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, 79362306a36Sopenharmony_ci {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, 79462306a36Sopenharmony_ci {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, 79562306a36Sopenharmony_ci {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, 79662306a36Sopenharmony_ci {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01}, 79762306a36Sopenharmony_ci {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0}, 79862306a36Sopenharmony_ci {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00}, 79962306a36Sopenharmony_ci {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61}, 80062306a36Sopenharmony_ci {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a}, 80162306a36Sopenharmony_ci {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01}, 80262306a36Sopenharmony_ci {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a}, 80362306a36Sopenharmony_ci {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c}, 80462306a36Sopenharmony_ci {0x04, 0x03}, {0x00, 0x13}, 80562306a36Sopenharmony_ci}; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_cistatic const struct i2c_reg_u16 mt9v112_init[] = { 80862306a36Sopenharmony_ci {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020}, 80962306a36Sopenharmony_ci {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b}, 81062306a36Sopenharmony_ci {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001}, 81162306a36Sopenharmony_ci {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a}, 81262306a36Sopenharmony_ci {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58}, 81362306a36Sopenharmony_ci {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001}, 81462306a36Sopenharmony_ci {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020}, 81562306a36Sopenharmony_ci {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020}, 81662306a36Sopenharmony_ci {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020}, 81762306a36Sopenharmony_ci {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c}, 81862306a36Sopenharmony_ci {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2}, 81962306a36Sopenharmony_ci {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0}, 82062306a36Sopenharmony_ci {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020}, 82162306a36Sopenharmony_ci {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c}, 82262306a36Sopenharmony_ci {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae}, 82362306a36Sopenharmony_ci {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae}, 82462306a36Sopenharmony_ci}; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_cistatic const struct i2c_reg_u16 mt9v111_init[] = { 82762306a36Sopenharmony_ci {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000}, 82862306a36Sopenharmony_ci {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0}, 82962306a36Sopenharmony_ci {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e}, 83062306a36Sopenharmony_ci {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016}, 83162306a36Sopenharmony_ci {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004}, 83262306a36Sopenharmony_ci {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008}, 83362306a36Sopenharmony_ci {0x0e, 0x0008}, {0x20, 0x0000} 83462306a36Sopenharmony_ci}; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_cistatic const struct i2c_reg_u16 mt9v011_init[] = { 83762306a36Sopenharmony_ci {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000}, 83862306a36Sopenharmony_ci {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1}, 83962306a36Sopenharmony_ci {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006}, 84062306a36Sopenharmony_ci {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000}, 84162306a36Sopenharmony_ci {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000}, 84262306a36Sopenharmony_ci {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000}, 84362306a36Sopenharmony_ci {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000}, 84462306a36Sopenharmony_ci {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000}, 84562306a36Sopenharmony_ci {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000}, 84662306a36Sopenharmony_ci {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000}, 84762306a36Sopenharmony_ci {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000}, 84862306a36Sopenharmony_ci {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000}, 84962306a36Sopenharmony_ci {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024}, 85062306a36Sopenharmony_ci {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000}, 85162306a36Sopenharmony_ci {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100}, 85262306a36Sopenharmony_ci {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1}, 85362306a36Sopenharmony_ci {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000}, 85462306a36Sopenharmony_ci {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000}, 85562306a36Sopenharmony_ci {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000}, 85662306a36Sopenharmony_ci {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101}, 85762306a36Sopenharmony_ci {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003}, 85862306a36Sopenharmony_ci {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0}, 85962306a36Sopenharmony_ci {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000}, 86062306a36Sopenharmony_ci {0x06, 0x0029}, {0x05, 0x0009}, 86162306a36Sopenharmony_ci}; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_cistatic const struct i2c_reg_u16 mt9m001_init[] = { 86462306a36Sopenharmony_ci {0x0d, 0x0001}, 86562306a36Sopenharmony_ci {0x0d, 0x0000}, 86662306a36Sopenharmony_ci {0x04, 0x0500}, /* hres = 1280 */ 86762306a36Sopenharmony_ci {0x03, 0x0400}, /* vres = 1024 */ 86862306a36Sopenharmony_ci {0x20, 0x1100}, 86962306a36Sopenharmony_ci {0x06, 0x0010}, 87062306a36Sopenharmony_ci {0x2b, 0x0024}, 87162306a36Sopenharmony_ci {0x2e, 0x0024}, 87262306a36Sopenharmony_ci {0x35, 0x0024}, 87362306a36Sopenharmony_ci {0x2d, 0x0020}, 87462306a36Sopenharmony_ci {0x2c, 0x0020}, 87562306a36Sopenharmony_ci {0x09, 0x0ad4}, 87662306a36Sopenharmony_ci {0x35, 0x0057}, 87762306a36Sopenharmony_ci}; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic const struct i2c_reg_u16 mt9m111_init[] = { 88062306a36Sopenharmony_ci {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, 88162306a36Sopenharmony_ci {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, 88262306a36Sopenharmony_ci {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, 88362306a36Sopenharmony_ci {0xf0, 0x0000}, 88462306a36Sopenharmony_ci}; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_cistatic const struct i2c_reg_u16 mt9m112_init[] = { 88762306a36Sopenharmony_ci {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, 88862306a36Sopenharmony_ci {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, 88962306a36Sopenharmony_ci {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, 89062306a36Sopenharmony_ci {0xf0, 0x0000}, 89162306a36Sopenharmony_ci}; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_cistatic const struct i2c_reg_u8 hv7131r_init[] = { 89462306a36Sopenharmony_ci {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08}, 89562306a36Sopenharmony_ci {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0}, 89662306a36Sopenharmony_ci {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08}, 89762306a36Sopenharmony_ci {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07}, 89862306a36Sopenharmony_ci {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62}, 89962306a36Sopenharmony_ci {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10}, 90062306a36Sopenharmony_ci {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00}, 90162306a36Sopenharmony_ci {0x23, 0x09}, {0x01, 0x08}, 90262306a36Sopenharmony_ci}; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_cistatic void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) 90562306a36Sopenharmony_ci{ 90662306a36Sopenharmony_ci struct usb_device *dev = gspca_dev->dev; 90762306a36Sopenharmony_ci int result; 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 91062306a36Sopenharmony_ci return; 91162306a36Sopenharmony_ci result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 91262306a36Sopenharmony_ci 0x00, 91362306a36Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 91462306a36Sopenharmony_ci reg, 91562306a36Sopenharmony_ci 0x00, 91662306a36Sopenharmony_ci gspca_dev->usb_buf, 91762306a36Sopenharmony_ci length, 91862306a36Sopenharmony_ci 500); 91962306a36Sopenharmony_ci if (unlikely(result < 0 || result != length)) { 92062306a36Sopenharmony_ci pr_err("Read register %02x failed %d\n", reg, result); 92162306a36Sopenharmony_ci gspca_dev->usb_err = result; 92262306a36Sopenharmony_ci /* 92362306a36Sopenharmony_ci * Make sure the buffer is zeroed to avoid uninitialized 92462306a36Sopenharmony_ci * values. 92562306a36Sopenharmony_ci */ 92662306a36Sopenharmony_ci memset(gspca_dev->usb_buf, 0, USB_BUF_SZ); 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci} 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_cistatic void reg_w(struct gspca_dev *gspca_dev, u16 reg, 93162306a36Sopenharmony_ci const u8 *buffer, int length) 93262306a36Sopenharmony_ci{ 93362306a36Sopenharmony_ci struct usb_device *dev = gspca_dev->dev; 93462306a36Sopenharmony_ci int result; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 93762306a36Sopenharmony_ci return; 93862306a36Sopenharmony_ci memcpy(gspca_dev->usb_buf, buffer, length); 93962306a36Sopenharmony_ci result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 94062306a36Sopenharmony_ci 0x08, 94162306a36Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 94262306a36Sopenharmony_ci reg, 94362306a36Sopenharmony_ci 0x00, 94462306a36Sopenharmony_ci gspca_dev->usb_buf, 94562306a36Sopenharmony_ci length, 94662306a36Sopenharmony_ci 500); 94762306a36Sopenharmony_ci if (unlikely(result < 0 || result != length)) { 94862306a36Sopenharmony_ci pr_err("Write register %02x failed %d\n", reg, result); 94962306a36Sopenharmony_ci gspca_dev->usb_err = result; 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci} 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_cistatic void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci reg_w(gspca_dev, reg, &value, 1); 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_cistatic void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) 95962306a36Sopenharmony_ci{ 96062306a36Sopenharmony_ci int i; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci reg_w(gspca_dev, 0x10c0, buffer, 8); 96362306a36Sopenharmony_ci for (i = 0; i < 5; i++) { 96462306a36Sopenharmony_ci reg_r(gspca_dev, 0x10c0, 1); 96562306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 96662306a36Sopenharmony_ci return; 96762306a36Sopenharmony_ci if (gspca_dev->usb_buf[0] & 0x04) { 96862306a36Sopenharmony_ci if (gspca_dev->usb_buf[0] & 0x08) { 96962306a36Sopenharmony_ci pr_err("i2c_w error\n"); 97062306a36Sopenharmony_ci gspca_dev->usb_err = -EIO; 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci return; 97362306a36Sopenharmony_ci } 97462306a36Sopenharmony_ci msleep(10); 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci pr_err("i2c_w reg %02x no response\n", buffer[2]); 97762306a36Sopenharmony_ci/* gspca_dev->usb_err = -EIO; fixme: may occur */ 97862306a36Sopenharmony_ci} 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_cistatic void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) 98162306a36Sopenharmony_ci{ 98262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 98362306a36Sopenharmony_ci u8 row[8]; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci /* 98662306a36Sopenharmony_ci * from the point of view of the bridge, the length 98762306a36Sopenharmony_ci * includes the address 98862306a36Sopenharmony_ci */ 98962306a36Sopenharmony_ci row[0] = sd->i2c_intf | (2 << 4); 99062306a36Sopenharmony_ci row[1] = sd->i2c_addr; 99162306a36Sopenharmony_ci row[2] = reg; 99262306a36Sopenharmony_ci row[3] = val; 99362306a36Sopenharmony_ci row[4] = 0x00; 99462306a36Sopenharmony_ci row[5] = 0x00; 99562306a36Sopenharmony_ci row[6] = 0x00; 99662306a36Sopenharmony_ci row[7] = 0x10; 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci i2c_w(gspca_dev, row); 99962306a36Sopenharmony_ci} 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_cistatic void i2c_w1_buf(struct gspca_dev *gspca_dev, 100262306a36Sopenharmony_ci const struct i2c_reg_u8 *buf, int sz) 100362306a36Sopenharmony_ci{ 100462306a36Sopenharmony_ci while (--sz >= 0) { 100562306a36Sopenharmony_ci i2c_w1(gspca_dev, buf->reg, buf->val); 100662306a36Sopenharmony_ci buf++; 100762306a36Sopenharmony_ci } 100862306a36Sopenharmony_ci} 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_cistatic void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) 101162306a36Sopenharmony_ci{ 101262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 101362306a36Sopenharmony_ci u8 row[8]; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci /* 101662306a36Sopenharmony_ci * from the point of view of the bridge, the length 101762306a36Sopenharmony_ci * includes the address 101862306a36Sopenharmony_ci */ 101962306a36Sopenharmony_ci row[0] = sd->i2c_intf | (3 << 4); 102062306a36Sopenharmony_ci row[1] = sd->i2c_addr; 102162306a36Sopenharmony_ci row[2] = reg; 102262306a36Sopenharmony_ci row[3] = val >> 8; 102362306a36Sopenharmony_ci row[4] = val; 102462306a36Sopenharmony_ci row[5] = 0x00; 102562306a36Sopenharmony_ci row[6] = 0x00; 102662306a36Sopenharmony_ci row[7] = 0x10; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci i2c_w(gspca_dev, row); 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_cistatic void i2c_w2_buf(struct gspca_dev *gspca_dev, 103262306a36Sopenharmony_ci const struct i2c_reg_u16 *buf, int sz) 103362306a36Sopenharmony_ci{ 103462306a36Sopenharmony_ci while (--sz >= 0) { 103562306a36Sopenharmony_ci i2c_w2(gspca_dev, buf->reg, buf->val); 103662306a36Sopenharmony_ci buf++; 103762306a36Sopenharmony_ci } 103862306a36Sopenharmony_ci} 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_cistatic void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) 104162306a36Sopenharmony_ci{ 104262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 104362306a36Sopenharmony_ci u8 row[8]; 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci row[0] = sd->i2c_intf | (1 << 4); 104662306a36Sopenharmony_ci row[1] = sd->i2c_addr; 104762306a36Sopenharmony_ci row[2] = reg; 104862306a36Sopenharmony_ci row[3] = 0; 104962306a36Sopenharmony_ci row[4] = 0; 105062306a36Sopenharmony_ci row[5] = 0; 105162306a36Sopenharmony_ci row[6] = 0; 105262306a36Sopenharmony_ci row[7] = 0x10; 105362306a36Sopenharmony_ci i2c_w(gspca_dev, row); 105462306a36Sopenharmony_ci row[0] = sd->i2c_intf | (1 << 4) | 0x02; 105562306a36Sopenharmony_ci row[2] = 0; 105662306a36Sopenharmony_ci i2c_w(gspca_dev, row); 105762306a36Sopenharmony_ci reg_r(gspca_dev, 0x10c2, 5); 105862306a36Sopenharmony_ci *val = gspca_dev->usb_buf[4]; 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_cistatic void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) 106262306a36Sopenharmony_ci{ 106362306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 106462306a36Sopenharmony_ci u8 row[8]; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci row[0] = sd->i2c_intf | (1 << 4); 106762306a36Sopenharmony_ci row[1] = sd->i2c_addr; 106862306a36Sopenharmony_ci row[2] = reg; 106962306a36Sopenharmony_ci row[3] = 0; 107062306a36Sopenharmony_ci row[4] = 0; 107162306a36Sopenharmony_ci row[5] = 0; 107262306a36Sopenharmony_ci row[6] = 0; 107362306a36Sopenharmony_ci row[7] = 0x10; 107462306a36Sopenharmony_ci i2c_w(gspca_dev, row); 107562306a36Sopenharmony_ci row[0] = sd->i2c_intf | (2 << 4) | 0x02; 107662306a36Sopenharmony_ci row[2] = 0; 107762306a36Sopenharmony_ci i2c_w(gspca_dev, row); 107862306a36Sopenharmony_ci reg_r(gspca_dev, 0x10c2, 5); 107962306a36Sopenharmony_ci *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; 108062306a36Sopenharmony_ci} 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_cistatic void ov9650_init_sensor(struct gspca_dev *gspca_dev) 108362306a36Sopenharmony_ci{ 108462306a36Sopenharmony_ci u16 id; 108562306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci i2c_r2(gspca_dev, 0x1c, &id); 108862306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 108962306a36Sopenharmony_ci return; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci if (id != 0x7fa2) { 109262306a36Sopenharmony_ci pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id); 109362306a36Sopenharmony_ci gspca_dev->usb_err = -ENODEV; 109462306a36Sopenharmony_ci return; 109562306a36Sopenharmony_ci } 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 109862306a36Sopenharmony_ci msleep(200); 109962306a36Sopenharmony_ci i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init)); 110062306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 110162306a36Sopenharmony_ci pr_err("OV9650 sensor initialization failed\n"); 110262306a36Sopenharmony_ci sd->hstart = 1; 110362306a36Sopenharmony_ci sd->vstart = 7; 110462306a36Sopenharmony_ci} 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic void ov9655_init_sensor(struct gspca_dev *gspca_dev) 110762306a36Sopenharmony_ci{ 110862306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 111162306a36Sopenharmony_ci msleep(200); 111262306a36Sopenharmony_ci i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init)); 111362306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 111462306a36Sopenharmony_ci pr_err("OV9655 sensor initialization failed\n"); 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci sd->hstart = 1; 111762306a36Sopenharmony_ci sd->vstart = 2; 111862306a36Sopenharmony_ci} 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_cistatic void soi968_init_sensor(struct gspca_dev *gspca_dev) 112162306a36Sopenharmony_ci{ 112262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 112562306a36Sopenharmony_ci msleep(200); 112662306a36Sopenharmony_ci i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init)); 112762306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 112862306a36Sopenharmony_ci pr_err("SOI968 sensor initialization failed\n"); 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci sd->hstart = 60; 113162306a36Sopenharmony_ci sd->vstart = 11; 113262306a36Sopenharmony_ci} 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_cistatic void ov7660_init_sensor(struct gspca_dev *gspca_dev) 113562306a36Sopenharmony_ci{ 113662306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 113962306a36Sopenharmony_ci msleep(200); 114062306a36Sopenharmony_ci i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init)); 114162306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 114262306a36Sopenharmony_ci pr_err("OV7660 sensor initialization failed\n"); 114362306a36Sopenharmony_ci sd->hstart = 3; 114462306a36Sopenharmony_ci sd->vstart = 3; 114562306a36Sopenharmony_ci} 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_cistatic void ov7670_init_sensor(struct gspca_dev *gspca_dev) 114862306a36Sopenharmony_ci{ 114962306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 115262306a36Sopenharmony_ci msleep(200); 115362306a36Sopenharmony_ci i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init)); 115462306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 115562306a36Sopenharmony_ci pr_err("OV7670 sensor initialization failed\n"); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci sd->hstart = 0; 115862306a36Sopenharmony_ci sd->vstart = 1; 115962306a36Sopenharmony_ci} 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_cistatic void mt9v_init_sensor(struct gspca_dev *gspca_dev) 116262306a36Sopenharmony_ci{ 116362306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 116462306a36Sopenharmony_ci u16 value; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci sd->i2c_addr = 0x5d; 116762306a36Sopenharmony_ci i2c_r2(gspca_dev, 0xff, &value); 116862306a36Sopenharmony_ci if (gspca_dev->usb_err >= 0 116962306a36Sopenharmony_ci && value == 0x8243) { 117062306a36Sopenharmony_ci i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init)); 117162306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) { 117262306a36Sopenharmony_ci pr_err("MT9V011 sensor initialization failed\n"); 117362306a36Sopenharmony_ci return; 117462306a36Sopenharmony_ci } 117562306a36Sopenharmony_ci sd->hstart = 2; 117662306a36Sopenharmony_ci sd->vstart = 2; 117762306a36Sopenharmony_ci sd->sensor = SENSOR_MT9V011; 117862306a36Sopenharmony_ci pr_info("MT9V011 sensor detected\n"); 117962306a36Sopenharmony_ci return; 118062306a36Sopenharmony_ci } 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci gspca_dev->usb_err = 0; 118362306a36Sopenharmony_ci sd->i2c_addr = 0x5c; 118462306a36Sopenharmony_ci i2c_w2(gspca_dev, 0x01, 0x0004); 118562306a36Sopenharmony_ci i2c_r2(gspca_dev, 0xff, &value); 118662306a36Sopenharmony_ci if (gspca_dev->usb_err >= 0 118762306a36Sopenharmony_ci && value == 0x823a) { 118862306a36Sopenharmony_ci i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init)); 118962306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) { 119062306a36Sopenharmony_ci pr_err("MT9V111 sensor initialization failed\n"); 119162306a36Sopenharmony_ci return; 119262306a36Sopenharmony_ci } 119362306a36Sopenharmony_ci sd->hstart = 2; 119462306a36Sopenharmony_ci sd->vstart = 2; 119562306a36Sopenharmony_ci sd->sensor = SENSOR_MT9V111; 119662306a36Sopenharmony_ci pr_info("MT9V111 sensor detected\n"); 119762306a36Sopenharmony_ci return; 119862306a36Sopenharmony_ci } 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci gspca_dev->usb_err = 0; 120162306a36Sopenharmony_ci sd->i2c_addr = 0x5d; 120262306a36Sopenharmony_ci i2c_w2(gspca_dev, 0xf0, 0x0000); 120362306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) { 120462306a36Sopenharmony_ci gspca_dev->usb_err = 0; 120562306a36Sopenharmony_ci sd->i2c_addr = 0x48; 120662306a36Sopenharmony_ci i2c_w2(gspca_dev, 0xf0, 0x0000); 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci i2c_r2(gspca_dev, 0x00, &value); 120962306a36Sopenharmony_ci if (gspca_dev->usb_err >= 0 121062306a36Sopenharmony_ci && value == 0x1229) { 121162306a36Sopenharmony_ci i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init)); 121262306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) { 121362306a36Sopenharmony_ci pr_err("MT9V112 sensor initialization failed\n"); 121462306a36Sopenharmony_ci return; 121562306a36Sopenharmony_ci } 121662306a36Sopenharmony_ci sd->hstart = 6; 121762306a36Sopenharmony_ci sd->vstart = 2; 121862306a36Sopenharmony_ci sd->sensor = SENSOR_MT9V112; 121962306a36Sopenharmony_ci pr_info("MT9V112 sensor detected\n"); 122062306a36Sopenharmony_ci return; 122162306a36Sopenharmony_ci } 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci gspca_dev->usb_err = -ENODEV; 122462306a36Sopenharmony_ci} 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_cistatic void mt9m112_init_sensor(struct gspca_dev *gspca_dev) 122762306a36Sopenharmony_ci{ 122862306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init)); 123162306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 123262306a36Sopenharmony_ci pr_err("MT9M112 sensor initialization failed\n"); 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci sd->hstart = 0; 123562306a36Sopenharmony_ci sd->vstart = 2; 123662306a36Sopenharmony_ci} 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_cistatic void mt9m111_init_sensor(struct gspca_dev *gspca_dev) 123962306a36Sopenharmony_ci{ 124062306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init)); 124362306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 124462306a36Sopenharmony_ci pr_err("MT9M111 sensor initialization failed\n"); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci sd->hstart = 0; 124762306a36Sopenharmony_ci sd->vstart = 2; 124862306a36Sopenharmony_ci} 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_cistatic void mt9m001_init_sensor(struct gspca_dev *gspca_dev) 125162306a36Sopenharmony_ci{ 125262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 125362306a36Sopenharmony_ci u16 id; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci i2c_r2(gspca_dev, 0x00, &id); 125662306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 125762306a36Sopenharmony_ci return; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ 126062306a36Sopenharmony_ci switch (id) { 126162306a36Sopenharmony_ci case 0x8411: 126262306a36Sopenharmony_ci case 0x8421: 126362306a36Sopenharmony_ci pr_info("MT9M001 color sensor detected\n"); 126462306a36Sopenharmony_ci break; 126562306a36Sopenharmony_ci case 0x8431: 126662306a36Sopenharmony_ci pr_info("MT9M001 mono sensor detected\n"); 126762306a36Sopenharmony_ci break; 126862306a36Sopenharmony_ci default: 126962306a36Sopenharmony_ci pr_err("No MT9M001 chip detected, ID = %x\n\n", id); 127062306a36Sopenharmony_ci gspca_dev->usb_err = -ENODEV; 127162306a36Sopenharmony_ci return; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init)); 127562306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 127662306a36Sopenharmony_ci pr_err("MT9M001 sensor initialization failed\n"); 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci sd->hstart = 1; 127962306a36Sopenharmony_ci sd->vstart = 1; 128062306a36Sopenharmony_ci} 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_cistatic void hv7131r_init_sensor(struct gspca_dev *gspca_dev) 128362306a36Sopenharmony_ci{ 128462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init)); 128762306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 128862306a36Sopenharmony_ci pr_err("HV7131R Sensor initialization failed\n"); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci sd->hstart = 0; 129162306a36Sopenharmony_ci sd->vstart = 1; 129262306a36Sopenharmony_ci} 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_cistatic void set_cmatrix(struct gspca_dev *gspca_dev, 129562306a36Sopenharmony_ci s32 brightness, s32 contrast, s32 satur, s32 hue) 129662306a36Sopenharmony_ci{ 129762306a36Sopenharmony_ci s32 hue_coord, hue_index = 180 + hue; 129862306a36Sopenharmony_ci u8 cmatrix[21]; 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci memset(cmatrix, 0, sizeof(cmatrix)); 130162306a36Sopenharmony_ci cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26; 130262306a36Sopenharmony_ci cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; 130362306a36Sopenharmony_ci cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; 130462306a36Sopenharmony_ci cmatrix[18] = brightness - 0x80; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci hue_coord = (hsv_red_x[hue_index] * satur) >> 8; 130762306a36Sopenharmony_ci cmatrix[6] = hue_coord; 130862306a36Sopenharmony_ci cmatrix[7] = (hue_coord >> 8) & 0x0f; 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci hue_coord = (hsv_red_y[hue_index] * satur) >> 8; 131162306a36Sopenharmony_ci cmatrix[8] = hue_coord; 131262306a36Sopenharmony_ci cmatrix[9] = (hue_coord >> 8) & 0x0f; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci hue_coord = (hsv_green_x[hue_index] * satur) >> 8; 131562306a36Sopenharmony_ci cmatrix[10] = hue_coord; 131662306a36Sopenharmony_ci cmatrix[11] = (hue_coord >> 8) & 0x0f; 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci hue_coord = (hsv_green_y[hue_index] * satur) >> 8; 131962306a36Sopenharmony_ci cmatrix[12] = hue_coord; 132062306a36Sopenharmony_ci cmatrix[13] = (hue_coord >> 8) & 0x0f; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci hue_coord = (hsv_blue_x[hue_index] * satur) >> 8; 132362306a36Sopenharmony_ci cmatrix[14] = hue_coord; 132462306a36Sopenharmony_ci cmatrix[15] = (hue_coord >> 8) & 0x0f; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci hue_coord = (hsv_blue_y[hue_index] * satur) >> 8; 132762306a36Sopenharmony_ci cmatrix[16] = hue_coord; 132862306a36Sopenharmony_ci cmatrix[17] = (hue_coord >> 8) & 0x0f; 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci reg_w(gspca_dev, 0x10e1, cmatrix, 21); 133162306a36Sopenharmony_ci} 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_cistatic void set_gamma(struct gspca_dev *gspca_dev, s32 val) 133462306a36Sopenharmony_ci{ 133562306a36Sopenharmony_ci u8 gamma[17]; 133662306a36Sopenharmony_ci u8 gval = val * 0xb8 / 0x100; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci gamma[0] = 0x0a; 133962306a36Sopenharmony_ci gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); 134062306a36Sopenharmony_ci gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8); 134162306a36Sopenharmony_ci gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8); 134262306a36Sopenharmony_ci gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8); 134362306a36Sopenharmony_ci gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8); 134462306a36Sopenharmony_ci gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8); 134562306a36Sopenharmony_ci gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8); 134662306a36Sopenharmony_ci gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8); 134762306a36Sopenharmony_ci gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8); 134862306a36Sopenharmony_ci gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8); 134962306a36Sopenharmony_ci gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8); 135062306a36Sopenharmony_ci gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8); 135162306a36Sopenharmony_ci gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8); 135262306a36Sopenharmony_ci gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8); 135362306a36Sopenharmony_ci gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); 135462306a36Sopenharmony_ci gamma[16] = 0xf5; 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci reg_w(gspca_dev, 0x1190, gamma, 17); 135762306a36Sopenharmony_ci} 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_cistatic void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red) 136062306a36Sopenharmony_ci{ 136162306a36Sopenharmony_ci reg_w1(gspca_dev, 0x118c, red); 136262306a36Sopenharmony_ci reg_w1(gspca_dev, 0x118f, blue); 136362306a36Sopenharmony_ci} 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_cistatic void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) 136662306a36Sopenharmony_ci{ 136762306a36Sopenharmony_ci u8 value, tslb; 136862306a36Sopenharmony_ci u16 value2; 136962306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { 137262306a36Sopenharmony_ci hflip = !hflip; 137362306a36Sopenharmony_ci vflip = !vflip; 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci switch (sd->sensor) { 137762306a36Sopenharmony_ci case SENSOR_OV7660: 137862306a36Sopenharmony_ci value = 0x01; 137962306a36Sopenharmony_ci if (hflip) 138062306a36Sopenharmony_ci value |= 0x20; 138162306a36Sopenharmony_ci if (vflip) { 138262306a36Sopenharmony_ci value |= 0x10; 138362306a36Sopenharmony_ci sd->vstart = 2; 138462306a36Sopenharmony_ci } else { 138562306a36Sopenharmony_ci sd->vstart = 3; 138662306a36Sopenharmony_ci } 138762306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1182, sd->vstart); 138862306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x1e, value); 138962306a36Sopenharmony_ci break; 139062306a36Sopenharmony_ci case SENSOR_OV9650: 139162306a36Sopenharmony_ci i2c_r1(gspca_dev, 0x1e, &value); 139262306a36Sopenharmony_ci value &= ~0x30; 139362306a36Sopenharmony_ci tslb = 0x01; 139462306a36Sopenharmony_ci if (hflip) 139562306a36Sopenharmony_ci value |= 0x20; 139662306a36Sopenharmony_ci if (vflip) { 139762306a36Sopenharmony_ci value |= 0x10; 139862306a36Sopenharmony_ci tslb = 0x49; 139962306a36Sopenharmony_ci } 140062306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x1e, value); 140162306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x3a, tslb); 140262306a36Sopenharmony_ci break; 140362306a36Sopenharmony_ci case SENSOR_MT9V111: 140462306a36Sopenharmony_ci case SENSOR_MT9V011: 140562306a36Sopenharmony_ci i2c_r2(gspca_dev, 0x20, &value2); 140662306a36Sopenharmony_ci value2 &= ~0xc0a0; 140762306a36Sopenharmony_ci if (hflip) 140862306a36Sopenharmony_ci value2 |= 0x8080; 140962306a36Sopenharmony_ci if (vflip) 141062306a36Sopenharmony_ci value2 |= 0x4020; 141162306a36Sopenharmony_ci i2c_w2(gspca_dev, 0x20, value2); 141262306a36Sopenharmony_ci break; 141362306a36Sopenharmony_ci case SENSOR_MT9M112: 141462306a36Sopenharmony_ci case SENSOR_MT9M111: 141562306a36Sopenharmony_ci case SENSOR_MT9V112: 141662306a36Sopenharmony_ci i2c_r2(gspca_dev, 0x20, &value2); 141762306a36Sopenharmony_ci value2 &= ~0x0003; 141862306a36Sopenharmony_ci if (hflip) 141962306a36Sopenharmony_ci value2 |= 0x0002; 142062306a36Sopenharmony_ci if (vflip) 142162306a36Sopenharmony_ci value2 |= 0x0001; 142262306a36Sopenharmony_ci i2c_w2(gspca_dev, 0x20, value2); 142362306a36Sopenharmony_ci break; 142462306a36Sopenharmony_ci case SENSOR_HV7131R: 142562306a36Sopenharmony_ci i2c_r1(gspca_dev, 0x01, &value); 142662306a36Sopenharmony_ci value &= ~0x03; 142762306a36Sopenharmony_ci if (vflip) 142862306a36Sopenharmony_ci value |= 0x01; 142962306a36Sopenharmony_ci if (hflip) 143062306a36Sopenharmony_ci value |= 0x02; 143162306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x01, value); 143262306a36Sopenharmony_ci break; 143362306a36Sopenharmony_ci } 143462306a36Sopenharmony_ci} 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_cistatic void set_exposure(struct gspca_dev *gspca_dev, s32 expo) 143762306a36Sopenharmony_ci{ 143862306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 143962306a36Sopenharmony_ci u8 exp[8] = {sd->i2c_intf, sd->i2c_addr, 144062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 144162306a36Sopenharmony_ci int expo2; 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci if (gspca_dev->streaming) 144462306a36Sopenharmony_ci exp[7] = 0x1e; 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci switch (sd->sensor) { 144762306a36Sopenharmony_ci case SENSOR_OV7660: 144862306a36Sopenharmony_ci case SENSOR_OV7670: 144962306a36Sopenharmony_ci case SENSOR_OV9655: 145062306a36Sopenharmony_ci case SENSOR_OV9650: 145162306a36Sopenharmony_ci if (expo > 547) 145262306a36Sopenharmony_ci expo2 = 547; 145362306a36Sopenharmony_ci else 145462306a36Sopenharmony_ci expo2 = expo; 145562306a36Sopenharmony_ci exp[0] |= (2 << 4); 145662306a36Sopenharmony_ci exp[2] = 0x10; /* AECH */ 145762306a36Sopenharmony_ci exp[3] = expo2 >> 2; 145862306a36Sopenharmony_ci exp[7] = 0x10; 145962306a36Sopenharmony_ci i2c_w(gspca_dev, exp); 146062306a36Sopenharmony_ci exp[2] = 0x04; /* COM1 */ 146162306a36Sopenharmony_ci exp[3] = expo2 & 0x0003; 146262306a36Sopenharmony_ci exp[7] = 0x10; 146362306a36Sopenharmony_ci i2c_w(gspca_dev, exp); 146462306a36Sopenharmony_ci expo -= expo2; 146562306a36Sopenharmony_ci exp[7] = 0x1e; 146662306a36Sopenharmony_ci exp[0] |= (3 << 4); 146762306a36Sopenharmony_ci exp[2] = 0x2d; /* ADVFL & ADVFH */ 146862306a36Sopenharmony_ci exp[3] = expo; 146962306a36Sopenharmony_ci exp[4] = expo >> 8; 147062306a36Sopenharmony_ci break; 147162306a36Sopenharmony_ci case SENSOR_MT9M001: 147262306a36Sopenharmony_ci case SENSOR_MT9V112: 147362306a36Sopenharmony_ci case SENSOR_MT9V011: 147462306a36Sopenharmony_ci exp[0] |= (3 << 4); 147562306a36Sopenharmony_ci exp[2] = 0x09; 147662306a36Sopenharmony_ci exp[3] = expo >> 8; 147762306a36Sopenharmony_ci exp[4] = expo; 147862306a36Sopenharmony_ci break; 147962306a36Sopenharmony_ci case SENSOR_HV7131R: 148062306a36Sopenharmony_ci exp[0] |= (4 << 4); 148162306a36Sopenharmony_ci exp[2] = 0x25; 148262306a36Sopenharmony_ci exp[3] = expo >> 5; 148362306a36Sopenharmony_ci exp[4] = expo << 3; 148462306a36Sopenharmony_ci exp[5] = 0; 148562306a36Sopenharmony_ci break; 148662306a36Sopenharmony_ci default: 148762306a36Sopenharmony_ci return; 148862306a36Sopenharmony_ci } 148962306a36Sopenharmony_ci i2c_w(gspca_dev, exp); 149062306a36Sopenharmony_ci} 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_cistatic void set_gain(struct gspca_dev *gspca_dev, s32 g) 149362306a36Sopenharmony_ci{ 149462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 149562306a36Sopenharmony_ci u8 gain[8] = {sd->i2c_intf, sd->i2c_addr, 149662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci if (gspca_dev->streaming) 149962306a36Sopenharmony_ci gain[7] = 0x15; /* or 1d ? */ 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci switch (sd->sensor) { 150262306a36Sopenharmony_ci case SENSOR_OV7660: 150362306a36Sopenharmony_ci case SENSOR_OV7670: 150462306a36Sopenharmony_ci case SENSOR_SOI968: 150562306a36Sopenharmony_ci case SENSOR_OV9655: 150662306a36Sopenharmony_ci case SENSOR_OV9650: 150762306a36Sopenharmony_ci gain[0] |= (2 << 4); 150862306a36Sopenharmony_ci gain[3] = ov_gain[g]; 150962306a36Sopenharmony_ci break; 151062306a36Sopenharmony_ci case SENSOR_MT9V011: 151162306a36Sopenharmony_ci gain[0] |= (3 << 4); 151262306a36Sopenharmony_ci gain[2] = 0x35; 151362306a36Sopenharmony_ci gain[3] = micron1_gain[g] >> 8; 151462306a36Sopenharmony_ci gain[4] = micron1_gain[g]; 151562306a36Sopenharmony_ci break; 151662306a36Sopenharmony_ci case SENSOR_MT9V112: 151762306a36Sopenharmony_ci gain[0] |= (3 << 4); 151862306a36Sopenharmony_ci gain[2] = 0x2f; 151962306a36Sopenharmony_ci gain[3] = micron1_gain[g] >> 8; 152062306a36Sopenharmony_ci gain[4] = micron1_gain[g]; 152162306a36Sopenharmony_ci break; 152262306a36Sopenharmony_ci case SENSOR_MT9M001: 152362306a36Sopenharmony_ci gain[0] |= (3 << 4); 152462306a36Sopenharmony_ci gain[2] = 0x2f; 152562306a36Sopenharmony_ci gain[3] = micron2_gain[g] >> 8; 152662306a36Sopenharmony_ci gain[4] = micron2_gain[g]; 152762306a36Sopenharmony_ci break; 152862306a36Sopenharmony_ci case SENSOR_HV7131R: 152962306a36Sopenharmony_ci gain[0] |= (2 << 4); 153062306a36Sopenharmony_ci gain[2] = 0x30; 153162306a36Sopenharmony_ci gain[3] = hv7131r_gain[g]; 153262306a36Sopenharmony_ci break; 153362306a36Sopenharmony_ci default: 153462306a36Sopenharmony_ci return; 153562306a36Sopenharmony_ci } 153662306a36Sopenharmony_ci i2c_w(gspca_dev, gain); 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_cistatic void set_led_mode(struct gspca_dev *gspca_dev, s32 val) 154062306a36Sopenharmony_ci{ 154162306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1007, 0x60); 154262306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1006, val ? 0x40 : 0x00); 154362306a36Sopenharmony_ci} 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_cistatic void set_quality(struct gspca_dev *gspca_dev, s32 val) 154662306a36Sopenharmony_ci{ 154762306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci jpeg_set_qual(sd->jpeg_hdr, val); 155062306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ 155162306a36Sopenharmony_ci reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ 155262306a36Sopenharmony_ci reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); 155362306a36Sopenharmony_ci reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); 155462306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ 155562306a36Sopenharmony_ci reg_w1(gspca_dev, 0x10e0, sd->fmt); 155662306a36Sopenharmony_ci sd->fmt ^= 0x0c; /* invert QTAB use + write */ 155762306a36Sopenharmony_ci reg_w1(gspca_dev, 0x10e0, sd->fmt); 155862306a36Sopenharmony_ci} 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 156162306a36Sopenharmony_cistatic int sd_dbg_g_register(struct gspca_dev *gspca_dev, 156262306a36Sopenharmony_ci struct v4l2_dbg_register *reg) 156362306a36Sopenharmony_ci{ 156462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci reg->size = 1; 156762306a36Sopenharmony_ci switch (reg->match.addr) { 156862306a36Sopenharmony_ci case 0: 156962306a36Sopenharmony_ci if (reg->reg < 0x1000 || reg->reg > 0x11ff) 157062306a36Sopenharmony_ci return -EINVAL; 157162306a36Sopenharmony_ci reg_r(gspca_dev, reg->reg, 1); 157262306a36Sopenharmony_ci reg->val = gspca_dev->usb_buf[0]; 157362306a36Sopenharmony_ci return gspca_dev->usb_err; 157462306a36Sopenharmony_ci case 1: 157562306a36Sopenharmony_ci if (sd->sensor >= SENSOR_MT9V011 && 157662306a36Sopenharmony_ci sd->sensor <= SENSOR_MT9M112) { 157762306a36Sopenharmony_ci i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); 157862306a36Sopenharmony_ci reg->size = 2; 157962306a36Sopenharmony_ci } else { 158062306a36Sopenharmony_ci i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); 158162306a36Sopenharmony_ci } 158262306a36Sopenharmony_ci return gspca_dev->usb_err; 158362306a36Sopenharmony_ci } 158462306a36Sopenharmony_ci return -EINVAL; 158562306a36Sopenharmony_ci} 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_cistatic int sd_dbg_s_register(struct gspca_dev *gspca_dev, 158862306a36Sopenharmony_ci const struct v4l2_dbg_register *reg) 158962306a36Sopenharmony_ci{ 159062306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci switch (reg->match.addr) { 159362306a36Sopenharmony_ci case 0: 159462306a36Sopenharmony_ci if (reg->reg < 0x1000 || reg->reg > 0x11ff) 159562306a36Sopenharmony_ci return -EINVAL; 159662306a36Sopenharmony_ci reg_w1(gspca_dev, reg->reg, reg->val); 159762306a36Sopenharmony_ci return gspca_dev->usb_err; 159862306a36Sopenharmony_ci case 1: 159962306a36Sopenharmony_ci if (sd->sensor >= SENSOR_MT9V011 && 160062306a36Sopenharmony_ci sd->sensor <= SENSOR_MT9M112) { 160162306a36Sopenharmony_ci i2c_w2(gspca_dev, reg->reg, reg->val); 160262306a36Sopenharmony_ci } else { 160362306a36Sopenharmony_ci i2c_w1(gspca_dev, reg->reg, reg->val); 160462306a36Sopenharmony_ci } 160562306a36Sopenharmony_ci return gspca_dev->usb_err; 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci return -EINVAL; 160862306a36Sopenharmony_ci} 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_cistatic int sd_chip_info(struct gspca_dev *gspca_dev, 161162306a36Sopenharmony_ci struct v4l2_dbg_chip_info *chip) 161262306a36Sopenharmony_ci{ 161362306a36Sopenharmony_ci if (chip->match.addr > 1) 161462306a36Sopenharmony_ci return -EINVAL; 161562306a36Sopenharmony_ci if (chip->match.addr == 1) 161662306a36Sopenharmony_ci strscpy(chip->name, "sensor", sizeof(chip->name)); 161762306a36Sopenharmony_ci return 0; 161862306a36Sopenharmony_ci} 161962306a36Sopenharmony_ci#endif 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev, 162262306a36Sopenharmony_ci const struct usb_device_id *id) 162362306a36Sopenharmony_ci{ 162462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 162562306a36Sopenharmony_ci struct cam *cam; 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci cam = &gspca_dev->cam; 162862306a36Sopenharmony_ci cam->needs_full_bandwidth = 1; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci sd->sensor = id->driver_info >> 8; 163162306a36Sopenharmony_ci sd->i2c_addr = id->driver_info; 163262306a36Sopenharmony_ci sd->flags = id->driver_info >> 16; 163362306a36Sopenharmony_ci sd->i2c_intf = 0x80; /* i2c 100 Kb/s */ 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_ci switch (sd->sensor) { 163662306a36Sopenharmony_ci case SENSOR_MT9M112: 163762306a36Sopenharmony_ci case SENSOR_MT9M111: 163862306a36Sopenharmony_ci case SENSOR_OV9650: 163962306a36Sopenharmony_ci case SENSOR_SOI968: 164062306a36Sopenharmony_ci cam->cam_mode = sxga_mode; 164162306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(sxga_mode); 164262306a36Sopenharmony_ci break; 164362306a36Sopenharmony_ci case SENSOR_MT9M001: 164462306a36Sopenharmony_ci cam->cam_mode = mono_mode; 164562306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(mono_mode); 164662306a36Sopenharmony_ci break; 164762306a36Sopenharmony_ci case SENSOR_HV7131R: 164862306a36Sopenharmony_ci sd->i2c_intf = 0x81; /* i2c 400 Kb/s */ 164962306a36Sopenharmony_ci fallthrough; 165062306a36Sopenharmony_ci default: 165162306a36Sopenharmony_ci cam->cam_mode = vga_mode; 165262306a36Sopenharmony_ci cam->nmodes = ARRAY_SIZE(vga_mode); 165362306a36Sopenharmony_ci break; 165462306a36Sopenharmony_ci } 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci sd->old_step = 0; 165762306a36Sopenharmony_ci sd->older_step = 0; 165862306a36Sopenharmony_ci sd->exposure_step = 16; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci INIT_WORK(&sd->work, qual_upd); 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci return 0; 166362306a36Sopenharmony_ci} 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl) 166662306a36Sopenharmony_ci{ 166762306a36Sopenharmony_ci struct gspca_dev *gspca_dev = 166862306a36Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 166962306a36Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci gspca_dev->usb_err = 0; 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci if (!gspca_dev->streaming) 167462306a36Sopenharmony_ci return 0; 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci switch (ctrl->id) { 167762306a36Sopenharmony_ci /* color control cluster */ 167862306a36Sopenharmony_ci case V4L2_CID_BRIGHTNESS: 167962306a36Sopenharmony_ci set_cmatrix(gspca_dev, sd->brightness->val, 168062306a36Sopenharmony_ci sd->contrast->val, sd->saturation->val, sd->hue->val); 168162306a36Sopenharmony_ci break; 168262306a36Sopenharmony_ci case V4L2_CID_GAMMA: 168362306a36Sopenharmony_ci set_gamma(gspca_dev, ctrl->val); 168462306a36Sopenharmony_ci break; 168562306a36Sopenharmony_ci /* blue/red balance cluster */ 168662306a36Sopenharmony_ci case V4L2_CID_BLUE_BALANCE: 168762306a36Sopenharmony_ci set_redblue(gspca_dev, sd->blue->val, sd->red->val); 168862306a36Sopenharmony_ci break; 168962306a36Sopenharmony_ci /* h/vflip cluster */ 169062306a36Sopenharmony_ci case V4L2_CID_HFLIP: 169162306a36Sopenharmony_ci set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val); 169262306a36Sopenharmony_ci break; 169362306a36Sopenharmony_ci /* standalone exposure control */ 169462306a36Sopenharmony_ci case V4L2_CID_EXPOSURE: 169562306a36Sopenharmony_ci set_exposure(gspca_dev, ctrl->val); 169662306a36Sopenharmony_ci break; 169762306a36Sopenharmony_ci /* standalone gain control */ 169862306a36Sopenharmony_ci case V4L2_CID_GAIN: 169962306a36Sopenharmony_ci set_gain(gspca_dev, ctrl->val); 170062306a36Sopenharmony_ci break; 170162306a36Sopenharmony_ci /* autogain + exposure or gain control cluster */ 170262306a36Sopenharmony_ci case V4L2_CID_AUTOGAIN: 170362306a36Sopenharmony_ci if (sd->sensor == SENSOR_SOI968) 170462306a36Sopenharmony_ci set_gain(gspca_dev, sd->gain->val); 170562306a36Sopenharmony_ci else 170662306a36Sopenharmony_ci set_exposure(gspca_dev, sd->exposure->val); 170762306a36Sopenharmony_ci break; 170862306a36Sopenharmony_ci case V4L2_CID_JPEG_COMPRESSION_QUALITY: 170962306a36Sopenharmony_ci set_quality(gspca_dev, ctrl->val); 171062306a36Sopenharmony_ci break; 171162306a36Sopenharmony_ci case V4L2_CID_FLASH_LED_MODE: 171262306a36Sopenharmony_ci set_led_mode(gspca_dev, ctrl->val); 171362306a36Sopenharmony_ci break; 171462306a36Sopenharmony_ci } 171562306a36Sopenharmony_ci return gspca_dev->usb_err; 171662306a36Sopenharmony_ci} 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = { 171962306a36Sopenharmony_ci .s_ctrl = sd_s_ctrl, 172062306a36Sopenharmony_ci}; 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev) 172362306a36Sopenharmony_ci{ 172462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 172562306a36Sopenharmony_ci struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci gspca_dev->vdev.ctrl_handler = hdl; 172862306a36Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 13); 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 173162306a36Sopenharmony_ci V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); 173262306a36Sopenharmony_ci sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 173362306a36Sopenharmony_ci V4L2_CID_CONTRAST, 0, 255, 1, 127); 173462306a36Sopenharmony_ci sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 173562306a36Sopenharmony_ci V4L2_CID_SATURATION, 0, 255, 1, 127); 173662306a36Sopenharmony_ci sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 173762306a36Sopenharmony_ci V4L2_CID_HUE, -180, 180, 1, 0); 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 174062306a36Sopenharmony_ci V4L2_CID_GAMMA, 0, 255, 1, 0x10); 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 174362306a36Sopenharmony_ci V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28); 174462306a36Sopenharmony_ci sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 174562306a36Sopenharmony_ci V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28); 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 && 174862306a36Sopenharmony_ci sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 && 174962306a36Sopenharmony_ci sd->sensor != SENSOR_MT9VPRB) { 175062306a36Sopenharmony_ci sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 175162306a36Sopenharmony_ci V4L2_CID_HFLIP, 0, 1, 1, 0); 175262306a36Sopenharmony_ci sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 175362306a36Sopenharmony_ci V4L2_CID_VFLIP, 0, 1, 1, 0); 175462306a36Sopenharmony_ci } 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB && 175762306a36Sopenharmony_ci sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 && 175862306a36Sopenharmony_ci sd->sensor != SENSOR_MT9V111) 175962306a36Sopenharmony_ci sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 176062306a36Sopenharmony_ci V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33); 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 && 176362306a36Sopenharmony_ci sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) { 176462306a36Sopenharmony_ci sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 176562306a36Sopenharmony_ci V4L2_CID_GAIN, 0, 28, 1, 0); 176662306a36Sopenharmony_ci sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 176762306a36Sopenharmony_ci V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 176862306a36Sopenharmony_ci } 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_ci sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 177162306a36Sopenharmony_ci V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80); 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci if (sd->flags & HAS_LED_TORCH) 177462306a36Sopenharmony_ci sd->led_mode = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, 177562306a36Sopenharmony_ci V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_TORCH, 177662306a36Sopenharmony_ci ~0x5, V4L2_FLASH_LED_MODE_NONE); 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci if (hdl->error) { 177962306a36Sopenharmony_ci pr_err("Could not initialize controls\n"); 178062306a36Sopenharmony_ci return hdl->error; 178162306a36Sopenharmony_ci } 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci v4l2_ctrl_cluster(4, &sd->brightness); 178462306a36Sopenharmony_ci v4l2_ctrl_cluster(2, &sd->blue); 178562306a36Sopenharmony_ci if (sd->hflip) 178662306a36Sopenharmony_ci v4l2_ctrl_cluster(2, &sd->hflip); 178762306a36Sopenharmony_ci if (sd->autogain) { 178862306a36Sopenharmony_ci if (sd->sensor == SENSOR_SOI968) 178962306a36Sopenharmony_ci /* this sensor doesn't have the exposure control and 179062306a36Sopenharmony_ci autogain is clustered with gain instead. This works 179162306a36Sopenharmony_ci because sd->exposure == NULL. */ 179262306a36Sopenharmony_ci v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false); 179362306a36Sopenharmony_ci else 179462306a36Sopenharmony_ci /* Otherwise autogain is clustered with exposure. */ 179562306a36Sopenharmony_ci v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false); 179662306a36Sopenharmony_ci } 179762306a36Sopenharmony_ci return 0; 179862306a36Sopenharmony_ci} 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev) 180162306a36Sopenharmony_ci{ 180262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 180362306a36Sopenharmony_ci int i; 180462306a36Sopenharmony_ci u8 value; 180562306a36Sopenharmony_ci u8 i2c_init[9] = { 180662306a36Sopenharmony_ci 0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 180762306a36Sopenharmony_ci }; 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { 181062306a36Sopenharmony_ci value = bridge_init[i][1]; 181162306a36Sopenharmony_ci reg_w(gspca_dev, bridge_init[i][0], &value, 1); 181262306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) { 181362306a36Sopenharmony_ci pr_err("Device initialization failed\n"); 181462306a36Sopenharmony_ci return gspca_dev->usb_err; 181562306a36Sopenharmony_ci } 181662306a36Sopenharmony_ci } 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci if (sd->flags & LED_REVERSE) 181962306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1006, 0x00); 182062306a36Sopenharmony_ci else 182162306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1006, 0x20); 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci reg_w(gspca_dev, 0x10c0, i2c_init, 9); 182462306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) { 182562306a36Sopenharmony_ci pr_err("Device initialization failed\n"); 182662306a36Sopenharmony_ci return gspca_dev->usb_err; 182762306a36Sopenharmony_ci } 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci switch (sd->sensor) { 183062306a36Sopenharmony_ci case SENSOR_OV9650: 183162306a36Sopenharmony_ci ov9650_init_sensor(gspca_dev); 183262306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 183362306a36Sopenharmony_ci break; 183462306a36Sopenharmony_ci pr_info("OV9650 sensor detected\n"); 183562306a36Sopenharmony_ci break; 183662306a36Sopenharmony_ci case SENSOR_OV9655: 183762306a36Sopenharmony_ci ov9655_init_sensor(gspca_dev); 183862306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 183962306a36Sopenharmony_ci break; 184062306a36Sopenharmony_ci pr_info("OV9655 sensor detected\n"); 184162306a36Sopenharmony_ci break; 184262306a36Sopenharmony_ci case SENSOR_SOI968: 184362306a36Sopenharmony_ci soi968_init_sensor(gspca_dev); 184462306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 184562306a36Sopenharmony_ci break; 184662306a36Sopenharmony_ci pr_info("SOI968 sensor detected\n"); 184762306a36Sopenharmony_ci break; 184862306a36Sopenharmony_ci case SENSOR_OV7660: 184962306a36Sopenharmony_ci ov7660_init_sensor(gspca_dev); 185062306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 185162306a36Sopenharmony_ci break; 185262306a36Sopenharmony_ci pr_info("OV7660 sensor detected\n"); 185362306a36Sopenharmony_ci break; 185462306a36Sopenharmony_ci case SENSOR_OV7670: 185562306a36Sopenharmony_ci ov7670_init_sensor(gspca_dev); 185662306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 185762306a36Sopenharmony_ci break; 185862306a36Sopenharmony_ci pr_info("OV7670 sensor detected\n"); 185962306a36Sopenharmony_ci break; 186062306a36Sopenharmony_ci case SENSOR_MT9VPRB: 186162306a36Sopenharmony_ci mt9v_init_sensor(gspca_dev); 186262306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 186362306a36Sopenharmony_ci break; 186462306a36Sopenharmony_ci pr_info("MT9VPRB sensor detected\n"); 186562306a36Sopenharmony_ci break; 186662306a36Sopenharmony_ci case SENSOR_MT9M111: 186762306a36Sopenharmony_ci mt9m111_init_sensor(gspca_dev); 186862306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 186962306a36Sopenharmony_ci break; 187062306a36Sopenharmony_ci pr_info("MT9M111 sensor detected\n"); 187162306a36Sopenharmony_ci break; 187262306a36Sopenharmony_ci case SENSOR_MT9M112: 187362306a36Sopenharmony_ci mt9m112_init_sensor(gspca_dev); 187462306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 187562306a36Sopenharmony_ci break; 187662306a36Sopenharmony_ci pr_info("MT9M112 sensor detected\n"); 187762306a36Sopenharmony_ci break; 187862306a36Sopenharmony_ci case SENSOR_MT9M001: 187962306a36Sopenharmony_ci mt9m001_init_sensor(gspca_dev); 188062306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 188162306a36Sopenharmony_ci break; 188262306a36Sopenharmony_ci break; 188362306a36Sopenharmony_ci case SENSOR_HV7131R: 188462306a36Sopenharmony_ci hv7131r_init_sensor(gspca_dev); 188562306a36Sopenharmony_ci if (gspca_dev->usb_err < 0) 188662306a36Sopenharmony_ci break; 188762306a36Sopenharmony_ci pr_info("HV7131R sensor detected\n"); 188862306a36Sopenharmony_ci break; 188962306a36Sopenharmony_ci default: 189062306a36Sopenharmony_ci pr_err("Unsupported sensor\n"); 189162306a36Sopenharmony_ci gspca_dev->usb_err = -ENODEV; 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci return gspca_dev->usb_err; 189462306a36Sopenharmony_ci} 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_cistatic void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) 189762306a36Sopenharmony_ci{ 189862306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 189962306a36Sopenharmony_ci u8 value; 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci switch (sd->sensor) { 190262306a36Sopenharmony_ci case SENSOR_SOI968: 190362306a36Sopenharmony_ci if (mode & MODE_SXGA) { 190462306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x17, 0x1d); 190562306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x18, 0xbd); 190662306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x19, 0x01); 190762306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x1a, 0x81); 190862306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, 0x00); 190962306a36Sopenharmony_ci sd->hstart = 140; 191062306a36Sopenharmony_ci sd->vstart = 19; 191162306a36Sopenharmony_ci } else { 191262306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x17, 0x13); 191362306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x18, 0x63); 191462306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x19, 0x01); 191562306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x1a, 0x79); 191662306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, 0x40); 191762306a36Sopenharmony_ci sd->hstart = 60; 191862306a36Sopenharmony_ci sd->vstart = 11; 191962306a36Sopenharmony_ci } 192062306a36Sopenharmony_ci break; 192162306a36Sopenharmony_ci case SENSOR_OV9650: 192262306a36Sopenharmony_ci if (mode & MODE_SXGA) { 192362306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x17, 0x1b); 192462306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x18, 0xbc); 192562306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x19, 0x01); 192662306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x1a, 0x82); 192762306a36Sopenharmony_ci i2c_r1(gspca_dev, 0x12, &value); 192862306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, value & 0x07); 192962306a36Sopenharmony_ci } else { 193062306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x17, 0x24); 193162306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x18, 0xc5); 193262306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x19, 0x00); 193362306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x1a, 0x3c); 193462306a36Sopenharmony_ci i2c_r1(gspca_dev, 0x12, &value); 193562306a36Sopenharmony_ci i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40); 193662306a36Sopenharmony_ci } 193762306a36Sopenharmony_ci break; 193862306a36Sopenharmony_ci case SENSOR_MT9M112: 193962306a36Sopenharmony_ci case SENSOR_MT9M111: 194062306a36Sopenharmony_ci if (mode & MODE_SXGA) { 194162306a36Sopenharmony_ci i2c_w2(gspca_dev, 0xf0, 0x0002); 194262306a36Sopenharmony_ci i2c_w2(gspca_dev, 0xc8, 0x970b); 194362306a36Sopenharmony_ci i2c_w2(gspca_dev, 0xf0, 0x0000); 194462306a36Sopenharmony_ci } else { 194562306a36Sopenharmony_ci i2c_w2(gspca_dev, 0xf0, 0x0002); 194662306a36Sopenharmony_ci i2c_w2(gspca_dev, 0xc8, 0x8000); 194762306a36Sopenharmony_ci i2c_w2(gspca_dev, 0xf0, 0x0000); 194862306a36Sopenharmony_ci } 194962306a36Sopenharmony_ci break; 195062306a36Sopenharmony_ci } 195162306a36Sopenharmony_ci} 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_cistatic int sd_isoc_init(struct gspca_dev *gspca_dev) 195462306a36Sopenharmony_ci{ 195562306a36Sopenharmony_ci struct usb_interface *intf; 195662306a36Sopenharmony_ci u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv; 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci /* 195962306a36Sopenharmony_ci * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth 196062306a36Sopenharmony_ci * than our regular bandwidth calculations reserve, so we force the 196162306a36Sopenharmony_ci * use of a specific altsetting when using the SN9C20X_I420 fmt. 196262306a36Sopenharmony_ci */ 196362306a36Sopenharmony_ci if (!(flags & (MODE_RAW | MODE_JPEG))) { 196462306a36Sopenharmony_ci intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci if (intf->num_altsetting != 9) { 196762306a36Sopenharmony_ci pr_warn("sn9c20x camera with unknown number of alt settings (%d), please report!\n", 196862306a36Sopenharmony_ci intf->num_altsetting); 196962306a36Sopenharmony_ci gspca_dev->alt = intf->num_altsetting; 197062306a36Sopenharmony_ci return 0; 197162306a36Sopenharmony_ci } 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci switch (gspca_dev->pixfmt.width) { 197462306a36Sopenharmony_ci case 160: /* 160x120 */ 197562306a36Sopenharmony_ci gspca_dev->alt = 2; 197662306a36Sopenharmony_ci break; 197762306a36Sopenharmony_ci case 320: /* 320x240 */ 197862306a36Sopenharmony_ci gspca_dev->alt = 6; 197962306a36Sopenharmony_ci break; 198062306a36Sopenharmony_ci default: /* >= 640x480 */ 198162306a36Sopenharmony_ci gspca_dev->alt = 9; 198262306a36Sopenharmony_ci break; 198362306a36Sopenharmony_ci } 198462306a36Sopenharmony_ci } 198562306a36Sopenharmony_ci 198662306a36Sopenharmony_ci return 0; 198762306a36Sopenharmony_ci} 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_ci#define HW_WIN(mode, hstart, vstart) \ 199062306a36Sopenharmony_ci((const u8 []){hstart, 0, vstart, 0, \ 199162306a36Sopenharmony_ci(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ 199262306a36Sopenharmony_ci(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)}) 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci#define CLR_WIN(width, height) \ 199562306a36Sopenharmony_ci((const u8 [])\ 199662306a36Sopenharmony_ci{0, width >> 2, 0, height >> 1,\ 199762306a36Sopenharmony_ci((width >> 10) & 0x01) | ((height >> 8) & 0x6)}) 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev) 200062306a36Sopenharmony_ci{ 200162306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 200262306a36Sopenharmony_ci int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; 200362306a36Sopenharmony_ci int width = gspca_dev->pixfmt.width; 200462306a36Sopenharmony_ci int height = gspca_dev->pixfmt.height; 200562306a36Sopenharmony_ci u8 fmt, scale = 0; 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_ci jpeg_define(sd->jpeg_hdr, height, width, 200862306a36Sopenharmony_ci 0x21); 200962306a36Sopenharmony_ci jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual)); 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_ci if (mode & MODE_RAW) 201262306a36Sopenharmony_ci fmt = 0x2d; 201362306a36Sopenharmony_ci else if (mode & MODE_JPEG) 201462306a36Sopenharmony_ci fmt = 0x24; 201562306a36Sopenharmony_ci else 201662306a36Sopenharmony_ci fmt = 0x2f; /* YUV 420 */ 201762306a36Sopenharmony_ci sd->fmt = fmt; 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci switch (mode & SCALE_MASK) { 202062306a36Sopenharmony_ci case SCALE_1280x1024: 202162306a36Sopenharmony_ci scale = 0xc0; 202262306a36Sopenharmony_ci pr_info("Set 1280x1024\n"); 202362306a36Sopenharmony_ci break; 202462306a36Sopenharmony_ci case SCALE_640x480: 202562306a36Sopenharmony_ci scale = 0x80; 202662306a36Sopenharmony_ci pr_info("Set 640x480\n"); 202762306a36Sopenharmony_ci break; 202862306a36Sopenharmony_ci case SCALE_320x240: 202962306a36Sopenharmony_ci scale = 0x90; 203062306a36Sopenharmony_ci pr_info("Set 320x240\n"); 203162306a36Sopenharmony_ci break; 203262306a36Sopenharmony_ci case SCALE_160x120: 203362306a36Sopenharmony_ci scale = 0xa0; 203462306a36Sopenharmony_ci pr_info("Set 160x120\n"); 203562306a36Sopenharmony_ci break; 203662306a36Sopenharmony_ci } 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci configure_sensor_output(gspca_dev, mode); 203962306a36Sopenharmony_ci reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); 204062306a36Sopenharmony_ci reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); 204162306a36Sopenharmony_ci reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5); 204262306a36Sopenharmony_ci reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6); 204362306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1189, scale); 204462306a36Sopenharmony_ci reg_w1(gspca_dev, 0x10e0, fmt); 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness), 204762306a36Sopenharmony_ci v4l2_ctrl_g_ctrl(sd->contrast), 204862306a36Sopenharmony_ci v4l2_ctrl_g_ctrl(sd->saturation), 204962306a36Sopenharmony_ci v4l2_ctrl_g_ctrl(sd->hue)); 205062306a36Sopenharmony_ci set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma)); 205162306a36Sopenharmony_ci set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue), 205262306a36Sopenharmony_ci v4l2_ctrl_g_ctrl(sd->red)); 205362306a36Sopenharmony_ci if (sd->gain) 205462306a36Sopenharmony_ci set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain)); 205562306a36Sopenharmony_ci if (sd->exposure) 205662306a36Sopenharmony_ci set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure)); 205762306a36Sopenharmony_ci if (sd->hflip) 205862306a36Sopenharmony_ci set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 205962306a36Sopenharmony_ci v4l2_ctrl_g_ctrl(sd->vflip)); 206062306a36Sopenharmony_ci 206162306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1007, 0x20); 206262306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1061, 0x03); 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_ci /* if JPEG, prepare the compression quality update */ 206562306a36Sopenharmony_ci if (mode & MODE_JPEG) { 206662306a36Sopenharmony_ci sd->pktsz = sd->npkt = 0; 206762306a36Sopenharmony_ci sd->nchg = 0; 206862306a36Sopenharmony_ci } 206962306a36Sopenharmony_ci if (sd->led_mode) 207062306a36Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->led_mode, 0); 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci return gspca_dev->usb_err; 207362306a36Sopenharmony_ci} 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev) 207662306a36Sopenharmony_ci{ 207762306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1007, 0x00); 207862306a36Sopenharmony_ci reg_w1(gspca_dev, 0x1061, 0x01); 207962306a36Sopenharmony_ci} 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci/* called on streamoff with alt==0 and on disconnect */ 208262306a36Sopenharmony_ci/* the usb_lock is held at entry - restore on exit */ 208362306a36Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev) 208462306a36Sopenharmony_ci{ 208562306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci mutex_unlock(&gspca_dev->usb_lock); 208862306a36Sopenharmony_ci flush_work(&sd->work); 208962306a36Sopenharmony_ci mutex_lock(&gspca_dev->usb_lock); 209062306a36Sopenharmony_ci} 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_cistatic void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) 209362306a36Sopenharmony_ci{ 209462306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 209562306a36Sopenharmony_ci s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure); 209662306a36Sopenharmony_ci s32 max = sd->exposure->maximum - sd->exposure_step; 209762306a36Sopenharmony_ci s32 min = sd->exposure->minimum + sd->exposure_step; 209862306a36Sopenharmony_ci s16 new_exp; 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci /* 210162306a36Sopenharmony_ci * some hardcoded values are present 210262306a36Sopenharmony_ci * like those for maximal/minimal exposure 210362306a36Sopenharmony_ci * and exposure steps 210462306a36Sopenharmony_ci */ 210562306a36Sopenharmony_ci if (avg_lum < MIN_AVG_LUM) { 210662306a36Sopenharmony_ci if (cur_exp > max) 210762306a36Sopenharmony_ci return; 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci new_exp = cur_exp + sd->exposure_step; 211062306a36Sopenharmony_ci if (new_exp > max) 211162306a36Sopenharmony_ci new_exp = max; 211262306a36Sopenharmony_ci if (new_exp < min) 211362306a36Sopenharmony_ci new_exp = min; 211462306a36Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->exposure, new_exp); 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci sd->older_step = sd->old_step; 211762306a36Sopenharmony_ci sd->old_step = 1; 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci if (sd->old_step ^ sd->older_step) 212062306a36Sopenharmony_ci sd->exposure_step /= 2; 212162306a36Sopenharmony_ci else 212262306a36Sopenharmony_ci sd->exposure_step += 2; 212362306a36Sopenharmony_ci } 212462306a36Sopenharmony_ci if (avg_lum > MAX_AVG_LUM) { 212562306a36Sopenharmony_ci if (cur_exp < min) 212662306a36Sopenharmony_ci return; 212762306a36Sopenharmony_ci new_exp = cur_exp - sd->exposure_step; 212862306a36Sopenharmony_ci if (new_exp > max) 212962306a36Sopenharmony_ci new_exp = max; 213062306a36Sopenharmony_ci if (new_exp < min) 213162306a36Sopenharmony_ci new_exp = min; 213262306a36Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->exposure, new_exp); 213362306a36Sopenharmony_ci sd->older_step = sd->old_step; 213462306a36Sopenharmony_ci sd->old_step = 0; 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_ci if (sd->old_step ^ sd->older_step) 213762306a36Sopenharmony_ci sd->exposure_step /= 2; 213862306a36Sopenharmony_ci else 213962306a36Sopenharmony_ci sd->exposure_step += 2; 214062306a36Sopenharmony_ci } 214162306a36Sopenharmony_ci} 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_cistatic void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) 214462306a36Sopenharmony_ci{ 214562306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 214662306a36Sopenharmony_ci s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain); 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum) 214962306a36Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1); 215062306a36Sopenharmony_ci if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum) 215162306a36Sopenharmony_ci v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1); 215262306a36Sopenharmony_ci} 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_cistatic void sd_dqcallback(struct gspca_dev *gspca_dev) 215562306a36Sopenharmony_ci{ 215662306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 215762306a36Sopenharmony_ci int avg_lum; 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain)) 216062306a36Sopenharmony_ci return; 216162306a36Sopenharmony_ci 216262306a36Sopenharmony_ci avg_lum = atomic_read(&sd->avg_lum); 216362306a36Sopenharmony_ci if (sd->sensor == SENSOR_SOI968) 216462306a36Sopenharmony_ci do_autogain(gspca_dev, avg_lum); 216562306a36Sopenharmony_ci else 216662306a36Sopenharmony_ci do_autoexposure(gspca_dev, avg_lum); 216762306a36Sopenharmony_ci} 216862306a36Sopenharmony_ci 216962306a36Sopenharmony_ci/* JPEG quality update */ 217062306a36Sopenharmony_ci/* This function is executed from a work queue. */ 217162306a36Sopenharmony_cistatic void qual_upd(struct work_struct *work) 217262306a36Sopenharmony_ci{ 217362306a36Sopenharmony_ci struct sd *sd = container_of(work, struct sd, work); 217462306a36Sopenharmony_ci struct gspca_dev *gspca_dev = &sd->gspca_dev; 217562306a36Sopenharmony_ci s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual); 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_ci /* To protect gspca_dev->usb_buf and gspca_dev->usb_err */ 217862306a36Sopenharmony_ci mutex_lock(&gspca_dev->usb_lock); 217962306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "qual_upd %d%%\n", qual); 218062306a36Sopenharmony_ci gspca_dev->usb_err = 0; 218162306a36Sopenharmony_ci set_quality(gspca_dev, qual); 218262306a36Sopenharmony_ci mutex_unlock(&gspca_dev->usb_lock); 218362306a36Sopenharmony_ci} 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT) 218662306a36Sopenharmony_cistatic int sd_int_pkt_scan(struct gspca_dev *gspca_dev, 218762306a36Sopenharmony_ci u8 *data, /* interrupt packet */ 218862306a36Sopenharmony_ci int len) /* interrupt packet length */ 218962306a36Sopenharmony_ci{ 219062306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { 219362306a36Sopenharmony_ci input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); 219462306a36Sopenharmony_ci input_sync(gspca_dev->input_dev); 219562306a36Sopenharmony_ci input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); 219662306a36Sopenharmony_ci input_sync(gspca_dev->input_dev); 219762306a36Sopenharmony_ci return 0; 219862306a36Sopenharmony_ci } 219962306a36Sopenharmony_ci return -EINVAL; 220062306a36Sopenharmony_ci} 220162306a36Sopenharmony_ci#endif 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci/* check the JPEG compression */ 220462306a36Sopenharmony_cistatic void transfer_check(struct gspca_dev *gspca_dev, 220562306a36Sopenharmony_ci u8 *data) 220662306a36Sopenharmony_ci{ 220762306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 220862306a36Sopenharmony_ci int new_qual, r; 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci new_qual = 0; 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_ci /* if USB error, discard the frame and decrease the quality */ 221362306a36Sopenharmony_ci if (data[6] & 0x08) { /* USB FIFO full */ 221462306a36Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 221562306a36Sopenharmony_ci new_qual = -5; 221662306a36Sopenharmony_ci } else { 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_ci /* else, compute the filling rate and a new JPEG quality */ 221962306a36Sopenharmony_ci r = (sd->pktsz * 100) / 222062306a36Sopenharmony_ci (sd->npkt * 222162306a36Sopenharmony_ci gspca_dev->urb[0]->iso_frame_desc[0].length); 222262306a36Sopenharmony_ci if (r >= 85) 222362306a36Sopenharmony_ci new_qual = -3; 222462306a36Sopenharmony_ci else if (r < 75) 222562306a36Sopenharmony_ci new_qual = 2; 222662306a36Sopenharmony_ci } 222762306a36Sopenharmony_ci if (new_qual != 0) { 222862306a36Sopenharmony_ci sd->nchg += new_qual; 222962306a36Sopenharmony_ci if (sd->nchg < -6 || sd->nchg >= 12) { 223062306a36Sopenharmony_ci /* Note: we are in interrupt context, so we can't 223162306a36Sopenharmony_ci use v4l2_ctrl_g/s_ctrl here. Access the value 223262306a36Sopenharmony_ci directly instead. */ 223362306a36Sopenharmony_ci s32 curqual = sd->jpegqual->cur.val; 223462306a36Sopenharmony_ci sd->nchg = 0; 223562306a36Sopenharmony_ci new_qual += curqual; 223662306a36Sopenharmony_ci if (new_qual < sd->jpegqual->minimum) 223762306a36Sopenharmony_ci new_qual = sd->jpegqual->minimum; 223862306a36Sopenharmony_ci else if (new_qual > sd->jpegqual->maximum) 223962306a36Sopenharmony_ci new_qual = sd->jpegqual->maximum; 224062306a36Sopenharmony_ci if (new_qual != curqual) { 224162306a36Sopenharmony_ci sd->jpegqual->cur.val = new_qual; 224262306a36Sopenharmony_ci schedule_work(&sd->work); 224362306a36Sopenharmony_ci } 224462306a36Sopenharmony_ci } 224562306a36Sopenharmony_ci } else { 224662306a36Sopenharmony_ci sd->nchg = 0; 224762306a36Sopenharmony_ci } 224862306a36Sopenharmony_ci sd->pktsz = sd->npkt = 0; 224962306a36Sopenharmony_ci} 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev, 225262306a36Sopenharmony_ci u8 *data, /* isoc packet */ 225362306a36Sopenharmony_ci int len) /* iso packet length */ 225462306a36Sopenharmony_ci{ 225562306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 225662306a36Sopenharmony_ci int avg_lum, is_jpeg; 225762306a36Sopenharmony_ci static const u8 frame_header[] = { 225862306a36Sopenharmony_ci 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96 225962306a36Sopenharmony_ci }; 226062306a36Sopenharmony_ci 226162306a36Sopenharmony_ci is_jpeg = (sd->fmt & 0x03) == 0; 226262306a36Sopenharmony_ci if (len >= 64 && memcmp(data, frame_header, 6) == 0) { 226362306a36Sopenharmony_ci avg_lum = ((data[35] >> 2) & 3) | 226462306a36Sopenharmony_ci (data[20] << 2) | 226562306a36Sopenharmony_ci (data[19] << 10); 226662306a36Sopenharmony_ci avg_lum += ((data[35] >> 4) & 3) | 226762306a36Sopenharmony_ci (data[22] << 2) | 226862306a36Sopenharmony_ci (data[21] << 10); 226962306a36Sopenharmony_ci avg_lum += ((data[35] >> 6) & 3) | 227062306a36Sopenharmony_ci (data[24] << 2) | 227162306a36Sopenharmony_ci (data[23] << 10); 227262306a36Sopenharmony_ci avg_lum += (data[36] & 3) | 227362306a36Sopenharmony_ci (data[26] << 2) | 227462306a36Sopenharmony_ci (data[25] << 10); 227562306a36Sopenharmony_ci avg_lum += ((data[36] >> 2) & 3) | 227662306a36Sopenharmony_ci (data[28] << 2) | 227762306a36Sopenharmony_ci (data[27] << 10); 227862306a36Sopenharmony_ci avg_lum += ((data[36] >> 4) & 3) | 227962306a36Sopenharmony_ci (data[30] << 2) | 228062306a36Sopenharmony_ci (data[29] << 10); 228162306a36Sopenharmony_ci avg_lum += ((data[36] >> 6) & 3) | 228262306a36Sopenharmony_ci (data[32] << 2) | 228362306a36Sopenharmony_ci (data[31] << 10); 228462306a36Sopenharmony_ci avg_lum += ((data[44] >> 4) & 3) | 228562306a36Sopenharmony_ci (data[34] << 2) | 228662306a36Sopenharmony_ci (data[33] << 10); 228762306a36Sopenharmony_ci avg_lum >>= 9; 228862306a36Sopenharmony_ci atomic_set(&sd->avg_lum, avg_lum); 228962306a36Sopenharmony_ci 229062306a36Sopenharmony_ci if (is_jpeg) 229162306a36Sopenharmony_ci transfer_check(gspca_dev, data); 229262306a36Sopenharmony_ci 229362306a36Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 229462306a36Sopenharmony_ci len -= 64; 229562306a36Sopenharmony_ci if (len == 0) 229662306a36Sopenharmony_ci return; 229762306a36Sopenharmony_ci data += 64; 229862306a36Sopenharmony_ci } 229962306a36Sopenharmony_ci if (gspca_dev->last_packet_type == LAST_PACKET) { 230062306a36Sopenharmony_ci if (is_jpeg) { 230162306a36Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, 230262306a36Sopenharmony_ci sd->jpeg_hdr, JPEG_HDR_SZ); 230362306a36Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, 230462306a36Sopenharmony_ci data, len); 230562306a36Sopenharmony_ci } else { 230662306a36Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, 230762306a36Sopenharmony_ci data, len); 230862306a36Sopenharmony_ci } 230962306a36Sopenharmony_ci } else { 231062306a36Sopenharmony_ci /* if JPEG, count the packets and their size */ 231162306a36Sopenharmony_ci if (is_jpeg) { 231262306a36Sopenharmony_ci sd->npkt++; 231362306a36Sopenharmony_ci sd->pktsz += len; 231462306a36Sopenharmony_ci } 231562306a36Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 231662306a36Sopenharmony_ci } 231762306a36Sopenharmony_ci} 231862306a36Sopenharmony_ci 231962306a36Sopenharmony_ci/* sub-driver description */ 232062306a36Sopenharmony_cistatic const struct sd_desc sd_desc = { 232162306a36Sopenharmony_ci .name = KBUILD_MODNAME, 232262306a36Sopenharmony_ci .config = sd_config, 232362306a36Sopenharmony_ci .init = sd_init, 232462306a36Sopenharmony_ci .init_controls = sd_init_controls, 232562306a36Sopenharmony_ci .isoc_init = sd_isoc_init, 232662306a36Sopenharmony_ci .start = sd_start, 232762306a36Sopenharmony_ci .stopN = sd_stopN, 232862306a36Sopenharmony_ci .stop0 = sd_stop0, 232962306a36Sopenharmony_ci .pkt_scan = sd_pkt_scan, 233062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT) 233162306a36Sopenharmony_ci .int_pkt_scan = sd_int_pkt_scan, 233262306a36Sopenharmony_ci#endif 233362306a36Sopenharmony_ci .dq_callback = sd_dqcallback, 233462306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 233562306a36Sopenharmony_ci .set_register = sd_dbg_s_register, 233662306a36Sopenharmony_ci .get_register = sd_dbg_g_register, 233762306a36Sopenharmony_ci .get_chip_info = sd_chip_info, 233862306a36Sopenharmony_ci#endif 233962306a36Sopenharmony_ci}; 234062306a36Sopenharmony_ci 234162306a36Sopenharmony_ci#define SN9C20X(sensor, i2c_addr, flags) \ 234262306a36Sopenharmony_ci .driver_info = ((flags & 0xff) << 16) \ 234362306a36Sopenharmony_ci | (SENSOR_ ## sensor << 8) \ 234462306a36Sopenharmony_ci | (i2c_addr) 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_cistatic const struct usb_device_id device_table[] = { 234762306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, 234862306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, HAS_LED_TORCH)}, 234962306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, 235062306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)}, 235162306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)}, 235262306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 235362306a36Sopenharmony_ci (FLIP_DETECT | HAS_NO_BUTTON))}, 235462306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, 235562306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, 235662306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, 235762306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)}, 235862306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)}, 235962306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)}, 236062306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)}, 236162306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, 236262306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, 236362306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)}, 236462306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)}, 236562306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, 236662306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, 236762306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, 236862306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)}, 236962306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)}, 237062306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)}, 237162306a36Sopenharmony_ci {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)}, 237262306a36Sopenharmony_ci {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, 237362306a36Sopenharmony_ci {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, 237462306a36Sopenharmony_ci {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)}, 237562306a36Sopenharmony_ci {USB_DEVICE(0x0458, 0x7045), SN9C20X(MT9M112, 0x5d, LED_REVERSE)}, 237662306a36Sopenharmony_ci {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)}, 237762306a36Sopenharmony_ci {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)}, 237862306a36Sopenharmony_ci {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)}, 237962306a36Sopenharmony_ci {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, 238062306a36Sopenharmony_ci {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, 238162306a36Sopenharmony_ci {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)}, 238262306a36Sopenharmony_ci {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)}, 238362306a36Sopenharmony_ci {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)}, 238462306a36Sopenharmony_ci {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)}, 238562306a36Sopenharmony_ci {} 238662306a36Sopenharmony_ci}; 238762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table); 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci/* -- device connect -- */ 239062306a36Sopenharmony_cistatic int sd_probe(struct usb_interface *intf, 239162306a36Sopenharmony_ci const struct usb_device_id *id) 239262306a36Sopenharmony_ci{ 239362306a36Sopenharmony_ci return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 239462306a36Sopenharmony_ci THIS_MODULE); 239562306a36Sopenharmony_ci} 239662306a36Sopenharmony_ci 239762306a36Sopenharmony_cistatic struct usb_driver sd_driver = { 239862306a36Sopenharmony_ci .name = KBUILD_MODNAME, 239962306a36Sopenharmony_ci .id_table = device_table, 240062306a36Sopenharmony_ci .probe = sd_probe, 240162306a36Sopenharmony_ci .disconnect = gspca_disconnect, 240262306a36Sopenharmony_ci#ifdef CONFIG_PM 240362306a36Sopenharmony_ci .suspend = gspca_suspend, 240462306a36Sopenharmony_ci .resume = gspca_resume, 240562306a36Sopenharmony_ci .reset_resume = gspca_resume, 240662306a36Sopenharmony_ci#endif 240762306a36Sopenharmony_ci}; 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_cimodule_usb_driver(sd_driver); 2410