18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define MODULE_NAME "etoms" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "gspca.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Etoms USB Camera Driver"); 168c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* specific webcam descriptor */ 198c2ecf20Sopenharmony_cistruct sd { 208c2ecf20Sopenharmony_ci struct gspca_dev gspca_dev; /* !! must be the first item */ 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci unsigned char autogain; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci char sensor; 258c2ecf20Sopenharmony_ci#define SENSOR_PAS106 0 268c2ecf20Sopenharmony_ci#define SENSOR_TAS5130CXX 1 278c2ecf20Sopenharmony_ci signed char ag_cnt; 288c2ecf20Sopenharmony_ci#define AG_CNT_START 13 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = { 328c2ecf20Sopenharmony_ci {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 338c2ecf20Sopenharmony_ci .bytesperline = 320, 348c2ecf20Sopenharmony_ci .sizeimage = 320 * 240, 358c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 368c2ecf20Sopenharmony_ci .priv = 1}, 378c2ecf20Sopenharmony_ci/* {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 388c2ecf20Sopenharmony_ci .bytesperline = 640, 398c2ecf20Sopenharmony_ci .sizeimage = 640 * 480, 408c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 418c2ecf20Sopenharmony_ci .priv = 0}, */ 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format sif_mode[] = { 458c2ecf20Sopenharmony_ci {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 468c2ecf20Sopenharmony_ci .bytesperline = 176, 478c2ecf20Sopenharmony_ci .sizeimage = 176 * 144, 488c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 498c2ecf20Sopenharmony_ci .priv = 1}, 508c2ecf20Sopenharmony_ci {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 518c2ecf20Sopenharmony_ci .bytesperline = 352, 528c2ecf20Sopenharmony_ci .sizeimage = 352 * 288, 538c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_SRGB, 548c2ecf20Sopenharmony_ci .priv = 0}, 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#define ETOMS_ALT_SIZE_1000 12 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define ET_GPIO_DIR_CTRL 0x04 /* Control IO bit[0..5] (0 in 1 out) */ 608c2ecf20Sopenharmony_ci#define ET_GPIO_OUT 0x05 /* Only IO data */ 618c2ecf20Sopenharmony_ci#define ET_GPIO_IN 0x06 /* Read Only IO data */ 628c2ecf20Sopenharmony_ci#define ET_RESET_ALL 0x03 638c2ecf20Sopenharmony_ci#define ET_ClCK 0x01 648c2ecf20Sopenharmony_ci#define ET_CTRL 0x02 /* enable i2c OutClck Powerdown mode */ 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define ET_COMP 0x12 /* Compression register */ 678c2ecf20Sopenharmony_ci#define ET_MAXQt 0x13 688c2ecf20Sopenharmony_ci#define ET_MINQt 0x14 698c2ecf20Sopenharmony_ci#define ET_COMP_VAL0 0x02 708c2ecf20Sopenharmony_ci#define ET_COMP_VAL1 0x03 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#define ET_REG1d 0x1d 738c2ecf20Sopenharmony_ci#define ET_REG1e 0x1e 748c2ecf20Sopenharmony_ci#define ET_REG1f 0x1f 758c2ecf20Sopenharmony_ci#define ET_REG20 0x20 768c2ecf20Sopenharmony_ci#define ET_REG21 0x21 778c2ecf20Sopenharmony_ci#define ET_REG22 0x22 788c2ecf20Sopenharmony_ci#define ET_REG23 0x23 798c2ecf20Sopenharmony_ci#define ET_REG24 0x24 808c2ecf20Sopenharmony_ci#define ET_REG25 0x25 818c2ecf20Sopenharmony_ci/* base registers for luma calculation */ 828c2ecf20Sopenharmony_ci#define ET_LUMA_CENTER 0x39 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#define ET_G_RED 0x4d 858c2ecf20Sopenharmony_ci#define ET_G_GREEN1 0x4e 868c2ecf20Sopenharmony_ci#define ET_G_BLUE 0x4f 878c2ecf20Sopenharmony_ci#define ET_G_GREEN2 0x50 888c2ecf20Sopenharmony_ci#define ET_G_GR_H 0x51 898c2ecf20Sopenharmony_ci#define ET_G_GB_H 0x52 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define ET_O_RED 0x34 928c2ecf20Sopenharmony_ci#define ET_O_GREEN1 0x35 938c2ecf20Sopenharmony_ci#define ET_O_BLUE 0x36 948c2ecf20Sopenharmony_ci#define ET_O_GREEN2 0x37 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci#define ET_SYNCHRO 0x68 978c2ecf20Sopenharmony_ci#define ET_STARTX 0x69 988c2ecf20Sopenharmony_ci#define ET_STARTY 0x6a 998c2ecf20Sopenharmony_ci#define ET_WIDTH_LOW 0x6b 1008c2ecf20Sopenharmony_ci#define ET_HEIGTH_LOW 0x6c 1018c2ecf20Sopenharmony_ci#define ET_W_H_HEIGTH 0x6d 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define ET_REG6e 0x6e /* OBW */ 1048c2ecf20Sopenharmony_ci#define ET_REG6f 0x6f /* OBW */ 1058c2ecf20Sopenharmony_ci#define ET_REG70 0x70 /* OBW_AWB */ 1068c2ecf20Sopenharmony_ci#define ET_REG71 0x71 /* OBW_AWB */ 1078c2ecf20Sopenharmony_ci#define ET_REG72 0x72 /* OBW_AWB */ 1088c2ecf20Sopenharmony_ci#define ET_REG73 0x73 /* Clkdelay ns */ 1098c2ecf20Sopenharmony_ci#define ET_REG74 0x74 /* test pattern */ 1108c2ecf20Sopenharmony_ci#define ET_REG75 0x75 /* test pattern */ 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci#define ET_I2C_CLK 0x8c 1138c2ecf20Sopenharmony_ci#define ET_PXL_CLK 0x60 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci#define ET_I2C_BASE 0x89 1168c2ecf20Sopenharmony_ci#define ET_I2C_COUNT 0x8a 1178c2ecf20Sopenharmony_ci#define ET_I2C_PREFETCH 0x8b 1188c2ecf20Sopenharmony_ci#define ET_I2C_REG 0x88 1198c2ecf20Sopenharmony_ci#define ET_I2C_DATA7 0x87 1208c2ecf20Sopenharmony_ci#define ET_I2C_DATA6 0x86 1218c2ecf20Sopenharmony_ci#define ET_I2C_DATA5 0x85 1228c2ecf20Sopenharmony_ci#define ET_I2C_DATA4 0x84 1238c2ecf20Sopenharmony_ci#define ET_I2C_DATA3 0x83 1248c2ecf20Sopenharmony_ci#define ET_I2C_DATA2 0x82 1258c2ecf20Sopenharmony_ci#define ET_I2C_DATA1 0x81 1268c2ecf20Sopenharmony_ci#define ET_I2C_DATA0 0x80 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#define PAS106_REG2 0x02 /* pxlClk = systemClk/(reg2) */ 1298c2ecf20Sopenharmony_ci#define PAS106_REG3 0x03 /* line/frame H [11..4] */ 1308c2ecf20Sopenharmony_ci#define PAS106_REG4 0x04 /* line/frame L [3..0] */ 1318c2ecf20Sopenharmony_ci#define PAS106_REG5 0x05 /* exposure time line offset(default 5) */ 1328c2ecf20Sopenharmony_ci#define PAS106_REG6 0x06 /* exposure time pixel offset(default 6) */ 1338c2ecf20Sopenharmony_ci#define PAS106_REG7 0x07 /* signbit Dac (default 0) */ 1348c2ecf20Sopenharmony_ci#define PAS106_REG9 0x09 1358c2ecf20Sopenharmony_ci#define PAS106_REG0e 0x0e /* global gain [4..0](default 0x0e) */ 1368c2ecf20Sopenharmony_ci#define PAS106_REG13 0x13 /* end i2c write */ 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 }; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d }; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic const __u8 I2c3[] = { 0x12, 0x05 }; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic const __u8 I2c4[] = { 0x41, 0x08 }; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/* read 'len' bytes to gspca_dev->usb_buf */ 1478c2ecf20Sopenharmony_cistatic void reg_r(struct gspca_dev *gspca_dev, 1488c2ecf20Sopenharmony_ci __u16 index, 1498c2ecf20Sopenharmony_ci __u16 len) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci struct usb_device *dev = gspca_dev->dev; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (len > USB_BUF_SZ) { 1548c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_r: buffer overflow\n"); 1558c2ecf20Sopenharmony_ci return; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci usb_control_msg(dev, 1598c2ecf20Sopenharmony_ci usb_rcvctrlpipe(dev, 0), 1608c2ecf20Sopenharmony_ci 0, 1618c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 1628c2ecf20Sopenharmony_ci 0, 1638c2ecf20Sopenharmony_ci index, gspca_dev->usb_buf, len, 500); 1648c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "reg read [%02x] -> %02x ..\n", 1658c2ecf20Sopenharmony_ci index, gspca_dev->usb_buf[0]); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic void reg_w_val(struct gspca_dev *gspca_dev, 1698c2ecf20Sopenharmony_ci __u16 index, 1708c2ecf20Sopenharmony_ci __u8 val) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci struct usb_device *dev = gspca_dev->dev; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0] = val; 1758c2ecf20Sopenharmony_ci usb_control_msg(dev, 1768c2ecf20Sopenharmony_ci usb_sndctrlpipe(dev, 0), 1778c2ecf20Sopenharmony_ci 0, 1788c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 1798c2ecf20Sopenharmony_ci 0, 1808c2ecf20Sopenharmony_ci index, gspca_dev->usb_buf, 1, 500); 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic void reg_w(struct gspca_dev *gspca_dev, 1848c2ecf20Sopenharmony_ci __u16 index, 1858c2ecf20Sopenharmony_ci const __u8 *buffer, 1868c2ecf20Sopenharmony_ci __u16 len) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci struct usb_device *dev = gspca_dev->dev; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (len > USB_BUF_SZ) { 1918c2ecf20Sopenharmony_ci pr_err("reg_w: buffer overflow\n"); 1928c2ecf20Sopenharmony_ci return; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "reg write [%02x] = %02x..\n", 1958c2ecf20Sopenharmony_ci index, *buffer); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci memcpy(gspca_dev->usb_buf, buffer, len); 1988c2ecf20Sopenharmony_ci usb_control_msg(dev, 1998c2ecf20Sopenharmony_ci usb_sndctrlpipe(dev, 0), 2008c2ecf20Sopenharmony_ci 0, 2018c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 2028c2ecf20Sopenharmony_ci 0, index, gspca_dev->usb_buf, len, 500); 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic int i2c_w(struct gspca_dev *gspca_dev, 2068c2ecf20Sopenharmony_ci __u8 reg, 2078c2ecf20Sopenharmony_ci const __u8 *buffer, 2088c2ecf20Sopenharmony_ci int len, __u8 mode) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci /* buffer should be [D0..D7] */ 2118c2ecf20Sopenharmony_ci __u8 ptchcount; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* set the base address */ 2148c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_BASE, 0x40); 2158c2ecf20Sopenharmony_ci /* sensor base for the pas106 */ 2168c2ecf20Sopenharmony_ci /* set count and prefetch */ 2178c2ecf20Sopenharmony_ci ptchcount = ((len & 0x07) << 4) | (mode & 0x03); 2188c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount); 2198c2ecf20Sopenharmony_ci /* set the register base */ 2208c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_REG, reg); 2218c2ecf20Sopenharmony_ci while (--len >= 0) 2228c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]); 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic int i2c_r(struct gspca_dev *gspca_dev, 2278c2ecf20Sopenharmony_ci __u8 reg) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci /* set the base address */ 2308c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_BASE, 0x40); 2318c2ecf20Sopenharmony_ci /* sensor base for the pas106 */ 2328c2ecf20Sopenharmony_ci /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */ 2338c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11); 2348c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_REG, reg); /* set the register base */ 2358c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02); /* prefetch */ 2368c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00); 2378c2ecf20Sopenharmony_ci reg_r(gspca_dev, ET_I2C_DATA0, 1); /* read one byte */ 2388c2ecf20Sopenharmony_ci return 0; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic int Et_WaitStatus(struct gspca_dev *gspca_dev) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci int retry = 10; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci while (retry--) { 2468c2ecf20Sopenharmony_ci reg_r(gspca_dev, ET_ClCK, 1); 2478c2ecf20Sopenharmony_ci if (gspca_dev->usb_buf[0] != 0) 2488c2ecf20Sopenharmony_ci return 1; 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci return 0; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic int et_video(struct gspca_dev *gspca_dev, 2548c2ecf20Sopenharmony_ci int on) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci int ret; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_GPIO_OUT, 2598c2ecf20Sopenharmony_ci on ? 0x10 /* startvideo - set Bit5 */ 2608c2ecf20Sopenharmony_ci : 0); /* stopvideo */ 2618c2ecf20Sopenharmony_ci ret = Et_WaitStatus(gspca_dev); 2628c2ecf20Sopenharmony_ci if (ret != 0) 2638c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "timeout video on/off\n"); 2648c2ecf20Sopenharmony_ci return ret; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic void Et_init2(struct gspca_dev *gspca_dev) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci __u8 value; 2708c2ecf20Sopenharmony_ci static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 }; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Open Init2 ET\n"); 2738c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f); 2748c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10); 2758c2ecf20Sopenharmony_ci reg_r(gspca_dev, ET_GPIO_IN, 1); 2768c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */ 2778c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_CTRL, 0x1b); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* compression et subsampling */ 2808c2ecf20Sopenharmony_ci if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) 2818c2ecf20Sopenharmony_ci value = ET_COMP_VAL1; /* 320 */ 2828c2ecf20Sopenharmony_ci else 2838c2ecf20Sopenharmony_ci value = ET_COMP_VAL0; /* 640 */ 2848c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_COMP, value); 2858c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_MAXQt, 0x1f); 2868c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_MINQt, 0x04); 2878c2ecf20Sopenharmony_ci /* undocumented registers */ 2888c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG1d, 0xff); 2898c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG1e, 0xff); 2908c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG1f, 0xff); 2918c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG20, 0x35); 2928c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG21, 0x01); 2938c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG22, 0x00); 2948c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG23, 0xff); 2958c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG24, 0xff); 2968c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG25, 0x0f); 2978c2ecf20Sopenharmony_ci /* colors setting */ 2988c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x30, 0x11); /* 0x30 */ 2998c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x31, 0x40); 3008c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x32, 0x00); 3018c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_O_RED, 0x00); /* 0x34 */ 3028c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_O_GREEN1, 0x00); 3038c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_O_BLUE, 0x00); 3048c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_O_GREEN2, 0x00); 3058c2ecf20Sopenharmony_ci /*************/ 3068c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_RED, 0x80); /* 0x4d */ 3078c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_GREEN1, 0x80); 3088c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_BLUE, 0x80); 3098c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_GREEN2, 0x80); 3108c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_GR_H, 0x00); 3118c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_GB_H, 0x00); /* 0x52 */ 3128c2ecf20Sopenharmony_ci /* Window control registers */ 3138c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x61, 0x80); /* use cmc_out */ 3148c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x62, 0x02); 3158c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x63, 0x03); 3168c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x64, 0x14); 3178c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x65, 0x0e); 3188c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x66, 0x02); 3198c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x67, 0x02); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /**************************************/ 3228c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f); /* 0x68 */ 3238c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_STARTX, 0x69); /* 0x6a //0x69 */ 3248c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_STARTY, 0x0d); /* 0x0d //0x0c */ 3258c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80); 3268c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0); 3278c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60); /* 6d */ 3288c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG6e, 0x86); 3298c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG6f, 0x01); 3308c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG70, 0x26); 3318c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG71, 0x7a); 3328c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG72, 0x01); 3338c2ecf20Sopenharmony_ci /* Clock Pattern registers ***************** */ 3348c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG73, 0x00); 3358c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG74, 0x18); /* 0x28 */ 3368c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG75, 0x0f); /* 0x01 */ 3378c2ecf20Sopenharmony_ci /**********************************************/ 3388c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x8a, 0x20); 3398c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x8d, 0x0f); 3408c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x8e, 0x08); 3418c2ecf20Sopenharmony_ci /**************************************/ 3428c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x03, 0x08); 3438c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_PXL_CLK, 0x03); 3448c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x81, 0xff); 3458c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x80, 0x00); 3468c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x81, 0xff); 3478c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x80, 0x20); 3488c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x03, 0x01); 3498c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x03, 0x00); 3508c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x03, 0x08); 3518c2ecf20Sopenharmony_ci /********************************************/ 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci/* reg_r(gspca_dev, ET_I2C_BASE, 1); 3548c2ecf20Sopenharmony_ci always 0x40 as the pas106 ??? */ 3558c2ecf20Sopenharmony_ci /* set the sensor */ 3568c2ecf20Sopenharmony_ci if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) 3578c2ecf20Sopenharmony_ci value = 0x04; /* 320 */ 3588c2ecf20Sopenharmony_ci else /* 640 */ 3598c2ecf20Sopenharmony_ci value = 0x1e; /* 0x17 * setting PixelClock 3608c2ecf20Sopenharmony_ci * 0x03 mean 24/(3+1) = 6 Mhz 3618c2ecf20Sopenharmony_ci * 0x05 -> 24/(5+1) = 4 Mhz 3628c2ecf20Sopenharmony_ci * 0x0b -> 24/(11+1) = 2 Mhz 3638c2ecf20Sopenharmony_ci * 0x17 -> 24/(23+1) = 1 Mhz 3648c2ecf20Sopenharmony_ci */ 3658c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_PXL_CLK, value); 3668c2ecf20Sopenharmony_ci /* now set by fifo the FormatLine setting */ 3678c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x62, FormLine, 6); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */ 3708c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x81, 0x47); /* 0x47; */ 3718c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x80, 0x40); /* 0x40; */ 3728c2ecf20Sopenharmony_ci /* Pedro change */ 3738c2ecf20Sopenharmony_ci /* Brightness change Brith+ decrease value */ 3748c2ecf20Sopenharmony_ci /* Brigth- increase value */ 3758c2ecf20Sopenharmony_ci /* original value = 0x70; */ 3768c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x81, 0x30); /* 0x20; - set brightness */ 3778c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */ 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev, s32 val) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci int i; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 3858c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_O_RED + i, val); 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev, s32 val) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 }; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci memset(RGBG, val, sizeof(RGBG) - 2); 3938c2ecf20Sopenharmony_ci reg_w(gspca_dev, ET_G_RED, RGBG, 6); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic void setcolors(struct gspca_dev *gspca_dev, s32 val) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 3998c2ecf20Sopenharmony_ci __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d }; 4008c2ecf20Sopenharmony_ci __u8 i2cflags = 0x01; 4018c2ecf20Sopenharmony_ci /* __u8 green = 0; */ 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci I2cc[3] = val; /* red */ 4048c2ecf20Sopenharmony_ci I2cc[0] = 15 - val; /* blue */ 4058c2ecf20Sopenharmony_ci /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */ 4068c2ecf20Sopenharmony_ci /* I2cc[1] = I2cc[2] = green; */ 4078c2ecf20Sopenharmony_ci if (sd->sensor == SENSOR_PAS106) { 4088c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3); 4098c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1); 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic s32 getcolors(struct gspca_dev *gspca_dev) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci if (sd->sensor == SENSOR_PAS106) { 4188c2ecf20Sopenharmony_ci/* i2c_r(gspca_dev, PAS106_REG9); * blue */ 4198c2ecf20Sopenharmony_ci i2c_r(gspca_dev, PAS106_REG9 + 3); /* red */ 4208c2ecf20Sopenharmony_ci return gspca_dev->usb_buf[0] & 0x0f; 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci return 0; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic void setautogain(struct gspca_dev *gspca_dev) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci if (sd->autogain) 4308c2ecf20Sopenharmony_ci sd->ag_cnt = AG_CNT_START; 4318c2ecf20Sopenharmony_ci else 4328c2ecf20Sopenharmony_ci sd->ag_cnt = -1; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic void Et_init1(struct gspca_dev *gspca_dev) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci __u8 value; 4388c2ecf20Sopenharmony_ci/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */ 4398c2ecf20Sopenharmony_ci __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 }; 4408c2ecf20Sopenharmony_ci /* try 1/120 0x6d 0xcd 0x40 */ 4418c2ecf20Sopenharmony_ci/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00}; 4428c2ecf20Sopenharmony_ci * 1/60000 hmm ?? */ 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Open Init1 ET\n\n"); 4458c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7); 4468c2ecf20Sopenharmony_ci reg_r(gspca_dev, ET_GPIO_IN, 1); 4478c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_RESET_ALL, 1); 4488c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_RESET_ALL, 0); 4498c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_ClCK, 0x10); 4508c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_CTRL, 0x19); 4518c2ecf20Sopenharmony_ci /* compression et subsampling */ 4528c2ecf20Sopenharmony_ci if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) 4538c2ecf20Sopenharmony_ci value = ET_COMP_VAL1; 4548c2ecf20Sopenharmony_ci else 4558c2ecf20Sopenharmony_ci value = ET_COMP_VAL0; 4568c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Open mode %d Compression %d\n", 4578c2ecf20Sopenharmony_ci gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv, 4588c2ecf20Sopenharmony_ci value); 4598c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_COMP, value); 4608c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_MAXQt, 0x1d); 4618c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_MINQt, 0x02); 4628c2ecf20Sopenharmony_ci /* undocumented registers */ 4638c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG1d, 0xff); 4648c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG1e, 0xff); 4658c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG1f, 0xff); 4668c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG20, 0x35); 4678c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG21, 0x01); 4688c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG22, 0x00); 4698c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG23, 0xf7); 4708c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG24, 0xff); 4718c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG25, 0x07); 4728c2ecf20Sopenharmony_ci /* colors setting */ 4738c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_RED, 0x80); 4748c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_GREEN1, 0x80); 4758c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_BLUE, 0x80); 4768c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_GREEN2, 0x80); 4778c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_GR_H, 0x00); 4788c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_G_GB_H, 0x00); 4798c2ecf20Sopenharmony_ci /* Window control registers */ 4808c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0); 4818c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_STARTX, 0x56); /* 0x56 */ 4828c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_STARTY, 0x05); /* 0x04 */ 4838c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60); 4848c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20); 4858c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50); 4868c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG6e, 0x86); 4878c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG6f, 0x01); 4888c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG70, 0x86); 4898c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG71, 0x14); 4908c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG72, 0x00); 4918c2ecf20Sopenharmony_ci /* Clock Pattern registers */ 4928c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG73, 0x00); 4938c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG74, 0x00); 4948c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_REG75, 0x0a); 4958c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_I2C_CLK, 0x04); 4968c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_PXL_CLK, 0x01); 4978c2ecf20Sopenharmony_ci /* set the sensor */ 4988c2ecf20Sopenharmony_ci if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 4998c2ecf20Sopenharmony_ci I2c0[0] = 0x06; 5008c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1); 5018c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1); 5028c2ecf20Sopenharmony_ci value = 0x06; 5038c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1); 5048c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1); 5058c2ecf20Sopenharmony_ci /* value = 0x1f; */ 5068c2ecf20Sopenharmony_ci value = 0x04; 5078c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1); 5088c2ecf20Sopenharmony_ci } else { 5098c2ecf20Sopenharmony_ci I2c0[0] = 0x0a; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1); 5128c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1); 5138c2ecf20Sopenharmony_ci value = 0x0a; 5148c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1); 5158c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1); 5168c2ecf20Sopenharmony_ci value = 0x04; 5178c2ecf20Sopenharmony_ci /* value = 0x10; */ 5188c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1); 5198c2ecf20Sopenharmony_ci /* bit 2 enable bit 1:2 select 0 1 2 3 5208c2ecf20Sopenharmony_ci value = 0x07; * curve 0 * 5218c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1); 5228c2ecf20Sopenharmony_ci */ 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci/* value = 0x01; */ 5268c2ecf20Sopenharmony_ci/* value = 0x22; */ 5278c2ecf20Sopenharmony_ci/* i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */ 5288c2ecf20Sopenharmony_ci /* magnetude and sign bit for DAC */ 5298c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1); 5308c2ecf20Sopenharmony_ci /* now set by fifo the whole colors setting */ 5318c2ecf20Sopenharmony_ci reg_w(gspca_dev, ET_G_RED, GainRGBG, 6); 5328c2ecf20Sopenharmony_ci setcolors(gspca_dev, getcolors(gspca_dev)); 5338c2ecf20Sopenharmony_ci} 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci/* this function is called at probe time */ 5368c2ecf20Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev, 5378c2ecf20Sopenharmony_ci const struct usb_device_id *id) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5408c2ecf20Sopenharmony_ci struct cam *cam; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci cam = &gspca_dev->cam; 5438c2ecf20Sopenharmony_ci sd->sensor = id->driver_info; 5448c2ecf20Sopenharmony_ci if (sd->sensor == SENSOR_PAS106) { 5458c2ecf20Sopenharmony_ci cam->cam_mode = sif_mode; 5468c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(sif_mode); 5478c2ecf20Sopenharmony_ci } else { 5488c2ecf20Sopenharmony_ci cam->cam_mode = vga_mode; 5498c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(vga_mode); 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci sd->ag_cnt = -1; 5528c2ecf20Sopenharmony_ci return 0; 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci/* this function is called at probe and resume time */ 5568c2ecf20Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (sd->sensor == SENSOR_PAS106) 5618c2ecf20Sopenharmony_ci Et_init1(gspca_dev); 5628c2ecf20Sopenharmony_ci else 5638c2ecf20Sopenharmony_ci Et_init2(gspca_dev); 5648c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); 5658c2ecf20Sopenharmony_ci et_video(gspca_dev, 0); /* video off */ 5668c2ecf20Sopenharmony_ci return 0; 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci/* -- start the camera -- */ 5708c2ecf20Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci if (sd->sensor == SENSOR_PAS106) 5758c2ecf20Sopenharmony_ci Et_init1(gspca_dev); 5768c2ecf20Sopenharmony_ci else 5778c2ecf20Sopenharmony_ci Et_init2(gspca_dev); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci setautogain(gspca_dev); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); 5828c2ecf20Sopenharmony_ci et_video(gspca_dev, 1); /* video on */ 5838c2ecf20Sopenharmony_ci return 0; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci et_video(gspca_dev, 0); /* video off */ 5898c2ecf20Sopenharmony_ci} 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_cistatic __u8 Et_getgainG(struct gspca_dev *gspca_dev) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci if (sd->sensor == SENSOR_PAS106) { 5968c2ecf20Sopenharmony_ci i2c_r(gspca_dev, PAS106_REG0e); 5978c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_CONF, "Etoms gain G %d\n", 5988c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0]); 5998c2ecf20Sopenharmony_ci return gspca_dev->usb_buf[0]; 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci return 0x1f; 6028c2ecf20Sopenharmony_ci} 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_cistatic void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (sd->sensor == SENSOR_PAS106) { 6098c2ecf20Sopenharmony_ci __u8 i2cflags = 0x01; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3); 6128c2ecf20Sopenharmony_ci i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1); 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci#define BLIMIT(bright) \ 6178c2ecf20Sopenharmony_ci (u8)((bright > 0x1f) ? 0x1f : ((bright < 4) ? 3 : bright)) 6188c2ecf20Sopenharmony_ci#define LIMIT(color) \ 6198c2ecf20Sopenharmony_ci (u8)((color > 0xff) ? 0xff : ((color < 0) ? 0 : color)) 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistatic void do_autogain(struct gspca_dev *gspca_dev) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 6248c2ecf20Sopenharmony_ci __u8 luma; 6258c2ecf20Sopenharmony_ci __u8 luma_mean = 128; 6268c2ecf20Sopenharmony_ci __u8 luma_delta = 20; 6278c2ecf20Sopenharmony_ci __u8 spring = 4; 6288c2ecf20Sopenharmony_ci int Gbright; 6298c2ecf20Sopenharmony_ci __u8 r, g, b; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci if (sd->ag_cnt < 0) 6328c2ecf20Sopenharmony_ci return; 6338c2ecf20Sopenharmony_ci if (--sd->ag_cnt >= 0) 6348c2ecf20Sopenharmony_ci return; 6358c2ecf20Sopenharmony_ci sd->ag_cnt = AG_CNT_START; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci Gbright = Et_getgainG(gspca_dev); 6388c2ecf20Sopenharmony_ci reg_r(gspca_dev, ET_LUMA_CENTER, 4); 6398c2ecf20Sopenharmony_ci g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1; 6408c2ecf20Sopenharmony_ci r = gspca_dev->usb_buf[1]; 6418c2ecf20Sopenharmony_ci b = gspca_dev->usb_buf[2]; 6428c2ecf20Sopenharmony_ci r = ((r << 8) - (r << 4) - (r << 3)) >> 10; 6438c2ecf20Sopenharmony_ci b = ((b << 7) >> 10); 6448c2ecf20Sopenharmony_ci g = ((g << 9) + (g << 7) + (g << 5)) >> 10; 6458c2ecf20Sopenharmony_ci luma = LIMIT(r + g + b); 6468c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_FRAM, "Etoms luma G %d\n", luma); 6478c2ecf20Sopenharmony_ci if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) { 6488c2ecf20Sopenharmony_ci Gbright += (luma_mean - luma) >> spring; 6498c2ecf20Sopenharmony_ci Gbright = BLIMIT(Gbright); 6508c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_FRAM, "Etoms Gbright %d\n", Gbright); 6518c2ecf20Sopenharmony_ci Et_setgainG(gspca_dev, (__u8) Gbright); 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci} 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci#undef BLIMIT 6568c2ecf20Sopenharmony_ci#undef LIMIT 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev, 6598c2ecf20Sopenharmony_ci u8 *data, /* isoc packet */ 6608c2ecf20Sopenharmony_ci int len) /* iso packet length */ 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci int seqframe; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci seqframe = data[0] & 0x3f; 6658c2ecf20Sopenharmony_ci len = (int) (((data[0] & 0xc0) << 2) | data[1]); 6668c2ecf20Sopenharmony_ci if (seqframe == 0x3f) { 6678c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_FRAM, 6688c2ecf20Sopenharmony_ci "header packet found datalength %d !!\n", len); 6698c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_FRAM, "G %d R %d G %d B %d", 6708c2ecf20Sopenharmony_ci data[2], data[3], data[4], data[5]); 6718c2ecf20Sopenharmony_ci data += 30; 6728c2ecf20Sopenharmony_ci /* don't change datalength as the chips provided it */ 6738c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 6748c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); 6758c2ecf20Sopenharmony_ci return; 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci if (len) { 6788c2ecf20Sopenharmony_ci data += 8; 6798c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 6808c2ecf20Sopenharmony_ci } else { /* Drop Packet */ 6818c2ecf20Sopenharmony_ci gspca_dev->last_packet_type = DISCARD_PACKET; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = 6888c2ecf20Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 6898c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci gspca_dev->usb_err = 0; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci if (!gspca_dev->streaming) 6948c2ecf20Sopenharmony_ci return 0; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci switch (ctrl->id) { 6978c2ecf20Sopenharmony_ci case V4L2_CID_BRIGHTNESS: 6988c2ecf20Sopenharmony_ci setbrightness(gspca_dev, ctrl->val); 6998c2ecf20Sopenharmony_ci break; 7008c2ecf20Sopenharmony_ci case V4L2_CID_CONTRAST: 7018c2ecf20Sopenharmony_ci setcontrast(gspca_dev, ctrl->val); 7028c2ecf20Sopenharmony_ci break; 7038c2ecf20Sopenharmony_ci case V4L2_CID_SATURATION: 7048c2ecf20Sopenharmony_ci setcolors(gspca_dev, ctrl->val); 7058c2ecf20Sopenharmony_ci break; 7068c2ecf20Sopenharmony_ci case V4L2_CID_AUTOGAIN: 7078c2ecf20Sopenharmony_ci sd->autogain = ctrl->val; 7088c2ecf20Sopenharmony_ci setautogain(gspca_dev); 7098c2ecf20Sopenharmony_ci break; 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci return gspca_dev->usb_err; 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = { 7158c2ecf20Sopenharmony_ci .s_ctrl = sd_s_ctrl, 7168c2ecf20Sopenharmony_ci}; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *)gspca_dev; 7218c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci gspca_dev->vdev.ctrl_handler = hdl; 7248c2ecf20Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 4); 7258c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 7268c2ecf20Sopenharmony_ci V4L2_CID_BRIGHTNESS, 1, 127, 1, 63); 7278c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 7288c2ecf20Sopenharmony_ci V4L2_CID_CONTRAST, 0, 255, 1, 127); 7298c2ecf20Sopenharmony_ci if (sd->sensor == SENSOR_PAS106) 7308c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 7318c2ecf20Sopenharmony_ci V4L2_CID_SATURATION, 0, 15, 1, 7); 7328c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 7338c2ecf20Sopenharmony_ci V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 7348c2ecf20Sopenharmony_ci if (hdl->error) { 7358c2ecf20Sopenharmony_ci pr_err("Could not initialize controls\n"); 7368c2ecf20Sopenharmony_ci return hdl->error; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci return 0; 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci/* sub-driver description */ 7428c2ecf20Sopenharmony_cistatic const struct sd_desc sd_desc = { 7438c2ecf20Sopenharmony_ci .name = MODULE_NAME, 7448c2ecf20Sopenharmony_ci .config = sd_config, 7458c2ecf20Sopenharmony_ci .init = sd_init, 7468c2ecf20Sopenharmony_ci .init_controls = sd_init_controls, 7478c2ecf20Sopenharmony_ci .start = sd_start, 7488c2ecf20Sopenharmony_ci .stopN = sd_stopN, 7498c2ecf20Sopenharmony_ci .pkt_scan = sd_pkt_scan, 7508c2ecf20Sopenharmony_ci .dq_callback = do_autogain, 7518c2ecf20Sopenharmony_ci}; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci/* -- module initialisation -- */ 7548c2ecf20Sopenharmony_cistatic const struct usb_device_id device_table[] = { 7558c2ecf20Sopenharmony_ci {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, 7568c2ecf20Sopenharmony_ci {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, 7578c2ecf20Sopenharmony_ci {} 7588c2ecf20Sopenharmony_ci}; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table); 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci/* -- device connect -- */ 7638c2ecf20Sopenharmony_cistatic int sd_probe(struct usb_interface *intf, 7648c2ecf20Sopenharmony_ci const struct usb_device_id *id) 7658c2ecf20Sopenharmony_ci{ 7668c2ecf20Sopenharmony_ci return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 7678c2ecf20Sopenharmony_ci THIS_MODULE); 7688c2ecf20Sopenharmony_ci} 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_cistatic struct usb_driver sd_driver = { 7718c2ecf20Sopenharmony_ci .name = MODULE_NAME, 7728c2ecf20Sopenharmony_ci .id_table = device_table, 7738c2ecf20Sopenharmony_ci .probe = sd_probe, 7748c2ecf20Sopenharmony_ci .disconnect = gspca_disconnect, 7758c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 7768c2ecf20Sopenharmony_ci .suspend = gspca_suspend, 7778c2ecf20Sopenharmony_ci .resume = gspca_resume, 7788c2ecf20Sopenharmony_ci .reset_resume = gspca_resume, 7798c2ecf20Sopenharmony_ci#endif 7808c2ecf20Sopenharmony_ci}; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_cimodule_usb_driver(sd_driver); 783