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 + -
显示快捷键?