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

📄 vino.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 5 页
字号:
	case VINO_DATA_NORM_NTSC:	case VINO_DATA_NORM_D1:		fps = (unsigned int)(fps / 6) * 6; // FIXME: round!		if (fps < vino_data_norms[vcs->data_norm].fps_min)			fps = vino_data_norms[vcs->data_norm].fps_min;		if (fps > vino_data_norms[vcs->data_norm].fps_max)			fps = vino_data_norms[vcs->data_norm].fps_max;		switch (fps) {		case 6:			mask = 0x003;			break;		case 12:			mask = 0x0c3;			break;		case 18:			mask = 0x333;			break;		case 24:			mask = 0x3ff;			break;		case 30:			mask = 0xfff;			break;		default:			mask = VINO_FRAMERT_FULL;		}		vcs->framert_reg = VINO_FRAMERT_RT(mask);		break;	case VINO_DATA_NORM_PAL:	case VINO_DATA_NORM_SECAM:		fps = (unsigned int)(fps / 5) * 5; // FIXME: round!		if (fps < vino_data_norms[vcs->data_norm].fps_min)			fps = vino_data_norms[vcs->data_norm].fps_min;		if (fps > vino_data_norms[vcs->data_norm].fps_max)			fps = vino_data_norms[vcs->data_norm].fps_max;		switch (fps) {		case 5:			mask = 0x003;			break;		case 10:			mask = 0x0c3;			break;		case 15:			mask = 0x333;			break;		case 20:			mask = 0x0ff;			break;		case 25:			mask = 0x3ff;			break;		default:			mask = VINO_FRAMERT_FULL;		}		vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;		break;	}	vcs->fps = fps;}/* execute with input_lock locked */static inline void vino_set_default_framerate(struct					      vino_channel_settings *vcs){	vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);}/* * Prepare VINO for DMA transfer... * (execute only with vino_lock and input_lock locked) */static int vino_dma_setup(struct vino_channel_settings *vcs,			  struct vino_framebuffer *fb){	u32 ctrl, intr;	struct sgi_vino_channel *ch;	const struct vino_data_norm *norm;	dprintk("vino_dma_setup():\n");	vcs->field = 0;	fb->frame_counter = 0;	ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;	norm = &vino_data_norms[vcs->data_norm];	ch->page_index = 0;	ch->line_count = 0;	/* VINO line size register is set 8 bytes less than actual */	ch->line_size = vcs->line_size - 8;	/* let VINO know where to transfer data */	ch->start_desc_tbl = fb->desc_table.dma;	ch->next_4_desc = fb->desc_table.dma;	/* give vino time to fetch the first four descriptors, 5 usec	 * should be more than enough time */	udelay(VINO_DESC_FETCH_DELAY);	dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n",		ch->start_desc_tbl, ch->next_4_desc);	/* set the alpha register */	ch->alpha = vcs->alpha;	/* set clipping registers */	ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |		VINO_CLIP_EVEN(norm->even.top +			       vcs->clipping.top / 2) |		VINO_CLIP_X(vcs->clipping.left);	ch->clip_end = VINO_CLIP_ODD(norm->odd.top +				     vcs->clipping.bottom / 2 - 1) |		VINO_CLIP_EVEN(norm->even.top +			       vcs->clipping.bottom / 2 - 1) |		VINO_CLIP_X(vcs->clipping.right);	/* set the size of actual content in the buffer (DECIMATION !) */	fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /			 vcs->decimation) *		((vcs->clipping.bottom - vcs->clipping.top) /		 vcs->decimation) *		vino_data_formats[vcs->data_format].bpp;	ch->frame_rate = vcs->framert_reg;	ctrl = vino->control;	intr = vino->intr_status;	if (vcs->channel == VINO_CHANNEL_A) {		/* All interrupt conditions for this channel was cleared		 * so clear the interrupt status register and enable		 * interrupts */		intr &=	~VINO_INTSTAT_A;		ctrl |= VINO_CTRL_A_INT;		/* enable synchronization */		ctrl |= VINO_CTRL_A_SYNC_ENBL;		/* enable frame assembly */		ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;		/* set decimation used */		if (vcs->decimation < 2)			ctrl &= ~VINO_CTRL_A_DEC_ENBL;		else {			ctrl |= VINO_CTRL_A_DEC_ENBL;			ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;			ctrl |= (vcs->decimation - 1) <<				VINO_CTRL_A_DEC_SCALE_SHIFT;		}		/* select input interface */		if (vcs->input == VINO_INPUT_D1)			ctrl |= VINO_CTRL_A_SELECT;		else			ctrl &= ~VINO_CTRL_A_SELECT;		/* palette */		ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |			  VINO_CTRL_A_DITHER);	} else {		intr &= ~VINO_INTSTAT_B;		ctrl |= VINO_CTRL_B_INT;		ctrl |= VINO_CTRL_B_SYNC_ENBL;		ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;		if (vcs->decimation < 2)			ctrl &= ~VINO_CTRL_B_DEC_ENBL;		else {			ctrl |= VINO_CTRL_B_DEC_ENBL;			ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;			ctrl |= (vcs->decimation - 1) <<				VINO_CTRL_B_DEC_SCALE_SHIFT;		}		if (vcs->input == VINO_INPUT_D1)			ctrl |= VINO_CTRL_B_SELECT;		else			ctrl &= ~VINO_CTRL_B_SELECT;		ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |			  VINO_CTRL_B_DITHER);	}	/* set palette */	fb->data_format = vcs->data_format;	switch (vcs->data_format) {		case VINO_DATA_FMT_GREY:			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?				VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;			break;		case VINO_DATA_FMT_RGB32:			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?				VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;			break;		case VINO_DATA_FMT_YUV:			/* nothing needs to be done */			break;		case VINO_DATA_FMT_RGB332:			ctrl |= (vcs->channel == VINO_CHANNEL_A) ?				VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :				VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;			break;	}	vino->intr_status = intr;	vino->control = ctrl;	return 0;}/* (execute only with vino_lock locked) */static inline void vino_dma_start(struct vino_channel_settings *vcs){	u32 ctrl = vino->control;	dprintk("vino_dma_start():\n");	ctrl |= (vcs->channel == VINO_CHANNEL_A) ?		VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;	vino->control = ctrl;}/* (execute only with vino_lock locked) */static inline void vino_dma_stop(struct vino_channel_settings *vcs){	u32 ctrl = vino->control;	ctrl &= (vcs->channel == VINO_CHANNEL_A) ?		~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;	ctrl &= (vcs->channel == VINO_CHANNEL_A) ?		~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT;	vino->control = ctrl;	dprintk("vino_dma_stop():\n");}/* * Load dummy page to descriptor registers. This prevents generating of * spurious interrupts. (execute only with vino_lock locked) */static void vino_clear_interrupt(struct vino_channel_settings *vcs){	struct sgi_vino_channel *ch;	ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;	ch->page_index = 0;	ch->line_count = 0;	ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;	ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;	udelay(VINO_DESC_FETCH_DELAY);	dprintk("channel %c clear interrupt condition\n",	       (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');}static int vino_capture(struct vino_channel_settings *vcs,			struct vino_framebuffer *fb){	int err = 0;	unsigned long flags, flags2;	spin_lock_irqsave(&fb->state_lock, flags);	if (fb->state == VINO_FRAMEBUFFER_IN_USE)		err = -EBUSY;	fb->state = VINO_FRAMEBUFFER_IN_USE;	spin_unlock_irqrestore(&fb->state_lock, flags);	if (err)		return err;	spin_lock_irqsave(&vino_drvdata->vino_lock, flags);	spin_lock_irqsave(&vino_drvdata->input_lock, flags2);	vino_dma_setup(vcs, fb);	vino_dma_start(vcs);	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);	return err;}staticstruct vino_framebuffer *vino_capture_enqueue(struct					      vino_channel_settings *vcs,					      unsigned int index){	struct vino_framebuffer *fb;	unsigned long flags;	dprintk("vino_capture_enqueue():\n");	spin_lock_irqsave(&vcs->capture_lock, flags);	fb = vino_queue_add(&vcs->fb_queue, index);	if (fb == NULL) {		dprintk("vino_capture_enqueue(): vino_queue_add() failed, "			"queue full?\n");		goto out;	}out:	spin_unlock_irqrestore(&vcs->capture_lock, flags);	return fb;}static int vino_capture_next(struct vino_channel_settings *vcs, int start){	struct vino_framebuffer *fb;	unsigned int incoming, id;	int err = 0;	unsigned long flags;	dprintk("vino_capture_next():\n");	spin_lock_irqsave(&vcs->capture_lock, flags);	if (start) {		/* start capture only if capture isn't in progress already */		if (vcs->capturing) {			spin_unlock_irqrestore(&vcs->capture_lock, flags);			return 0;		}	} else {		/* capture next frame:		 * stop capture if capturing is not set */		if (!vcs->capturing) {			spin_unlock_irqrestore(&vcs->capture_lock, flags);			return 0;		}	}	err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);	if (err) {		dprintk("vino_capture_next(): vino_queue_get_incoming() "			"failed\n");		err = -EINVAL;		goto out;	}	if (incoming == 0) {		dprintk("vino_capture_next(): no buffers available\n");		goto out;	}	fb = vino_queue_peek(&vcs->fb_queue, &id);	if (fb == NULL) {		dprintk("vino_capture_next(): vino_queue_peek() failed\n");		err = -EINVAL;		goto out;	}	if (start) {		vcs->capturing = 1;	}	spin_unlock_irqrestore(&vcs->capture_lock, flags);	err = vino_capture(vcs, fb);	return err;out:	vcs->capturing = 0;	spin_unlock_irqrestore(&vcs->capture_lock, flags);	return err;}static inline int vino_is_capturing(struct vino_channel_settings *vcs){	int ret;	unsigned long flags;	spin_lock_irqsave(&vcs->capture_lock, flags);	ret = vcs->capturing;	spin_unlock_irqrestore(&vcs->capture_lock, flags);	return ret;}/* waits until a frame is captured */static int vino_wait_for_frame(struct vino_channel_settings *vcs){	wait_queue_t wait;	int err = 0;	dprintk("vino_wait_for_frame():\n");	init_waitqueue_entry(&wait, current);	/* add ourselves into wait queue */	add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);	/* and set current state */	set_current_state(TASK_INTERRUPTIBLE);	/* to ensure that schedule_timeout will return immediately	 * if VINO interrupt was triggred meanwhile */	schedule_timeout(HZ / 10);	if (signal_pending(current))		err = -EINTR;	remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);	dprintk("vino_wait_for_frame(): waiting for frame %s\n",		err ? "failed" : "ok");	return err;}/* the function assumes that PAGE_SIZE % 4 == 0 */static void vino_convert_to_rgba(struct vino_framebuffer *fb) {	unsigned char *pageptr;	unsigned int page, i;	unsigned char a;	for (page = 0; page < fb->desc_table.page_count; page++) {		pageptr = (unsigned char *)fb->desc_table.virtual[page];		for (i = 0; i < PAGE_SIZE; i += 4) {			a = pageptr[0];			pageptr[0] = pageptr[3];			pageptr[1] = pageptr[2];			pageptr[2] = pageptr[1];			pageptr[3] = a;			pageptr += 4;		}	}}/* checks if the buffer is in correct state and syncs data */static int vino_check_buffer(struct vino_channel_settings *vcs,			     struct vino_framebuffer *fb){	int err = 0;	unsigned long flags;	dprintk("vino_check_buffer():\n");	spin_lock_irqsave(&fb->state_lock, flags);	switch (fb->state) {	case VINO_FRAMEBUFFER_IN_USE:		err = -EIO;		break;	case VINO_FRAMEBUFFER_READY:		vino_sync_buffer(fb);		fb->state = VINO_FRAMEBUFFER_UNUSED;		break;	default:		err = -EINVAL;	}	spin_unlock_irqrestore(&fb->state_lock, flags);	if (!err) {		if (vino_pixel_conversion		    && (fb->data_format == VINO_DATA_FMT_RGB32)) {			vino_convert_to_rgba(fb);		}	} else if (err && (err != -EINVAL)) {		dprintk("vino_check_buffer(): buffer not ready\n");		spin_lock_irqsave(&vino_drvdata->vino_lock, flags);		vino_dma_stop(vcs);		vino_clear_interrupt(vcs);		spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);	}	return err;}/* forcefully terminates capture */static void vino_capture_stop(struct vino_channel_settings *vcs){	unsigned int incoming = 0, outgoing = 0, id;	unsigned long flags, flags2;	dprintk("vino_capture_stop():\n");	spin_lock_irqsave(&vcs->capture_lock, flags);	/* unset capturing to stop queue processing */	vcs->capturing = 0;	spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);	vino_dma_stop(vcs);	vino_clear_interrupt(vcs);	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);	/* remove all items from the queue */	if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {		dprintk("vino_capture_stop(): "			"vino_queue_get_incoming() failed\n");		goto out;	}	while (incoming > 0) {		vino_queue_transfer(&vcs->fb_queue);		if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {			dprintk("vino_capture_stop(): "				"vino_queue_get_incoming() failed\n");			goto out;		}	}	if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {		dprintk("vino_capture_stop(): "			"vino_queue_get_outgoing() failed\n");		goto out;	}	while (outgoing > 0) {		vino_queue_remove(&vcs->fb_queue, &id);		if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {			dprintk("vino_capture_stop(): "				"vino_queue_get_outgoing() failed\n");			goto out;		}	}out:	spin_unlock_irqrestore(&vcs->capture_lock, flags);}#if 0 /* keep */;static int vino_capture_failed(struct vino_channel_settings *vcs){	struct vino_framebuffer *fb;	unsigned long flags;	unsigned int i;	int ret;	dprintk("vino_capture_failed():\n");	spin_lock_irqsave(&vino_drvdata->vino_lock, flags);	vino_dma_stop(vcs);	vino_clear_interrupt(vcs);	spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);	ret = vino_queue_get_incoming(&vcs->fb_queue, &i);	if (ret == VINO_QUEUE_ERROR) {		dprintk("vino_queue_get_incoming() failed\n");		return -EINVAL;

⌨️ 快捷键说明

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