sonixj.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 1,721 行 · 第 1/4 页
C
1,721 行
{ int i = 0; static const __u8 SetSensorClk[] = /* 0x08 Mclk */ { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 }; while (hv7131r_sensor_init[i][0]) { i2c_w8(gspca_dev, hv7131r_sensor_init[i]); i++; } i2c_w8(gspca_dev, SetSensorClk);}static void mi0360_InitSensor(struct gspca_dev *gspca_dev){ int i = 0; while (mi0360_sensor_init[i][0]) { i2c_w8(gspca_dev, mi0360_sensor_init[i]); i++; }}static void mo4000_InitSensor(struct gspca_dev *gspca_dev){ int i = 0; while (mo4000_sensor_init[i][0]) { i2c_w8(gspca_dev, mo4000_sensor_init[i]); i++; }}static void om6802_InitSensor(struct gspca_dev *gspca_dev){ int i = 0; while (om6802_sensor_init[i][0]) { i2c_w8(gspca_dev, om6802_sensor_init[i]); i++; }}static void ov7630_InitSensor(struct gspca_dev *gspca_dev){ int i = 0; i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */ i++; i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */ i++; msleep(20); i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */ i++; i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */ i++; msleep(20); i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */ i++;/*jfm:win i2c_r from 00 to 80*/ while (ov7630_sensor_init[i][0]) { i2c_w8(gspca_dev, ov7630_sensor_init[i]); i++; }}static void ov7648_InitSensor(struct gspca_dev *gspca_dev){ int i = 0; while (ov7648_sensor_init[i][0]) { i2c_w8(gspca_dev, ov7648_sensor_init[i]); i++; }}static void ov7660_InitSensor(struct gspca_dev *gspca_dev){ int i = 0; i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */ i++; msleep(20); while (ov7660_sensor_init[i][0]) { i2c_w8(gspca_dev, ov7660_sensor_init[i]); i++; }}/* 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; cam = &gspca_dev->cam; cam->epaddr = 0x01; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); sd->bridge = id->driver_info >> 16; sd->sensor = id->driver_info >> 8; sd->i2c_base = id->driver_info; sd->qindex = 4; /* set the quantization table */ sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; sd->autogain = AUTOGAIN_DEF; sd->ag_cnt = -1; switch (sd->sensor) { case SENSOR_OV7630: case SENSOR_OV7648: case SENSOR_OV7660: gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX); break; } if (sd->sensor != SENSOR_OV7630) gspca_dev->ctrl_dis |= (1 << VFLIP_IDX); return 0;}/* this function is called at probe and resume time */static int sd_init(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev;/* const __u8 *sn9c1xx; */ __u8 regGpio[] = { 0x29, 0x74 }; __u8 regF1; /* setup a selector by bridge */ reg_w1(gspca_dev, 0xf1, 0x01); reg_r(gspca_dev, 0x00, 1); reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]); reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */ regF1 = gspca_dev->usb_buf[0]; PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1); switch (sd->bridge) { case BRIDGE_SN9C102P: if (regF1 != 0x11) return -ENODEV; reg_w1(gspca_dev, 0x02, regGpio[1]); break; case BRIDGE_SN9C105: if (regF1 != 0x11) return -ENODEV; reg_w(gspca_dev, 0x01, regGpio, 2); break; case BRIDGE_SN9C120: if (regF1 != 0x12) return -ENODEV; regGpio[1] = 0x70; reg_w(gspca_dev, 0x01, regGpio, 2); break; default:/* case BRIDGE_SN9C110: *//* case BRIDGE_SN9C325: */ if (regF1 != 0x12) return -ENODEV; reg_w1(gspca_dev, 0x02, 0x62); break; } reg_w1(gspca_dev, 0xf1, 0x01);#if 1 /*jfm: from win trace*/ return 0;#else sn9c1xx = sn_tb[(int) sd->sensor]; return configure_gpio(gspca_dev, sn9c1xx);#endif}static unsigned int setexposure(struct gspca_dev *gspca_dev, unsigned int expo){ struct sd *sd = (struct sd *) gspca_dev; static const __u8 doit[] = /* update sensor */ { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; static const __u8 sensorgo[] = /* sensor on */ { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 }; static const __u8 gainMo[] = { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d }; switch (sd->sensor) { case SENSOR_HV7131R: { __u8 Expodoit[] = { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 }; Expodoit[3] = expo >> 16; Expodoit[4] = expo >> 8; Expodoit[5] = expo; i2c_w8(gspca_dev, Expodoit); break; } case SENSOR_MI0360: { __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 }; if (expo > 0x0635) expo = 0x0635; else if (expo < 0x0001) expo = 0x0001; expoMi[3] = expo >> 8; expoMi[4] = expo; i2c_w8(gspca_dev, expoMi); i2c_w8(gspca_dev, doit); i2c_w8(gspca_dev, sensorgo); break; } case SENSOR_MO4000: { __u8 expoMof[] = { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 }; __u8 expoMo10[] = { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 }; if (expo > 0x1fff) expo = 0x1fff; else if (expo < 0x0001) expo = 0x0001; expoMof[3] = (expo & 0x03fc) >> 2; i2c_w8(gspca_dev, expoMof); expoMo10[3] = ((expo & 0x1c00) >> 10) | ((expo & 0x0003) << 4); i2c_w8(gspca_dev, expoMo10); i2c_w8(gspca_dev, gainMo); PDEBUG(D_CONF, "set exposure %d", ((expoMo10[3] & 0x07) << 10) | (expoMof[3] << 2) | ((expoMo10[3] & 0x30) >> 4)); break; } case SENSOR_OM6802: { __u8 gainOm[] = { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; if (expo > 0x03ff) expo = 0x03ff; if (expo < 0x0001) expo = 0x0001; gainOm[3] = expo >> 2; i2c_w8(gspca_dev, gainOm); reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f); PDEBUG(D_CONF, "set exposure %d", gainOm[3]); break; } } return expo;}/* this function is used for sensors o76xx only */static void setbrightcont(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; int val; __u8 reg84_full[0x15]; memcpy(reg84_full, reg84, sizeof reg84_full); val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10; /* 10..40 */ reg84_full[0] = (val + 1) / 2; /* red */ reg84_full[2] = val; /* green */ reg84_full[4] = (val + 1) / 5; /* blue */ val = (sd->brightness - BRIGHTNESS_DEF) * 0x10 / BRIGHTNESS_MAX; reg84_full[0x12] = val & 0x1f; /* 5:0 signed value */ reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);}/* sensor != ov76xx */static void setbrightness(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; unsigned int expo; __u8 k2; k2 = sd->brightness >> 10; switch (sd->sensor) { case SENSOR_HV7131R: expo = sd->brightness << 4; if (expo > 0x002dc6c0) expo = 0x002dc6c0; else if (expo < 0x02a0) expo = 0x02a0; sd->exposure = setexposure(gspca_dev, expo); break; case SENSOR_MI0360: case SENSOR_MO4000: expo = sd->brightness >> 4; sd->exposure = setexposure(gspca_dev, expo); break; case SENSOR_OM6802: expo = sd->brightness >> 6; sd->exposure = setexposure(gspca_dev, expo); k2 = sd->brightness >> 11; break; } reg_w1(gspca_dev, 0x96, k2);}/* sensor != ov76xx */static void setcontrast(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; __u8 k2; __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 }; k2 = sd->contrast; contrast[2] = k2; contrast[0] = (k2 + 1) >> 1; contrast[4] = (k2 + 1) / 5; reg_w(gspca_dev, 0x84, contrast, 6);}static void setcolors(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; __u8 blue, red; if (sd->colors >= 32) { red = 32 + (sd->colors - 32) / 2; blue = 64 - sd->colors; } else { red = sd->colors; blue = 32 + (32 - sd->colors) / 2; } reg_w1(gspca_dev, 0x05, red);/* reg_w1(gspca_dev, 0x07, 32); */ reg_w1(gspca_dev, 0x06, blue);}static void setautogain(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) return; if (sd->autogain) sd->ag_cnt = AG_CNT_START; else sd->ag_cnt = -1;}static void setvflip(struct sd *sd){ if (sd->sensor != SENSOR_OV7630) return; i2c_w1(&sd->gspca_dev, 0x75, /* COMN */ sd->vflip ? 0x82 : 0x02);}/* -- start the camera -- */static int sd_start(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; int i; __u8 reg1, reg17, reg18; const __u8 *sn9c1xx; int mode; static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ static const __u8 CE_ov76xx[] = { 0x32, 0xdd, 0x32, 0xdd }; sn9c1xx = sn_tb[(int) sd->sensor]; configure_gpio(gspca_dev, sn9c1xx); reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]); reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */ reg_w1(gspca_dev, 0xd3, 0x50); reg_w1(gspca_dev, 0xc6, 0x00); reg_w1(gspca_dev, 0xc7, 0x00); reg_w1(gspca_dev, 0xc8, 0x50); reg_w1(gspca_dev, 0xc9, 0x3c); reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); switch (sd->sensor) { case SENSOR_OV7630: reg17 = 0xe2; break; case SENSOR_OV7648: reg17 = 0xae; break;#if 1/*jfm: from win trace */ case SENSOR_OV7660: reg17 = 0xa0; break;#endif default: reg17 = 0x60; break; } reg_w1(gspca_dev, 0x17, reg17); reg_w1(gspca_dev, 0x05, sn9c1xx[5]); reg_w1(gspca_dev, 0x07, sn9c1xx[7]); reg_w1(gspca_dev, 0x06, sn9c1xx[6]); reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def); for (i = 0; i < 8; i++) reg_w(gspca_dev, 0x84, reg84, sizeof reg84); switch (sd->sensor) { case SENSOR_OV7660: reg_w1(gspca_dev, 0x9a, 0x05); break; default: reg_w1(gspca_dev, 0x9a, 0x08); reg_w1(gspca_dev, 0x99, 0x59); break; } mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; if (mode) reg1 = 0x46; /* 320 clk 48Mhz */ else reg1 = 0x06; /* 640 clk 24Mz */ reg17 = 0x61; switch (sd->sensor) { case SENSOR_HV7131R: hv7131R_InitSensor(gspca_dev); break; case SENSOR_MI0360: mi0360_InitSensor(gspca_dev); break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?