usbvision-core.c
来自「linux 内核源代码」· C语言 代码 · 共 2,307 行 · 第 1/5 页
C
2,307 行
frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; */ errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop); return errCode;}/* * usbvision_frames_alloc * allocate the required frames */int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames){ int i; /*needs to be page aligned cause the buffers can be mapped individually! */ usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * usbvision->curheight * usbvision->palette.bytes_per_pixel); /* Try to do my best to allocate the frames the user want in the remaining memory */ usbvision->num_frames = number_of_frames; while (usbvision->num_frames > 0) { usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size; if((usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size))) { break; } usbvision->num_frames--; } spin_lock_init(&usbvision->queue_lock); init_waitqueue_head(&usbvision->wait_frame); init_waitqueue_head(&usbvision->wait_stream); /* Allocate all buffers */ for (i = 0; i < usbvision->num_frames; i++) { usbvision->frame[i].index = i; usbvision->frame[i].grabstate = FrameState_Unused; usbvision->frame[i].data = usbvision->fbuf + i * usbvision->max_frame_size; /* * Set default sizes for read operation. */ usbvision->stretch_width = 1; usbvision->stretch_height = 1; usbvision->frame[i].width = usbvision->curwidth; usbvision->frame[i].height = usbvision->curheight; usbvision->frame[i].bytes_read = 0; } PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",usbvision->num_frames,usbvision->max_frame_size); return usbvision->num_frames;}/* * usbvision_frames_free * frees memory allocated for the frames */void usbvision_frames_free(struct usb_usbvision *usbvision){ /* Have to free all that memory */ PDEBUG(DBG_FUNC, "free %d frames",usbvision->num_frames); if (usbvision->fbuf != NULL) { usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); usbvision->fbuf = NULL; usbvision->num_frames = 0; }}/* * usbvision_empty_framequeues() * prepare queues for incoming and outgoing frames */void usbvision_empty_framequeues(struct usb_usbvision *usbvision){ u32 i; INIT_LIST_HEAD(&(usbvision->inqueue)); INIT_LIST_HEAD(&(usbvision->outqueue)); for (i = 0; i < USBVISION_NUMFRAMES; i++) { usbvision->frame[i].grabstate = FrameState_Unused; usbvision->frame[i].bytes_read = 0; }}/* * usbvision_stream_interrupt() * stops streaming */int usbvision_stream_interrupt(struct usb_usbvision *usbvision){ int ret = 0; /* stop reading from the device */ usbvision->streaming = Stream_Interrupt; ret = wait_event_timeout(usbvision->wait_stream, (usbvision->streaming == Stream_Idle), msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); return ret;}/* * usbvision_set_compress_params() * */static int usbvision_set_compress_params(struct usb_usbvision *usbvision){ static const char proc[] = "usbvision_set_compresion_params: "; int rc; unsigned char value[6]; value[0] = 0x0F; // Intra-Compression cycle value[1] = 0x01; // Reg.45 one line per strip value[2] = 0x00; // Reg.46 Force intra mode on all new frames value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force) value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression //catched values for NT1004 // value[0] = 0xFF; // Never apply intra mode automatically // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip // value[2] = 0x01; // Force intra mode on all new frames // value[3] = 0x00; // Strip size 400 Bytes; do not force up // value[4] = 0xA2; // if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) USBVISION_INTRA_CYC, value, 5, HZ); if (rc < 0) { printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); return rc; } if (usbvision->bridgeType == BRIDGE_NT1004) { value[0] = 20; // PCM Threshold 1 value[1] = 12; // PCM Threshold 2 value[2] = 255; // Distorsion Threshold inter value[3] = 255; // Distorsion Threshold intra value[4] = 43; // Max Distorsion inter value[5] = 43; // Max Distorsion intra } else { value[0] = 20; // PCM Threshold 1 value[1] = 12; // PCM Threshold 2 value[2] = 255; // Distorsion Threshold d7-d0 value[3] = 0; // Distorsion Threshold d11-d8 value[4] = 43; // Max Distorsion d7-d0 value[5] = 0; // Max Distorsion d8 } if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) USBVISION_PCM_THR1, value, 6, HZ); if (rc < 0) { printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); return rc; } return rc;}/* * usbvision_set_input() * * Set the input (saa711x, ...) size x y and other misc input params * I've no idea if this parameters are right * */int usbvision_set_input(struct usb_usbvision *usbvision){ static const char proc[] = "usbvision_set_input: "; int rc; unsigned char value[8]; unsigned char dvi_yuv_value; if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; /* Set input format expected from decoder*/ if (usbvision_device_data[usbvision->DevModel].Vin_Reg1_override) { value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1; } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { /* SAA7113 uses 8 bit output */ value[0] = USBVISION_8_422_SYNC; } else { /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses * as that is how saa7111 is configured */ value[0] = USBVISION_16_422_SYNC; /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/ } rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]); if (rc < 0) { printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); return rc; } if (usbvision->tvnormId & V4L2_STD_PAL) { value[0] = 0xC0; value[1] = 0x02; //0x02C0 -> 704 Input video line length value[2] = 0x20; value[3] = 0x01; //0x0120 -> 288 Input video n. of lines value[4] = 0x60; value[5] = 0x00; //0x0060 -> 96 Input video h offset value[6] = 0x16; value[7] = 0x00; //0x0016 -> 22 Input video v offset } else if (usbvision->tvnormId & V4L2_STD_SECAM) { value[0] = 0xC0; value[1] = 0x02; //0x02C0 -> 704 Input video line length value[2] = 0x20; value[3] = 0x01; //0x0120 -> 288 Input video n. of lines value[4] = 0x01; value[5] = 0x00; //0x0001 -> 01 Input video h offset value[6] = 0x01; value[7] = 0x00; //0x0001 -> 01 Input video v offset } else { /* V4L2_STD_NTSC */ value[0] = 0xD0; value[1] = 0x02; //0x02D0 -> 720 Input video line length value[2] = 0xF0; value[3] = 0x00; //0x00F0 -> 240 Input video number of lines value[4] = 0x50; value[5] = 0x00; //0x0050 -> 80 Input video h offset value[6] = 0x10; value[7] = 0x00; //0x0010 -> 16 Input video v offset } if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) { value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff; value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8; } if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) { value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff; value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8; } rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, /* USBVISION specific code */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) USBVISION_LXSIZE_I, value, 8, HZ); if (rc < 0) { printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); return rc; } dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ if(usbvision_device_data[usbvision->DevModel].Dvi_yuv_override){ dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv; } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { /* This changes as the fine sync control changes. Further investigation necessary */ dvi_yuv_value = 0x06; } return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value));}/* * usbvision_set_dram_settings() * * Set the buffer address needed by the usbvision dram to operate * This values has been taken with usbsnoop. * */static int usbvision_set_dram_settings(struct usb_usbvision *usbvision){ int rc; unsigned char value[8]; if (usbvision->isocMode == ISOC_MODE_COMPRESS) { value[0] = 0x42; value[1] = 0x71; value[2] = 0xff; value[3] = 0x00; value[4] = 0x98; value[5] = 0xe0; value[6] = 0x71; value[7] = 0xff; // UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) // FDL: 0x00000-0x0E099 = 57498 Words // VDW: 0x0E3FF-0x3FFFF } else { value[0] = 0x42; value[1] = 0x00; value[2] = 0xff; value[3] = 0x00; value[4] = 0x00; value[5] = 0x00; value[6] = 0x00; value[7] = 0xff; } /* These are the values of the address of the video buffer, * they have to be loaded into the USBVISION_DRM_PRM1-8 * * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 * Only used in compressed mode * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff * Only used in compressed mode * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff */ if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, /* USBVISION specific code */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) USBVISION_DRM_PRM1, value, 8, HZ); if (rc < 0) { err("%sERROR=%d", __FUNCTION__, rc); return rc; } /* Restart the video buffer logic */ if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0) return rc; rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00); return rc;}/* * () * * Power on the device, enables suspend-resume logic * & reset the isoc End-Point * */int usbvision_power_on(struct usb_usbvision *usbvision){ int errCode = 0; PDEBUG(DBG_FUNC, ""); usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_RES2); usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_PWR_VID); errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); if (errCode == 1) { usbvision->power = 1; } PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode); return errCode;}/* * usbvision timer stuff */// to call usbvision_power_off from task queuestatic void call_usbvision_power_off(struct work_struct *work){ struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork); PDEBUG(DBG_FUNC, ""); down_interruptible(&usbvision->lock); if(usbvision->user == 0) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; } up(&usbvision->lock);}static void usbvision_powerOffTimer(unsigned long data){ struct usb_usbvision *usbvision = (void *) data; PDEBUG(DBG_FUNC, ""); del_timer(&usbvision->powerOffTimer); INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off); (void) schedule_work(&usbvision->powerOffWork);}void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision){ init_timer(&usbvision->powerOffTimer); usbvision->powerOffTimer.data = (long) usbvision; usbvision->powerOffTimer.function = usbvision_powerOffTimer;}void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision){ mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME);}void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision){ if (timer_pending(&usbvision->powerOffTimer)) { del_timer(&usbvision->powerOffTimer); }}/* * usbvision_begin_streaming() * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no * idea about the rest */int usbvision_begin_streaming(struct usb_usbvision *usbvision){ int errCode = 0; if (usbvision->isocMode == ISOC_MODE_COMPRESS) { usbvision_init_compression(usbvision); } errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | usbvision->Vin_Reg2_Preset); return errCode;}/* * usbvision_restart_isoc() * Not sure yet if touching here PWR_REG make loose the config */int usbvision_restart_isoc(struct
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?