tv8532.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 670 行 · 第 1/2 页
C
670 行
/* * Quickcam cameras initialization data * * 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 "tv8532"#include "gspca.h"MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");MODULE_DESCRIPTION("TV8532 USB Camera Driver");MODULE_LICENSE("GPL");/* specific webcam descriptor */struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ int buflen; /* current length of tmpbuf */ __u8 tmpbuf[352 * 288 + 10 * 288]; /* no protection... */ __u8 tmpbuf2[352 * 288]; /* no protection... */ unsigned short brightness; unsigned short contrast; char packet; char synchro;};/* 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 struct ctrl sd_ctrls[] = {#define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = 1, .maximum = 0x2ff, .step = 1, .default_value = 0x18f, }, .set = sd_setbrightness, .get = sd_getbrightness, },#define SD_CONTRAST 1 { { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, .maximum = 0xffff, .step = 1, .default_value = 0x7fff, }, .set = sd_setcontrast, .get = sd_getcontrast, },};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},};/* * Initialization data: this is the first set-up data written to the * device (before the open data). */#define TESTCLK 0x10 /* reg 0x2c -> 0x12 //10 */#define TESTCOMP 0x90 /* reg 0x28 -> 0x80 */#define TESTLINE 0x81 /* reg 0x29 -> 0x81 */#define QCIFLINE 0x41 /* reg 0x29 -> 0x81 */#define TESTPTL 0x14 /* reg 0x2D -> 0x14 */#define TESTPTH 0x01 /* reg 0x2E -> 0x01 */#define TESTPTBL 0x12 /* reg 0x2F -> 0x0a */#define TESTPTBH 0x01 /* reg 0x30 -> 0x01 */#define ADWIDTHL 0xe8 /* reg 0x0c -> 0xe8 */#define ADWIDTHH 0x03 /* reg 0x0d -> 0x03 */#define ADHEIGHL 0x90 /* reg 0x0e -> 0x91 //93 */#define ADHEIGHH 0x01 /* reg 0x0f -> 0x01 */#define EXPOL 0x8f /* reg 0x1c -> 0x8f */#define EXPOH 0x01 /* reg 0x1d -> 0x01 */#define ADCBEGINL 0x44 /* reg 0x10 -> 0x46 //47 */#define ADCBEGINH 0x00 /* reg 0x11 -> 0x00 */#define ADRBEGINL 0x0a /* reg 0x14 -> 0x0b //0x0c */#define ADRBEGINH 0x00 /* reg 0x15 -> 0x00 */#define TV8532_CMD_UPDATE 0x84#define TV8532_EEprom_Add 0x03#define TV8532_EEprom_DataL 0x04#define TV8532_EEprom_DataM 0x05#define TV8532_EEprom_DataH 0x06#define TV8532_EEprom_TableLength 0x07#define TV8532_EEprom_Write 0x08#define TV8532_PART_CTRL 0x00#define TV8532_CTRL 0x01#define TV8532_CMD_EEprom_Open 0x30#define TV8532_CMD_EEprom_Close 0x29#define TV8532_UDP_UPDATE 0x31#define TV8532_GPIO 0x39#define TV8532_GPIO_OE 0x3B#define TV8532_REQ_RegWrite 0x02#define TV8532_REQ_RegRead 0x03#define TV8532_ADWIDTH_L 0x0C#define TV8532_ADWIDTH_H 0x0D#define TV8532_ADHEIGHT_L 0x0E#define TV8532_ADHEIGHT_H 0x0F#define TV8532_EXPOSURE 0x1C#define TV8532_QUANT_COMP 0x28#define TV8532_MODE_PACKET 0x29#define TV8532_SETCLK 0x2C#define TV8532_POINT_L 0x2D#define TV8532_POINT_H 0x2E#define TV8532_POINTB_L 0x2F#define TV8532_POINTB_H 0x30#define TV8532_BUDGET_L 0x2A#define TV8532_BUDGET_H 0x2B#define TV8532_VID_L 0x34#define TV8532_VID_H 0x35#define TV8532_PID_L 0x36#define TV8532_PID_H 0x37#define TV8532_DeviceID 0x83#define TV8532_AD_SLOPE 0x91#define TV8532_AD_BITCTRL 0x94#define TV8532_AD_COLBEGIN_L 0x10#define TV8532_AD_COLBEGIN_H 0x11#define TV8532_AD_ROWBEGIN_L 0x14#define TV8532_AD_ROWBEGIN_H 0x15static const __u32 tv_8532_eeprom_data[] = {/* add dataL dataM dataH */ 0x00010001, 0x01018011, 0x02050014, 0x0305001c, 0x040d001e, 0x0505001f, 0x06050519, 0x0705011b, 0x0805091e, 0x090d892e, 0x0a05892f, 0x0b050dd9, 0x0c0509f1, 0};static int reg_r(struct gspca_dev *gspca_dev, __u16 index){ usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), TV8532_REQ_RegRead, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, 1, 500); return gspca_dev->usb_buf[0];}/* write 1 byte */static void reg_w_1(struct gspca_dev *gspca_dev, __u16 index, __u8 value){ gspca_dev->usb_buf[0] = value; usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), TV8532_REQ_RegWrite, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, 1, 500);}/* write 2 bytes */static void reg_w_2(struct gspca_dev *gspca_dev, __u16 index, __u8 val1, __u8 val2){ gspca_dev->usb_buf[0] = val1; gspca_dev->usb_buf[1] = val2; usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), TV8532_REQ_RegWrite, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, 2, 500);}static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev){ int i = 0; __u8 reg, data0, data1, data2; reg_w_1(gspca_dev, TV8532_GPIO, 0xb0); reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Open);/* msleep(1); */ while (tv_8532_eeprom_data[i]) { reg = (tv_8532_eeprom_data[i] & 0xff000000) >> 24; reg_w_1(gspca_dev, TV8532_EEprom_Add, reg); /* msleep(1); */ data0 = (tv_8532_eeprom_data[i] & 0x000000ff); reg_w_1(gspca_dev, TV8532_EEprom_DataL, data0); /* msleep(1); */ data1 = (tv_8532_eeprom_data[i] & 0x0000ff00) >> 8; reg_w_1(gspca_dev, TV8532_EEprom_DataM, data1); /* msleep(1); */ data2 = (tv_8532_eeprom_data[i] & 0x00ff0000) >> 16; reg_w_1(gspca_dev, TV8532_EEprom_DataH, data2); /* msleep(1); */ reg_w_1(gspca_dev, TV8532_EEprom_Write, 0); /* msleep(10); */ i++; } reg_w_1(gspca_dev, TV8532_EEprom_TableLength, i);/* msleep(1); */ reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Close); msleep(10);}/* this function is called at probe time */static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id){ struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; tv_8532WriteEEprom(gspca_dev); cam = &gspca_dev->cam; cam->epaddr = 1; cam->cam_mode = sif_mode; cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; return 0;}static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev){ __u8 data; data = reg_r(gspca_dev, 0x0001); PDEBUG(D_USBI, "register 0x01-> %x", data); data = reg_r(gspca_dev, 0x0002); PDEBUG(D_USBI, "register 0x02-> %x", data); reg_r(gspca_dev, TV8532_ADWIDTH_L); reg_r(gspca_dev, TV8532_ADWIDTH_H); reg_r(gspca_dev, TV8532_QUANT_COMP); reg_r(gspca_dev, TV8532_MODE_PACKET); reg_r(gspca_dev, TV8532_SETCLK); reg_r(gspca_dev, TV8532_POINT_L); reg_r(gspca_dev, TV8532_POINT_H); reg_r(gspca_dev, TV8532_POINTB_L); reg_r(gspca_dev, TV8532_POINTB_H); reg_r(gspca_dev, TV8532_BUDGET_L); reg_r(gspca_dev, TV8532_BUDGET_H); reg_r(gspca_dev, TV8532_VID_L); reg_r(gspca_dev, TV8532_VID_H); reg_r(gspca_dev, TV8532_PID_L); reg_r(gspca_dev, TV8532_PID_H); reg_r(gspca_dev, TV8532_DeviceID); reg_r(gspca_dev, TV8532_AD_COLBEGIN_L); reg_r(gspca_dev, TV8532_AD_COLBEGIN_H); reg_r(gspca_dev, TV8532_AD_ROWBEGIN_L); reg_r(gspca_dev, TV8532_AD_ROWBEGIN_H);}static void tv_8532_setReg(struct gspca_dev *gspca_dev){ reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L, ADCBEGINL); /* 0x10 */ reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H, ADCBEGINH); /* also digital gain */ reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE); /* 0x00<-0x84 */ reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0a); /******************************************************/ reg_w_1(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL); /* 0e */ reg_w_1(gspca_dev, TV8532_ADHEIGHT_H, ADHEIGHH); /* 0f */ reg_w_2(gspca_dev, TV8532_EXPOSURE, EXPOL, EXPOH); /* 350d 0x014c; 1c */ reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L, ADCBEGINL); /* 0x10 */ reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H, ADCBEGINH); /* also digital gain */ reg_w_1(gspca_dev, TV8532_AD_ROWBEGIN_L, ADRBEGINL); /* 0x14 */ reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00); /* 0x91 */ reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x02); /* 0x94 */ reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Close); /* 0x01 */ reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00); /* 0x91 */ reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE); /* 0x00<-0x84 */}static void tv_8532_PollReg(struct gspca_dev *gspca_dev){ int i; /* strange polling from tgc */ for (i = 0; i < 10; i++) { reg_w_1(gspca_dev, TV8532_SETCLK, TESTCLK); /* 0x48; //0x08; 0x2c */ reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE); reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */ }}/* this function is called at probe and resume time */static int sd_init(struct gspca_dev *gspca_dev)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?