⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vino.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 5 页
字号:
		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Blue Balance",		.minimum = INDYCAM_BLUE_BALANCE_MIN,		.maximum = INDYCAM_BLUE_BALANCE_MAX,		.step = 1,		.default_value = INDYCAM_BLUE_BALANCE_DEFAULT,		.flags = 0,		.reserved = { INDYCAM_CONTROL_BLUE_BALANCE, 0 },	},{		.id = V4L2_CID_EXPOSURE,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Shutter Control",		.minimum = INDYCAM_SHUTTER_MIN,		.maximum = INDYCAM_SHUTTER_MAX,		.step = 1,		.default_value = INDYCAM_SHUTTER_DEFAULT,		.flags = 0,		.reserved = { INDYCAM_CONTROL_SHUTTER, 0 },	},{		.id = V4L2_CID_GAMMA,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Gamma",		.minimum = INDYCAM_GAMMA_MIN,		.maximum = INDYCAM_GAMMA_MAX,		.step = 1,		.default_value = INDYCAM_GAMMA_DEFAULT,		.flags = 0,		.reserved = { INDYCAM_CONTROL_GAMMA, 0 },	}};#define VINO_SAA7191_V4L2_CONTROL_COUNT		9struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {	{		.id = V4L2_CID_HUE,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Hue",		.minimum = SAA7191_HUE_MIN,		.maximum = SAA7191_HUE_MAX,		.step = 1,		.default_value = SAA7191_HUE_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_HUE, 0 },	},{		.id = V4L2_CID_PRIVATE_BASE,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Luminance Bandpass",		.minimum = SAA7191_BANDPASS_MIN,		.maximum = SAA7191_BANDPASS_MAX,		.step = 1,		.default_value = SAA7191_BANDPASS_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_BANDPASS, 0 },	},{		.id = V4L2_CID_PRIVATE_BASE + 1,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Luminance Bandpass Weight",		.minimum = SAA7191_BANDPASS_WEIGHT_MIN,		.maximum = SAA7191_BANDPASS_WEIGHT_MAX,		.step = 1,		.default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_BANDPASS_WEIGHT, 0 },	},{		.id = V4L2_CID_PRIVATE_BASE + 2,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "HF Luminance Coring",		.minimum = SAA7191_CORING_MIN,		.maximum = SAA7191_CORING_MAX,		.step = 1,		.default_value = SAA7191_CORING_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_CORING, 0 },	},{		.id = V4L2_CID_PRIVATE_BASE + 3,		.type = V4L2_CTRL_TYPE_BOOLEAN,		.name = "Force Colour",		.minimum = SAA7191_FORCE_COLOUR_MIN,		.maximum = SAA7191_FORCE_COLOUR_MAX,		.step = 1,		.default_value = SAA7191_FORCE_COLOUR_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_FORCE_COLOUR, 0 },	},{		.id = V4L2_CID_PRIVATE_BASE + 4,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Chrominance Gain Control",		.minimum = SAA7191_CHROMA_GAIN_MIN,		.maximum = SAA7191_CHROMA_GAIN_MAX,		.step = 1,		.default_value = SAA7191_CHROMA_GAIN_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_CHROMA_GAIN, 0 },	},{		.id = V4L2_CID_PRIVATE_BASE + 5,		.type = V4L2_CTRL_TYPE_BOOLEAN,		.name = "VTR Time Constant",		.minimum = SAA7191_VTRC_MIN,		.maximum = SAA7191_VTRC_MAX,		.step = 1,		.default_value = SAA7191_VTRC_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_VTRC, 0 },	},{		.id = V4L2_CID_PRIVATE_BASE + 6,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Luminance Delay Compensation",		.minimum = SAA7191_LUMA_DELAY_MIN,		.maximum = SAA7191_LUMA_DELAY_MAX,		.step = 1,		.default_value = SAA7191_LUMA_DELAY_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_LUMA_DELAY, 0 },	},{		.id = V4L2_CID_PRIVATE_BASE + 7,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Vertical Noise Reduction",		.minimum = SAA7191_VNR_MIN,		.maximum = SAA7191_VNR_MAX,		.step = 1,		.default_value = SAA7191_VNR_DEFAULT,		.flags = 0,		.reserved = { SAA7191_CONTROL_VNR, 0 },	}};/* VINO I2C bus functions */unsigned i2c_vino_getctrl(void *data){	return vino->i2c_control;}void i2c_vino_setctrl(void *data, unsigned val){	vino->i2c_control = val;}unsigned i2c_vino_rdata(void *data){	return vino->i2c_data;}void i2c_vino_wdata(void *data, unsigned val){	vino->i2c_data = val;}static struct i2c_algo_sgi_data i2c_sgi_vino_data ={	.getctrl = &i2c_vino_getctrl,	.setctrl = &i2c_vino_setctrl,	.rdata   = &i2c_vino_rdata,	.wdata   = &i2c_vino_wdata,	.xfer_timeout = 200,	.ack_timeout  = 1000,};/* * There are two possible clients on VINO I2C bus, so we limit usage only * to them. */static int i2c_vino_client_reg(struct i2c_client *client){	unsigned long flags;	int ret = 0;	spin_lock_irqsave(&vino_drvdata->input_lock, flags);	switch (client->driver->id) {	case I2C_DRIVERID_SAA7191:		if (vino_drvdata->decoder.driver)			ret = -EBUSY;		else			vino_drvdata->decoder.driver = client;		break;	case I2C_DRIVERID_INDYCAM:		if (vino_drvdata->camera.driver)			ret = -EBUSY;		else			vino_drvdata->camera.driver = client;		break;	default:		ret = -ENODEV;	}	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);	return ret;}static int i2c_vino_client_unreg(struct i2c_client *client){	unsigned long flags;	int ret = 0;	spin_lock_irqsave(&vino_drvdata->input_lock, flags);	if (client == vino_drvdata->decoder.driver) {		if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL)			ret = -EBUSY;		else			vino_drvdata->decoder.driver = NULL;	} else if (client == vino_drvdata->camera.driver) {		if (vino_drvdata->camera.owner != VINO_NO_CHANNEL)			ret = -EBUSY;		else			vino_drvdata->camera.driver = NULL;	}	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);	return ret;}static struct i2c_adapter vino_i2c_adapter ={	.name			= "VINO I2C bus",	.id			= I2C_HW_SGI_VINO,	.algo_data		= &i2c_sgi_vino_data,	.client_register	= &i2c_vino_client_reg,	.client_unregister	= &i2c_vino_client_unreg,};static int vino_i2c_add_bus(void){	return i2c_sgi_add_bus(&vino_i2c_adapter);}static int vino_i2c_del_bus(void){	return i2c_sgi_del_bus(&vino_i2c_adapter);}static int i2c_camera_command(unsigned int cmd, void *arg){	return vino_drvdata->camera.driver->		driver->command(vino_drvdata->camera.driver,				cmd, arg);}static int i2c_decoder_command(unsigned int cmd, void *arg){	return vino_drvdata->decoder.driver->		driver->command(vino_drvdata->decoder.driver,				cmd, arg);}/* VINO framebuffer/DMA descriptor management */static void vino_free_buffer_with_count(struct vino_framebuffer *fb,					       unsigned int count){	unsigned int i;	dprintk("vino_free_buffer_with_count(): count = %d\n", count);	for (i = 0; i < count; i++) {		ClearPageReserved(virt_to_page(fb->desc_table.virtual[i]));		dma_unmap_single(NULL,				 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],				 PAGE_SIZE, DMA_FROM_DEVICE);		free_page(fb->desc_table.virtual[i]);	}	dma_free_coherent(NULL,			  VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *			  sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,			  fb->desc_table.dma);	kfree(fb->desc_table.virtual);	memset(fb, 0, sizeof(struct vino_framebuffer));}static void vino_free_buffer(struct vino_framebuffer *fb){	vino_free_buffer_with_count(fb, fb->desc_table.page_count);}static int vino_allocate_buffer(struct vino_framebuffer *fb,				unsigned int size){	unsigned int count, i, j;	int ret = 0;	dprintk("vino_allocate_buffer():\n");	if (size < 1)		return -EINVAL;	memset(fb, 0, sizeof(struct vino_framebuffer));	count = ((size / PAGE_SIZE) + 4) & ~3;	dprintk("vino_allocate_buffer(): size = %d, count = %d\n",		size, count);	/* allocate memory for table with virtual (page) addresses */	fb->desc_table.virtual = (unsigned long *)		kmalloc(count * sizeof(unsigned long), GFP_KERNEL);	if (!fb->desc_table.virtual)		return -ENOMEM;	/* allocate memory for table with dma addresses	 * (has space for four extra descriptors) */	fb->desc_table.dma_cpu =		dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *				   sizeof(dma_addr_t), &fb->desc_table.dma,				   GFP_KERNEL | GFP_DMA);	if (!fb->desc_table.dma_cpu) {		ret = -ENOMEM;		goto out_free_virtual;	}	/* allocate pages for the buffer and acquire the according	 * dma addresses */	for (i = 0; i < count; i++) {		dma_addr_t dma_data_addr;		fb->desc_table.virtual[i] =			get_zeroed_page(GFP_KERNEL | GFP_DMA);		if (!fb->desc_table.virtual[i]) {			ret = -ENOBUFS;			break;		}		dma_data_addr =			dma_map_single(NULL,				       (void *)fb->desc_table.virtual[i],				       PAGE_SIZE, DMA_FROM_DEVICE);		for (j = 0; j < VINO_PAGE_RATIO; j++) {			fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =				dma_data_addr + VINO_PAGE_SIZE * j;		}		SetPageReserved(virt_to_page(fb->desc_table.virtual[i]));	}	/* page_count needs to be set anyway, because the descriptor table has	 * been allocated according to this number */	fb->desc_table.page_count = count;	if (ret) {		/* the descriptor with index i doesn't contain		 * a valid address yet */		vino_free_buffer_with_count(fb, i);		return ret;	}	//fb->size = size;	fb->size = count * PAGE_SIZE;	fb->data_format = VINO_DATA_FMT_NONE;	/* set the dma stop-bit for the last (count+1)th descriptor */	fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;	return 0; out_free_virtual:	kfree(fb->desc_table.virtual);	return ret;}#if 0 /* keep */;/* user buffers not fully implemented yet */static int vino_prepare_user_buffer(struct vino_framebuffer *fb,				     void *user,				     unsigned int size){	unsigned int count, i, j;	int ret = 0;	dprintk("vino_prepare_user_buffer():\n");	if (size < 1)		return -EINVAL;	memset(fb, 0, sizeof(struct vino_framebuffer));	count = ((size / PAGE_SIZE)) & ~3;	dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",		size, count);	/* allocate memory for table with virtual (page) addresses */	fb->desc_table.virtual = (unsigned long *)		kmalloc(count * sizeof(unsigned long), GFP_KERNEL);	if (!fb->desc_table.virtual)		return -ENOMEM;	/* allocate memory for table with dma addresses	 * (has space for four extra descriptors) */	fb->desc_table.dma_cpu =		dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *				   sizeof(dma_addr_t), &fb->desc_table.dma,				   GFP_KERNEL | GFP_DMA);	if (!fb->desc_table.dma_cpu) {		ret = -ENOMEM;		goto out_free_virtual;	}	/* allocate pages for the buffer and acquire the according	 * dma addresses */	for (i = 0; i < count; i++) {		dma_addr_t dma_data_addr;		fb->desc_table.virtual[i] =			get_zeroed_page(GFP_KERNEL | GFP_DMA);		if (!fb->desc_table.virtual[i]) {			ret = -ENOBUFS;			break;		}		dma_data_addr =			dma_map_single(NULL,				       (void *)fb->desc_table.virtual[i],				       PAGE_SIZE, DMA_FROM_DEVICE);		for (j = 0; j < VINO_PAGE_RATIO; j++) {			fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =				dma_data_addr + VINO_PAGE_SIZE * j;		}		SetPageReserved(virt_to_page(fb->desc_table.virtual[i]));	}	/* page_count needs to be set anyway, because the descriptor table has	 * been allocated according to this number */	fb->desc_table.page_count = count;	if (ret) {		/* the descriptor with index i doesn't contain		 * a valid address yet */		vino_free_buffer_with_count(fb, i);		return ret;	}	//fb->size = size;	fb->size = count * PAGE_SIZE;	/* set the dma stop-bit for the last (count+1)th descriptor */	fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;	return 0; out_free_virtual:	kfree(fb->desc_table.virtual);	return ret;}#endifstatic void vino_sync_buffer(struct vino_framebuffer *fb){	int i;	dprintk("vino_sync_buffer():\n");	for (i = 0; i < fb->desc_table.page_count; i++)		dma_sync_single(NULL,				fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],				PAGE_SIZE, DMA_FROM_DEVICE);}/* Framebuffer fifo functions (need to be locked externally) */static inline void vino_fifo_init(struct vino_framebuffer_fifo *f,			   unsigned int length){	f->length = 0;	f->used = 0;	f->head = 0;	f->tail = 0;	if (length > VINO_FRAMEBUFFER_COUNT_MAX)		length = VINO_FRAMEBUFFER_COUNT_MAX;	f->length = length;}/* returns true/false */static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f,				   unsigned int id){	unsigned int i;	for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {		if (f->data[i] == id)			return 1;	}	return 0;}#if 0 /* keep */;/* returns true/false */static inline int vino_fifo_full(struct vino_framebuffer_fifo *f){	return (f->used == f->length);}#endifstatic inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f){	return f->used;}static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id){	if (id >= f->length) {		return VINO_QUEUE_ERROR;	}	if (vino_fifo_has_id(f, id)) {		return VINO_QUEUE_ERROR;	}	if (f->used < f->length) {		f->data[f->tail] = id;		f->tail = (f->tail + 1) % f->length;		f->used++;	} else {		return VINO_QUEUE_ERROR;	}	return 0;}static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id){	if (f->used > 0) {		*id = f->data[f->head];	} else {		return VINO_QUEUE_ERROR;	}	return 0;}static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id){	if (f->used > 0) {		*id = f->data[f->head];		f->head = (f->head + 1) % f->length;		f->used--;	} else {		return VINO_QUEUE_ERROR;	}	return 0;}/* Framebuffer queue functions *//* execute with queue_lock locked */static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,				       unsigned int length){	unsigned int i;	q->length = 0;	memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));	memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));	for (i = 0; i < length; i++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -