📄 etoms.c
字号:
/* * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004) * * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#define MODULE_NAME "etoms"#include "gspca.h"MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");MODULE_DESCRIPTION("Etoms USB Camera Driver");MODULE_LICENSE("GPL");/* specific webcam descriptor */struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ unsigned char brightness; unsigned char contrast; unsigned char colors; unsigned char autogain; char sensor;#define SENSOR_PAS106 0#define SENSOR_TAS5130CXX 1 signed char ag_cnt;#define AG_CNT_START 13};/* V4L2 controls supported by the driver */static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);static struct ctrl sd_ctrls[] = { { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = 1, .maximum = 127, .step = 1,#define BRIGHTNESS_DEF 63 .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, }, { { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, .maximum = 255, .step = 1,#define CONTRAST_DEF 127 .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, .get = sd_getcontrast, },#define COLOR_IDX 2 { { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Color", .minimum = 0, .maximum = 15, .step = 1,#define COLOR_DEF 7 .default_value = COLOR_DEF, }, .set = sd_setcolors, .get = sd_getcolors, }, { { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Auto Gain", .minimum = 0, .maximum = 1, .step = 1,#define AUTOGAIN_DEF 1 .default_value = AUTOGAIN_DEF, }, .set = sd_setautogain, .get = sd_getautogain, },};static struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1},/* {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0}, */};static struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 352, .sizeimage = 352 * 288, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0},};#define ETOMS_ALT_SIZE_1000 12#define ET_GPIO_DIR_CTRL 0x04 /* Control IO bit[0..5] (0 in 1 out) */#define ET_GPIO_OUT 0x05 /* Only IO data */#define ET_GPIO_IN 0x06 /* Read Only IO data */#define ET_RESET_ALL 0x03#define ET_ClCK 0x01#define ET_CTRL 0x02 /* enable i2c OutClck Powerdown mode */#define ET_COMP 0x12 /* Compression register */#define ET_MAXQt 0x13#define ET_MINQt 0x14#define ET_COMP_VAL0 0x02#define ET_COMP_VAL1 0x03#define ET_REG1d 0x1d#define ET_REG1e 0x1e#define ET_REG1f 0x1f#define ET_REG20 0x20#define ET_REG21 0x21#define ET_REG22 0x22#define ET_REG23 0x23#define ET_REG24 0x24#define ET_REG25 0x25/* base registers for luma calculation */#define ET_LUMA_CENTER 0x39#define ET_G_RED 0x4d#define ET_G_GREEN1 0x4e#define ET_G_BLUE 0x4f#define ET_G_GREEN2 0x50#define ET_G_GR_H 0x51#define ET_G_GB_H 0x52#define ET_O_RED 0x34#define ET_O_GREEN1 0x35#define ET_O_BLUE 0x36#define ET_O_GREEN2 0x37#define ET_SYNCHRO 0x68#define ET_STARTX 0x69#define ET_STARTY 0x6a#define ET_WIDTH_LOW 0x6b#define ET_HEIGTH_LOW 0x6c#define ET_W_H_HEIGTH 0x6d#define ET_REG6e 0x6e /* OBW */#define ET_REG6f 0x6f /* OBW */#define ET_REG70 0x70 /* OBW_AWB */#define ET_REG71 0x71 /* OBW_AWB */#define ET_REG72 0x72 /* OBW_AWB */#define ET_REG73 0x73 /* Clkdelay ns */#define ET_REG74 0x74 /* test pattern */#define ET_REG75 0x75 /* test pattern */#define ET_I2C_CLK 0x8c#define ET_PXL_CLK 0x60#define ET_I2C_BASE 0x89#define ET_I2C_COUNT 0x8a#define ET_I2C_PREFETCH 0x8b#define ET_I2C_REG 0x88#define ET_I2C_DATA7 0x87#define ET_I2C_DATA6 0x86#define ET_I2C_DATA5 0x85#define ET_I2C_DATA4 0x84#define ET_I2C_DATA3 0x83#define ET_I2C_DATA2 0x82#define ET_I2C_DATA1 0x81#define ET_I2C_DATA0 0x80#define PAS106_REG2 0x02 /* pxlClk = systemClk/(reg2) */#define PAS106_REG3 0x03 /* line/frame H [11..4] */#define PAS106_REG4 0x04 /* line/frame L [3..0] */#define PAS106_REG5 0x05 /* exposure time line offset(default 5) */#define PAS106_REG6 0x06 /* exposure time pixel offset(default 6) */#define PAS106_REG7 0x07 /* signbit Dac (default 0) */#define PAS106_REG9 0x09#define PAS106_REG0e 0x0e /* global gain [4..0](default 0x0e) */#define PAS106_REG13 0x13 /* end i2c write */static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d };static const __u8 I2c3[] = { 0x12, 0x05 };static const __u8 I2c4[] = { 0x41, 0x08 };/* read 'len' bytes to gspca_dev->usb_buf */static void reg_r(struct gspca_dev *gspca_dev, __u16 index, __u16 len){ struct usb_device *dev = gspca_dev->dev;#ifdef GSPCA_DEBUG if (len > USB_BUF_SZ) { err("reg_r: buffer overflow"); return; }#endif usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, index, gspca_dev->usb_buf, len, 500); PDEBUG(D_USBI, "reg read [%02x] -> %02x ..", index, gspca_dev->usb_buf[0]);}static void reg_w_val(struct gspca_dev *gspca_dev, __u16 index, __u8 val){ struct usb_device *dev = gspca_dev->dev; gspca_dev->usb_buf[0] = val; usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, index, gspca_dev->usb_buf, 1, 500);}static void reg_w(struct gspca_dev *gspca_dev, __u16 index, const __u8 *buffer, __u16 len){ struct usb_device *dev = gspca_dev->dev;#ifdef GSPCA_DEBUG if (len > USB_BUF_SZ) { err("reg_w: buffer overflow"); return; } PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);#endif memcpy(gspca_dev->usb_buf, buffer, len); usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, index, gspca_dev->usb_buf, len, 500);}static int i2c_w(struct gspca_dev *gspca_dev, __u8 reg, const __u8 *buffer, int len, __u8 mode){ /* buffer should be [D0..D7] */ __u8 ptchcount; /* set the base address */ reg_w_val(gspca_dev, ET_I2C_BASE, 0x40); /* sensor base for the pas106 */ /* set count and prefetch */ ptchcount = ((len & 0x07) << 4) | (mode & 0x03); reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount); /* set the register base */ reg_w_val(gspca_dev, ET_I2C_REG, reg); while (--len >= 0) reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]); return 0;}static int i2c_r(struct gspca_dev *gspca_dev, __u8 reg){ /* set the base address */ reg_w_val(gspca_dev, ET_I2C_BASE, 0x40); /* sensor base for the pas106 */ /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */ reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11); reg_w_val(gspca_dev, ET_I2C_REG, reg); /* set the register base */ reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02); /* prefetch */ reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00); reg_r(gspca_dev, ET_I2C_DATA0, 1); /* read one byte */ return 0;}static int Et_WaitStatus(struct gspca_dev *gspca_dev){ int retry = 10; while (retry--) { reg_r(gspca_dev, ET_ClCK, 1); if (gspca_dev->usb_buf[0] != 0) return 1; } return 0;}static int et_video(struct gspca_dev *gspca_dev, int on){ int ret; reg_w_val(gspca_dev, ET_GPIO_OUT, on ? 0x10 /* startvideo - set Bit5 */ : 0); /* stopvideo */ ret = Et_WaitStatus(gspca_dev); if (ret != 0) PDEBUG(D_ERR, "timeout video on/off"); return ret;}static void Et_init2(struct gspca_dev *gspca_dev){ __u8 value; static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 }; PDEBUG(D_STREAM, "Open Init2 ET"); reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f); reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10); reg_r(gspca_dev, ET_GPIO_IN, 1); reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */ reg_w_val(gspca_dev, ET_CTRL, 0x1b); /* compression et subsampling */ if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) value = ET_COMP_VAL1; /* 320 */ else value = ET_COMP_VAL0; /* 640 */ reg_w_val(gspca_dev, ET_COMP, value); reg_w_val(gspca_dev, ET_MAXQt, 0x1f); reg_w_val(gspca_dev, ET_MINQt, 0x04); /* undocumented registers */ reg_w_val(gspca_dev, ET_REG1d, 0xff); reg_w_val(gspca_dev, ET_REG1e, 0xff); reg_w_val(gspca_dev, ET_REG1f, 0xff); reg_w_val(gspca_dev, ET_REG20, 0x35); reg_w_val(gspca_dev, ET_REG21, 0x01); reg_w_val(gspca_dev, ET_REG22, 0x00); reg_w_val(gspca_dev, ET_REG23, 0xff); reg_w_val(gspca_dev, ET_REG24, 0xff); reg_w_val(gspca_dev, ET_REG25, 0x0f); /* colors setting */ reg_w_val(gspca_dev, 0x30, 0x11); /* 0x30 */ reg_w_val(gspca_dev, 0x31, 0x40); reg_w_val(gspca_dev, 0x32, 0x00); reg_w_val(gspca_dev, ET_O_RED, 0x00); /* 0x34 */ reg_w_val(gspca_dev, ET_O_GREEN1, 0x00); reg_w_val(gspca_dev, ET_O_BLUE, 0x00); reg_w_val(gspca_dev, ET_O_GREEN2, 0x00); /*************/ reg_w_val(gspca_dev, ET_G_RED, 0x80); /* 0x4d */ reg_w_val(gspca_dev, ET_G_GREEN1, 0x80); reg_w_val(gspca_dev, ET_G_BLUE, 0x80); reg_w_val(gspca_dev, ET_G_GREEN2, 0x80); reg_w_val(gspca_dev, ET_G_GR_H, 0x00); reg_w_val(gspca_dev, ET_G_GB_H, 0x00); /* 0x52 */ /* Window control registers */ reg_w_val(gspca_dev, 0x61, 0x80); /* use cmc_out */ reg_w_val(gspca_dev, 0x62, 0x02); reg_w_val(gspca_dev, 0x63, 0x03); reg_w_val(gspca_dev, 0x64, 0x14); reg_w_val(gspca_dev, 0x65, 0x0e); reg_w_val(gspca_dev, 0x66, 0x02); reg_w_val(gspca_dev, 0x67, 0x02); /**************************************/ reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f); /* 0x68 */ reg_w_val(gspca_dev, ET_STARTX, 0x69); /* 0x6a //0x69 */ reg_w_val(gspca_dev, ET_STARTY, 0x0d); /* 0x0d //0x0c */ reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80); reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0); reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60); /* 6d */ reg_w_val(gspca_dev, ET_REG6e, 0x86); reg_w_val(gspca_dev, ET_REG6f, 0x01); reg_w_val(gspca_dev, ET_REG70, 0x26); reg_w_val(gspca_dev, ET_REG71, 0x7a); reg_w_val(gspca_dev, ET_REG72, 0x01); /* Clock Pattern registers ***************** */ reg_w_val(gspca_dev, ET_REG73, 0x00); reg_w_val(gspca_dev, ET_REG74, 0x18); /* 0x28 */ reg_w_val(gspca_dev, ET_REG75, 0x0f); /* 0x01 */ /**********************************************/ reg_w_val(gspca_dev, 0x8a, 0x20); reg_w_val(gspca_dev, 0x8d, 0x0f); reg_w_val(gspca_dev, 0x8e, 0x08); /**************************************/ reg_w_val(gspca_dev, 0x03, 0x08); reg_w_val(gspca_dev, ET_PXL_CLK, 0x03); reg_w_val(gspca_dev, 0x81, 0xff); reg_w_val(gspca_dev, 0x80, 0x00); reg_w_val(gspca_dev, 0x81, 0xff); reg_w_val(gspca_dev, 0x80, 0x20); reg_w_val(gspca_dev, 0x03, 0x01); reg_w_val(gspca_dev, 0x03, 0x00); reg_w_val(gspca_dev, 0x03, 0x08); /********************************************//* reg_r(gspca_dev, ET_I2C_BASE, 1); always 0x40 as the pas106 ??? */ /* set the sensor */ if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) value = 0x04; /* 320 */ else /* 640 */ value = 0x1e; /* 0x17 * setting PixelClock * 0x03 mean 24/(3+1) = 6 Mhz * 0x05 -> 24/(5+1) = 4 Mhz * 0x0b -> 24/(11+1) = 2 Mhz * 0x17 -> 24/(23+1) = 1 Mhz */ reg_w_val(gspca_dev, ET_PXL_CLK, value); /* now set by fifo the FormatLine setting */ reg_w(gspca_dev, 0x62, FormLine, 6); /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */ reg_w_val(gspca_dev, 0x81, 0x47); /* 0x47; */ reg_w_val(gspca_dev, 0x80, 0x40); /* 0x40; */ /* Pedro change */ /* Brightness change Brith+ decrease value */ /* Brigth- increase value */ /* original value = 0x70; */ reg_w_val(gspca_dev, 0x81, 0x30); /* 0x20; - set brightness */ reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */}static void setbrightness(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; int i; __u8 brightness = sd->brightness; for (i = 0; i < 4; i++) reg_w_val(gspca_dev, ET_O_RED + i, brightness);}static void getbrightness(struct gspca_dev *gspca_dev){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -