Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/au0828/au0828-vbi.c
17988 views
1
/*
2
au0828-vbi.c - VBI driver for au0828
3
4
Copyright (C) 2010 Devin Heitmueller <[email protected]>
5
6
This work was sponsored by GetWellNetwork Inc.
7
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
17
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
02110-1301, USA.
22
*/
23
24
#include <linux/kernel.h>
25
#include <linux/module.h>
26
#include <linux/init.h>
27
#include <linux/slab.h>
28
29
#include "au0828.h"
30
31
static unsigned int vbibufs = 5;
32
module_param(vbibufs, int, 0644);
33
MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");
34
35
/* ------------------------------------------------------------------ */
36
37
static void
38
free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
39
{
40
struct au0828_fh *fh = vq->priv_data;
41
struct au0828_dev *dev = fh->dev;
42
unsigned long flags = 0;
43
if (in_interrupt())
44
BUG();
45
46
/* We used to wait for the buffer to finish here, but this didn't work
47
because, as we were keeping the state as VIDEOBUF_QUEUED,
48
videobuf_queue_cancel marked it as finished for us.
49
(Also, it could wedge forever if the hardware was misconfigured.)
50
51
This should be safe; by the time we get here, the buffer isn't
52
queued anymore. If we ever start marking the buffers as
53
VIDEOBUF_ACTIVE, it won't be, though.
54
*/
55
spin_lock_irqsave(&dev->slock, flags);
56
if (dev->isoc_ctl.vbi_buf == buf)
57
dev->isoc_ctl.vbi_buf = NULL;
58
spin_unlock_irqrestore(&dev->slock, flags);
59
60
videobuf_vmalloc_free(&buf->vb);
61
buf->vb.state = VIDEOBUF_NEEDS_INIT;
62
}
63
64
static int
65
vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
66
{
67
struct au0828_fh *fh = q->priv_data;
68
struct au0828_dev *dev = fh->dev;
69
70
*size = dev->vbi_width * dev->vbi_height * 2;
71
72
if (0 == *count)
73
*count = vbibufs;
74
if (*count < 2)
75
*count = 2;
76
if (*count > 32)
77
*count = 32;
78
return 0;
79
}
80
81
static int
82
vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
83
enum v4l2_field field)
84
{
85
struct au0828_fh *fh = q->priv_data;
86
struct au0828_dev *dev = fh->dev;
87
struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
88
int rc = 0;
89
90
buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
91
92
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
93
return -EINVAL;
94
95
buf->vb.width = dev->vbi_width;
96
buf->vb.height = dev->vbi_height;
97
buf->vb.field = field;
98
99
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
100
rc = videobuf_iolock(q, &buf->vb, NULL);
101
if (rc < 0)
102
goto fail;
103
}
104
105
buf->vb.state = VIDEOBUF_PREPARED;
106
return 0;
107
108
fail:
109
free_buffer(q, buf);
110
return rc;
111
}
112
113
static void
114
vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
115
{
116
struct au0828_buffer *buf = container_of(vb,
117
struct au0828_buffer,
118
vb);
119
struct au0828_fh *fh = vq->priv_data;
120
struct au0828_dev *dev = fh->dev;
121
struct au0828_dmaqueue *vbiq = &dev->vbiq;
122
123
buf->vb.state = VIDEOBUF_QUEUED;
124
list_add_tail(&buf->vb.queue, &vbiq->active);
125
}
126
127
static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
128
{
129
struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
130
free_buffer(q, buf);
131
}
132
133
struct videobuf_queue_ops au0828_vbi_qops = {
134
.buf_setup = vbi_setup,
135
.buf_prepare = vbi_prepare,
136
.buf_queue = vbi_queue,
137
.buf_release = vbi_release,
138
};
139
140