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

📄 vivi.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Updates stream time */	dev->ms += jiffies_to_msecs(jiffies-dev->jiffies);	dev->jiffies = jiffies;	if (dev->ms >= 1000) {		dev->ms -= 1000;		dev->s++;		if (dev->s >= 60) {			dev->s -= 60;			dev->m++;			if (dev->m > 60) {				dev->m -= 60;				dev->h++;				if (dev->h > 24)					dev->h -= 24;			}		}	}	sprintf(dev->timestr, "%02d:%02d:%02d:%03d",			dev->h, dev->m, dev->s, dev->ms);	dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n",			dev->timestr, (unsigned long)tmpbuf, pos);	/* Advice that buffer was filled */	buf->vb.field_count++;	do_gettimeofday(&ts);	buf->vb.ts = ts;	buf->vb.state = VIDEOBUF_DONE;}static void vivi_thread_tick(struct vivi_fh *fh){	struct vivi_buffer *buf;	struct vivi_dev *dev = fh->dev;	struct vivi_dmaqueue *dma_q = &dev->vidq;	unsigned long flags = 0;	dprintk(dev, 1, "Thread tick\n");	spin_lock_irqsave(&dev->slock, flags);	if (list_empty(&dma_q->active)) {		dprintk(dev, 1, "No active queue to serve\n");		goto unlock;	}	buf = list_entry(dma_q->active.next,			 struct vivi_buffer, vb.queue);	/* Nobody is waiting on this buffer, return */	if (!waitqueue_active(&buf->vb.done))		goto unlock;	list_del(&buf->vb.queue);	do_gettimeofday(&buf->vb.ts);	/* Fill buffer */	vivi_fillbuff(fh, buf);	dprintk(dev, 1, "filled buffer %p\n", buf);	wake_up(&buf->vb.done);	dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);unlock:	spin_unlock_irqrestore(&dev->slock, flags);	return;}#define frames_to_ms(frames)					\	((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)static void vivi_sleep(struct vivi_fh *fh){	struct vivi_dev *dev = fh->dev;	struct vivi_dmaqueue *dma_q = &dev->vidq;	int timeout;	DECLARE_WAITQUEUE(wait, current);	dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,		(unsigned long)dma_q);	add_wait_queue(&dma_q->wq, &wait);	if (kthread_should_stop())		goto stop_task;	/* Calculate time to wake up */	timeout = msecs_to_jiffies(frames_to_ms(1));	vivi_thread_tick(fh);	schedule_timeout_interruptible(timeout);stop_task:	remove_wait_queue(&dma_q->wq, &wait);	try_to_freeze();}static int vivi_thread(void *data){	struct vivi_fh  *fh = data;	struct vivi_dev *dev = fh->dev;	dprintk(dev, 1, "thread started\n");	set_freezable();	for (;;) {		vivi_sleep(fh);		if (kthread_should_stop())			break;	}	dprintk(dev, 1, "thread: exit\n");	return 0;}static int vivi_start_thread(struct vivi_fh *fh){	struct vivi_dev *dev = fh->dev;	struct vivi_dmaqueue *dma_q = &dev->vidq;	dma_q->frame = 0;	dma_q->ini_jiffies = jiffies;	dprintk(dev, 1, "%s\n", __func__);	dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");	if (IS_ERR(dma_q->kthread)) {		printk(KERN_ERR "vivi: kernel_thread() failed\n");		return PTR_ERR(dma_q->kthread);	}	/* Wakes thread */	wake_up_interruptible(&dma_q->wq);	dprintk(dev, 1, "returning from %s\n", __func__);	return 0;}static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q){	struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);	dprintk(dev, 1, "%s\n", __func__);	/* shutdown control thread */	if (dma_q->kthread) {		kthread_stop(dma_q->kthread);		dma_q->kthread = NULL;	}}/* ------------------------------------------------------------------	Videobuf operations   ------------------------------------------------------------------*/static intbuffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size){	struct vivi_fh  *fh = vq->priv_data;	struct vivi_dev *dev  = fh->dev;	*size = fh->width*fh->height*2;	if (0 == *count)		*count = 32;	while (*size * *count > vid_limit * 1024 * 1024)		(*count)--;	dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,		*count, *size);	return 0;}static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf){	struct vivi_fh  *fh = vq->priv_data;	struct vivi_dev *dev  = fh->dev;	dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);	if (in_interrupt())		BUG();	videobuf_vmalloc_free(&buf->vb);	dprintk(dev, 1, "free_buffer: freed\n");	buf->vb.state = VIDEOBUF_NEEDS_INIT;}#define norm_maxw() 1024#define norm_maxh() 768static intbuffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,						enum v4l2_field field){	struct vivi_fh     *fh  = vq->priv_data;	struct vivi_dev    *dev = fh->dev;	struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);	int rc;	dprintk(dev, 1, "%s, field=%d\n", __func__, field);	BUG_ON(NULL == fh->fmt);	if (fh->width  < 48 || fh->width  > norm_maxw() ||	    fh->height < 32 || fh->height > norm_maxh())		return -EINVAL;	buf->vb.size = fh->width*fh->height*2;	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)		return -EINVAL;	/* These properties only change when queue is idle, see s_fmt */	buf->fmt       = fh->fmt;	buf->vb.width  = fh->width;	buf->vb.height = fh->height;	buf->vb.field  = field;	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {		rc = videobuf_iolock(vq, &buf->vb, NULL);		if (rc < 0)			goto fail;	}	buf->vb.state = VIDEOBUF_PREPARED;	return 0;fail:	free_buffer(vq, buf);	return rc;}static voidbuffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb){	struct vivi_buffer    *buf  = container_of(vb, struct vivi_buffer, vb);	struct vivi_fh        *fh   = vq->priv_data;	struct vivi_dev       *dev  = fh->dev;	struct vivi_dmaqueue *vidq = &dev->vidq;	dprintk(dev, 1, "%s\n", __func__);	buf->vb.state = VIDEOBUF_QUEUED;	list_add_tail(&buf->vb.queue, &vidq->active);}static void buffer_release(struct videobuf_queue *vq,			   struct videobuf_buffer *vb){	struct vivi_buffer   *buf  = container_of(vb, struct vivi_buffer, vb);	struct vivi_fh       *fh   = vq->priv_data;	struct vivi_dev      *dev  = (struct vivi_dev *)fh->dev;	dprintk(dev, 1, "%s\n", __func__);	free_buffer(vq, buf);}static struct videobuf_queue_ops vivi_video_qops = {	.buf_setup      = buffer_setup,	.buf_prepare    = buffer_prepare,	.buf_queue      = buffer_queue,	.buf_release    = buffer_release,};/* ------------------------------------------------------------------	IOCTL vidioc handling   ------------------------------------------------------------------*/static int vidioc_querycap(struct file *file, void  *priv,					struct v4l2_capability *cap){	strcpy(cap->driver, "vivi");	strcpy(cap->card, "vivi");	cap->version = VIVI_VERSION;	cap->capabilities =	V4L2_CAP_VIDEO_CAPTURE |				V4L2_CAP_STREAMING     |				V4L2_CAP_READWRITE;	return 0;}static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,					struct v4l2_fmtdesc *f){	struct vivi_fmt *fmt;	if (f->index >= ARRAY_SIZE(formats))		return -EINVAL;	fmt = &formats[f->index];	strlcpy(f->description, fmt->name, sizeof(f->description));	f->pixelformat = fmt->fourcc;	return 0;}static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,					struct v4l2_format *f){	struct vivi_fh *fh = priv;	f->fmt.pix.width        = fh->width;	f->fmt.pix.height       = fh->height;	f->fmt.pix.field        = fh->vb_vidq.field;	f->fmt.pix.pixelformat  = fh->fmt->fourcc;	f->fmt.pix.bytesperline =		(f->fmt.pix.width * fh->fmt->depth) >> 3;	f->fmt.pix.sizeimage =		f->fmt.pix.height * f->fmt.pix.bytesperline;	return (0);}static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,			struct v4l2_format *f){	struct vivi_fh  *fh  = priv;	struct vivi_dev *dev = fh->dev;	struct vivi_fmt *fmt;	enum v4l2_field field;	unsigned int maxw, maxh;	fmt = get_format(f);	if (!fmt) {		dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",			f->fmt.pix.pixelformat);		return -EINVAL;	}	field = f->fmt.pix.field;	if (field == V4L2_FIELD_ANY) {		field = V4L2_FIELD_INTERLACED;	} else if (V4L2_FIELD_INTERLACED != field) {		dprintk(dev, 1, "Field type invalid.\n");		return -EINVAL;	}	maxw  = norm_maxw();	maxh  = norm_maxh();	f->fmt.pix.field = field;	if (f->fmt.pix.height < 32)		f->fmt.pix.height = 32;	if (f->fmt.pix.height > maxh)		f->fmt.pix.height = maxh;	if (f->fmt.pix.width < 48)		f->fmt.pix.width = 48;	if (f->fmt.pix.width > maxw)		f->fmt.pix.width = maxw;	f->fmt.pix.width &= ~0x03;	f->fmt.pix.bytesperline =		(f->fmt.pix.width * fmt->depth) >> 3;	f->fmt.pix.sizeimage =		f->fmt.pix.height * f->fmt.pix.bytesperline;	return 0;}/*FIXME: This seems to be generic enough to be at videodev2 */static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,					struct v4l2_format *f){	struct vivi_fh  *fh = priv;	struct videobuf_queue *q = &fh->vb_vidq;	unsigned char r, g, b;	int k, is_yuv;	int ret = vidioc_try_fmt_vid_cap(file, fh, f);	if (ret < 0)		return (ret);	mutex_lock(&q->vb_lock);	if (videobuf_queue_is_busy(&fh->vb_vidq)) {		dprintk(fh->dev, 1, "%s queue busy\n", __func__);		ret = -EBUSY;		goto out;	}	fh->fmt           = get_format(f);	fh->width         = f->fmt.pix.width;	fh->height        = f->fmt.pix.height;	fh->vb_vidq.field = f->fmt.pix.field;	fh->type          = f->type;	/* precalculate color bar values to speed up rendering */	for (k = 0; k < 8; k++) {		r = bars[k][0];		g = bars[k][1];		b = bars[k][2];		is_yuv = 0;		switch (fh->fmt->fourcc) {		case V4L2_PIX_FMT_YUYV:		case V4L2_PIX_FMT_UYVY:			is_yuv = 1;			break;		case V4L2_PIX_FMT_RGB565:		case V4L2_PIX_FMT_RGB565X:			r >>= 3;			g >>= 2;			b >>= 3;			break;		case V4L2_PIX_FMT_RGB555:		case V4L2_PIX_FMT_RGB555X:			r >>= 3;			g >>= 3;			b >>= 3;			break;		}		if (is_yuv) {			fh->bars[k][0] = TO_Y(r, g, b);	/* Luma */			fh->bars[k][1] = TO_U(r, g, b);	/* Cb */			fh->bars[k][2] = TO_V(r, g, b);	/* Cr */		} else {			fh->bars[k][0] = r;			fh->bars[k][1] = g;			fh->bars[k][2] = b;		}	}	ret = 0;out:	mutex_unlock(&q->vb_lock);	return (ret);}static int vidioc_reqbufs(struct file *file, void *priv,			  struct v4l2_requestbuffers *p){	struct vivi_fh  *fh = priv;	return (videobuf_reqbufs(&fh->vb_vidq, p));}static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p){	struct vivi_fh  *fh = priv;	return (videobuf_querybuf(&fh->vb_vidq, p));}static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p){	struct vivi_fh *fh = priv;	return (videobuf_qbuf(&fh->vb_vidq, p));}

⌨️ 快捷键说明

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