tv8532.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 670 行 · 第 1/2 页
C
670 行
{ reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); tv_8532ReadRegisters(gspca_dev); reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); reg_w_2(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL, ADHEIGHH); /* 401d 0x0169; 0e */ reg_w_2(gspca_dev, TV8532_EXPOSURE, EXPOL, EXPOH); /* 350d 0x014c; 1c */ reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL); /* 0x20; 0x0c */ reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH); /* 0x0d */ /*******************************************************************/ reg_w_1(gspca_dev, TV8532_QUANT_COMP, TESTCOMP); /* 0x72 compressed mode 0x28 */ reg_w_1(gspca_dev, TV8532_MODE_PACKET, TESTLINE); /* 0x84; // CIF | 4 packet 0x29 */ /************************************************/ reg_w_1(gspca_dev, TV8532_SETCLK, TESTCLK); /* 0x48; //0x08; 0x2c */ reg_w_1(gspca_dev, TV8532_POINT_L, TESTPTL); /* 0x38; 0x2d */ reg_w_1(gspca_dev, TV8532_POINT_H, TESTPTH); /* 0x04; 0x2e */ reg_w_1(gspca_dev, TV8532_POINTB_L, TESTPTBL); /* 0x04; 0x2f */ reg_w_1(gspca_dev, TV8532_POINTB_H, TESTPTBH); /* 0x04; 0x30 */ reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE); /* 0x00<-0x84 */ /*************************************************/ reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */ msleep(200); reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ /*************************************************/ tv_8532_setReg(gspca_dev); /*************************************************/ reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); /*************************************************/ tv_8532_setReg(gspca_dev); /*************************************************/ tv_8532_PollReg(gspca_dev); return 0;}static void setbrightness(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev; int brightness = sd->brightness; reg_w_2(gspca_dev, TV8532_EXPOSURE, brightness >> 8, brightness); /* 1c */ reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);}/* -- start the camera -- */static int sd_start(struct gspca_dev *gspca_dev){ reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); tv_8532ReadRegisters(gspca_dev); reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); reg_w_2(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL, ADHEIGHH); /* 401d 0x0169; 0e *//* reg_w_2(gspca_dev, TV8532_EXPOSURE, EXPOL, EXPOH); * 350d 0x014c; 1c */ setbrightness(gspca_dev); reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL); /* 0x20; 0x0c */ reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH); /* 0x0d */ /************************************************/ reg_w_1(gspca_dev, TV8532_QUANT_COMP, TESTCOMP); /* 0x72 compressed mode 0x28 */ if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { /* 176x144 */ reg_w_1(gspca_dev, TV8532_MODE_PACKET, QCIFLINE); /* 0x84; // CIF | 4 packet 0x29 */ } else { /* 352x288 */ reg_w_1(gspca_dev, TV8532_MODE_PACKET, TESTLINE); /* 0x84; // CIF | 4 packet 0x29 */ } /************************************************/ reg_w_1(gspca_dev, TV8532_SETCLK, TESTCLK); /* 0x48; //0x08; 0x2c */ reg_w_1(gspca_dev, TV8532_POINT_L, TESTPTL); /* 0x38; 0x2d */ reg_w_1(gspca_dev, TV8532_POINT_H, TESTPTH); /* 0x04; 0x2e */ reg_w_1(gspca_dev, TV8532_POINTB_L, TESTPTBL); /* 0x04; 0x2f */ reg_w_1(gspca_dev, TV8532_POINTB_H, TESTPTBH); /* 0x04; 0x30 */ reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE); /* 0x00<-0x84 */ /************************************************/ reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */ msleep(200); reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ /************************************************/ tv_8532_setReg(gspca_dev); /************************************************/ reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); /************************************************/ tv_8532_setReg(gspca_dev); /************************************************/ tv_8532_PollReg(gspca_dev); reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ return 0;}static void sd_stopN(struct gspca_dev *gspca_dev){ reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);}static void tv8532_preprocess(struct gspca_dev *gspca_dev){ struct sd *sd = (struct sd *) gspca_dev;/* we should received a whole frame with header and EOL marker * in gspca_dev->tmpbuf and return a GBRG pattern in gspca_dev->tmpbuf2 * sequence 2bytes header the Alternate pixels bayer GB 4 bytes * Alternate pixels bayer RG 4 bytes EOL */ int width = gspca_dev->width; int height = gspca_dev->height; unsigned char *dst = sd->tmpbuf2; unsigned char *data = sd->tmpbuf; int i; /* precompute where is the good bayer line */ if (((data[3] + data[width + 7]) >> 1) + (data[4] >> 2) + (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1) + (data[3] >> 2) + (data[width + 5] >> 1)) data += 3; else data += 2; for (i = 0; i < height / 2; i++) { memcpy(dst, data, width); data += width + 3; dst += width; memcpy(dst, data, width); data += width + 7; dst += width; }}static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */{ struct sd *sd = (struct sd *) gspca_dev; if (data[0] != 0x80) { sd->packet++; if (sd->buflen + len > sizeof sd->tmpbuf) { if (gspca_dev->last_packet_type != DISCARD_PACKET) { PDEBUG(D_PACK, "buffer overflow"); gspca_dev->last_packet_type = DISCARD_PACKET; } return; } memcpy(&sd->tmpbuf[sd->buflen], data, len); sd->buflen += len; return; } /* here we detect 0x80 */ /* counter is limited so we need few header for a frame :) */ /* header 0x80 0x80 0x80 0x80 0x80 */ /* packet 00 63 127 145 00 */ /* sof 0 1 1 0 0 */ /* update sequence */ if (sd->packet == 63 || sd->packet == 127) sd->synchro = 1; /* is there a frame start ? */ if (sd->packet >= (gspca_dev->height >> 1) - 1) { PDEBUG(D_PACK, "SOF > %d packet %d", sd->synchro, sd->packet); if (!sd->synchro) { /* start of frame */ if (gspca_dev->last_packet_type == FIRST_PACKET) { tv8532_preprocess(gspca_dev); frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, sd->tmpbuf2, gspca_dev->width * gspca_dev->width); } gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); memcpy(sd->tmpbuf, data, len); sd->buflen = len; sd->packet = 0; return; } if (gspca_dev->last_packet_type != DISCARD_PACKET) { PDEBUG(D_PACK, "Warning wrong TV8532 frame detection %d", sd->packet); gspca_dev->last_packet_type = DISCARD_PACKET; } return; } if (!sd->synchro) { /* Drop packet frame corrupt */ PDEBUG(D_PACK, "DROP SOF %d packet %d", sd->synchro, sd->packet); sd->packet = 0; gspca_dev->last_packet_type = DISCARD_PACKET; return; } sd->synchro = 1; sd->packet++; memcpy(&sd->tmpbuf[sd->buflen], data, len); sd->buflen += len;}static void setcontrast(struct gspca_dev *gspca_dev){#if 0 value[0] = (gspca_dev->contrast) & 0xff; value[1] = (gspca_dev->contrast >> 8) & 0xff; reg_w_1(gspca_dev, 0x0020, value[1]); reg_w_1(gspca_dev, 0x0022, value[1]); reg_w_1(gspca_dev, 0x0024, value[1]); reg_w_1(gspca_dev, 0x0026, value[1]); reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);#endif}static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->brightness = val; if (gspca_dev->streaming) setbrightness(gspca_dev); return 0;}static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; *val = sd->brightness; return 0;}static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val){ struct sd *sd = (struct sd *) gspca_dev; sd->contrast = val; if (gspca_dev->streaming) setcontrast(gspca_dev); return 0;}static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val){ struct sd *sd = (struct sd *) gspca_dev; *val = sd->contrast; return 0;}/* sub-driver description */static const struct sd_desc sd_desc = { .name = MODULE_NAME, .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, .init = sd_init, .start = sd_start, .stopN = sd_stopN, .pkt_scan = sd_pkt_scan,};/* -- module initialisation -- */static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x0920)}, {USB_DEVICE(0x046d, 0x0921)}, {USB_DEVICE(0x0545, 0x808b)}, {USB_DEVICE(0x0545, 0x8333)}, {USB_DEVICE(0x0923, 0x010f)}, {}};MODULE_DEVICE_TABLE(usb, device_table);/* -- device connect -- */static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id){ return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), THIS_MODULE);}static struct usb_driver sd_driver = { .name = MODULE_NAME, .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect,#ifdef CONFIG_PM .suspend = gspca_suspend, .resume = gspca_resume,#endif};/* -- module insert / remove -- */static int __init sd_mod_init(void){ if (usb_register(&sd_driver) < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0;}static void __exit sd_mod_exit(void){ usb_deregister(&sd_driver); PDEBUG(D_PROBE, "deregistered");}module_init(sd_mod_init);module_exit(sd_mod_exit);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?