1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | au0828-vbi.c - VBI driver for au0828 |
4 | |
5 | Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> |
6 | |
7 | This work was sponsored by GetWellNetwork Inc. |
8 | |
9 | */ |
10 | |
11 | #include "au0828.h" |
12 | |
13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> |
15 | #include <linux/init.h> |
16 | #include <linux/slab.h> |
17 | #include <media/v4l2-mc.h> |
18 | |
19 | /* ------------------------------------------------------------------ */ |
20 | |
21 | static int vbi_queue_setup(struct vb2_queue *vq, |
22 | unsigned int *nbuffers, unsigned int *nplanes, |
23 | unsigned int sizes[], struct device *alloc_devs[]) |
24 | { |
25 | struct au0828_dev *dev = vb2_get_drv_priv(q: vq); |
26 | unsigned long size = dev->vbi_width * dev->vbi_height * 2; |
27 | |
28 | if (*nplanes) |
29 | return sizes[0] < size ? -EINVAL : 0; |
30 | *nplanes = 1; |
31 | sizes[0] = size; |
32 | return 0; |
33 | } |
34 | |
35 | static int vbi_buffer_prepare(struct vb2_buffer *vb) |
36 | { |
37 | struct au0828_dev *dev = vb2_get_drv_priv(q: vb->vb2_queue); |
38 | unsigned long size; |
39 | |
40 | size = dev->vbi_width * dev->vbi_height * 2; |
41 | |
42 | if (vb2_plane_size(vb, plane_no: 0) < size) { |
43 | pr_err("%s data will not fit into plane (%lu < %lu)\n" , |
44 | __func__, vb2_plane_size(vb, 0), size); |
45 | return -EINVAL; |
46 | } |
47 | vb2_set_plane_payload(vb, plane_no: 0, size); |
48 | |
49 | return 0; |
50 | } |
51 | |
52 | static void |
53 | vbi_buffer_queue(struct vb2_buffer *vb) |
54 | { |
55 | struct au0828_dev *dev = vb2_get_drv_priv(q: vb->vb2_queue); |
56 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
57 | struct au0828_buffer *buf = |
58 | container_of(vbuf, struct au0828_buffer, vb); |
59 | struct au0828_dmaqueue *vbiq = &dev->vbiq; |
60 | unsigned long flags = 0; |
61 | |
62 | buf->mem = vb2_plane_vaddr(vb, plane_no: 0); |
63 | buf->length = vb2_plane_size(vb, plane_no: 0); |
64 | |
65 | spin_lock_irqsave(&dev->slock, flags); |
66 | list_add_tail(new: &buf->list, head: &vbiq->active); |
67 | spin_unlock_irqrestore(lock: &dev->slock, flags); |
68 | } |
69 | |
70 | const struct vb2_ops au0828_vbi_qops = { |
71 | .queue_setup = vbi_queue_setup, |
72 | .buf_prepare = vbi_buffer_prepare, |
73 | .buf_queue = vbi_buffer_queue, |
74 | .prepare_streaming = v4l_vb2q_enable_media_source, |
75 | .start_streaming = au0828_start_analog_streaming, |
76 | .stop_streaming = au0828_stop_vbi_streaming, |
77 | .wait_prepare = vb2_ops_wait_prepare, |
78 | .wait_finish = vb2_ops_wait_finish, |
79 | }; |
80 | |