1 // SPDX-License-Identifier: GPL-2.0-only
3 * vivid-vbi-out.c - vbi output support functions.
5 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/videodev2.h>
11 #include <media/v4l2-common.h>
13 #include "vivid-core.h"
14 #include "vivid-kthread-out.h"
15 #include "vivid-vbi-out.h"
16 #include "vivid-vbi-cap.h"
18 static int vbi_out_queue_setup(struct vb2_queue
*vq
,
19 unsigned *nbuffers
, unsigned *nplanes
,
20 unsigned sizes
[], struct device
*alloc_devs
[])
22 struct vivid_dev
*dev
= vb2_get_drv_priv(vq
);
23 bool is_60hz
= dev
->std_out
& V4L2_STD_525_60
;
24 unsigned size
= vq
->type
== V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
?
25 36 * sizeof(struct v4l2_sliced_vbi_data
) :
26 1440 * 2 * (is_60hz
? 12 : 18);
28 if (!vivid_is_svid_out(dev
))
33 if (vq
->num_buffers
+ *nbuffers
< 2)
34 *nbuffers
= 2 - vq
->num_buffers
;
40 static int vbi_out_buf_prepare(struct vb2_buffer
*vb
)
42 struct vivid_dev
*dev
= vb2_get_drv_priv(vb
->vb2_queue
);
43 bool is_60hz
= dev
->std_out
& V4L2_STD_525_60
;
44 unsigned size
= vb
->vb2_queue
->type
== V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
?
45 36 * sizeof(struct v4l2_sliced_vbi_data
) :
46 1440 * 2 * (is_60hz
? 12 : 18);
48 dprintk(dev
, 1, "%s\n", __func__
);
50 if (dev
->buf_prepare_error
) {
52 * Error injection: test what happens if buf_prepare() returns
55 dev
->buf_prepare_error
= false;
58 if (vb2_plane_size(vb
, 0) < size
) {
59 dprintk(dev
, 1, "%s data will not fit into plane (%lu < %u)\n",
60 __func__
, vb2_plane_size(vb
, 0), size
);
63 vb2_set_plane_payload(vb
, 0, size
);
68 static void vbi_out_buf_queue(struct vb2_buffer
*vb
)
70 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
71 struct vivid_dev
*dev
= vb2_get_drv_priv(vb
->vb2_queue
);
72 struct vivid_buffer
*buf
= container_of(vbuf
, struct vivid_buffer
, vb
);
74 dprintk(dev
, 1, "%s\n", __func__
);
76 spin_lock(&dev
->slock
);
77 list_add_tail(&buf
->list
, &dev
->vbi_out_active
);
78 spin_unlock(&dev
->slock
);
81 static int vbi_out_start_streaming(struct vb2_queue
*vq
, unsigned count
)
83 struct vivid_dev
*dev
= vb2_get_drv_priv(vq
);
86 dprintk(dev
, 1, "%s\n", __func__
);
87 dev
->vbi_out_seq_count
= 0;
88 if (dev
->start_streaming_error
) {
89 dev
->start_streaming_error
= false;
92 err
= vivid_start_generating_vid_out(dev
, &dev
->vbi_out_streaming
);
95 struct vivid_buffer
*buf
, *tmp
;
97 list_for_each_entry_safe(buf
, tmp
, &dev
->vbi_out_active
, list
) {
99 vb2_buffer_done(&buf
->vb
.vb2_buf
,
100 VB2_BUF_STATE_QUEUED
);
106 /* abort streaming and wait for last buffer */
107 static void vbi_out_stop_streaming(struct vb2_queue
*vq
)
109 struct vivid_dev
*dev
= vb2_get_drv_priv(vq
);
111 dprintk(dev
, 1, "%s\n", __func__
);
112 vivid_stop_generating_vid_out(dev
, &dev
->vbi_out_streaming
);
113 dev
->vbi_out_have_wss
= false;
114 dev
->vbi_out_have_cc
[0] = false;
115 dev
->vbi_out_have_cc
[1] = false;
118 const struct vb2_ops vivid_vbi_out_qops
= {
119 .queue_setup
= vbi_out_queue_setup
,
120 .buf_prepare
= vbi_out_buf_prepare
,
121 .buf_queue
= vbi_out_buf_queue
,
122 .start_streaming
= vbi_out_start_streaming
,
123 .stop_streaming
= vbi_out_stop_streaming
,
124 .wait_prepare
= vb2_ops_wait_prepare
,
125 .wait_finish
= vb2_ops_wait_finish
,
128 int vidioc_g_fmt_vbi_out(struct file
*file
, void *priv
,
129 struct v4l2_format
*f
)
131 struct vivid_dev
*dev
= video_drvdata(file
);
132 struct v4l2_vbi_format
*vbi
= &f
->fmt
.vbi
;
133 bool is_60hz
= dev
->std_out
& V4L2_STD_525_60
;
135 if (!vivid_is_svid_out(dev
) || !dev
->has_raw_vbi_out
)
138 vbi
->sampling_rate
= 25000000;
140 vbi
->samples_per_line
= 1440;
141 vbi
->sample_format
= V4L2_PIX_FMT_GREY
;
142 vbi
->start
[0] = is_60hz
? V4L2_VBI_ITU_525_F1_START
+ 9 : V4L2_VBI_ITU_625_F1_START
+ 5;
143 vbi
->start
[1] = is_60hz
? V4L2_VBI_ITU_525_F2_START
+ 9 : V4L2_VBI_ITU_625_F2_START
+ 5;
144 vbi
->count
[0] = vbi
->count
[1] = is_60hz
? 12 : 18;
145 vbi
->flags
= dev
->vbi_cap_interlaced
? V4L2_VBI_INTERLACED
: 0;
146 vbi
->reserved
[0] = 0;
147 vbi
->reserved
[1] = 0;
151 int vidioc_s_fmt_vbi_out(struct file
*file
, void *priv
,
152 struct v4l2_format
*f
)
154 struct vivid_dev
*dev
= video_drvdata(file
);
155 int ret
= vidioc_g_fmt_vbi_out(file
, priv
, f
);
159 if (vb2_is_busy(&dev
->vb_vbi_out_q
))
161 dev
->stream_sliced_vbi_out
= false;
162 dev
->vbi_out_dev
.queue
->type
= V4L2_BUF_TYPE_VBI_OUTPUT
;
166 int vidioc_g_fmt_sliced_vbi_out(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
168 struct vivid_dev
*dev
= video_drvdata(file
);
169 struct v4l2_sliced_vbi_format
*vbi
= &fmt
->fmt
.sliced
;
171 if (!vivid_is_svid_out(dev
) || !dev
->has_sliced_vbi_out
)
174 vivid_fill_service_lines(vbi
, dev
->service_set_out
);
178 int vidioc_try_fmt_sliced_vbi_out(struct file
*file
, void *fh
, struct v4l2_format
*fmt
)
180 struct vivid_dev
*dev
= video_drvdata(file
);
181 struct v4l2_sliced_vbi_format
*vbi
= &fmt
->fmt
.sliced
;
182 bool is_60hz
= dev
->std_out
& V4L2_STD_525_60
;
183 u32 service_set
= vbi
->service_set
;
185 if (!vivid_is_svid_out(dev
) || !dev
->has_sliced_vbi_out
)
188 service_set
&= is_60hz
? V4L2_SLICED_CAPTION_525
:
189 V4L2_SLICED_WSS_625
| V4L2_SLICED_TELETEXT_B
;
190 vivid_fill_service_lines(vbi
, service_set
);
194 int vidioc_s_fmt_sliced_vbi_out(struct file
*file
, void *fh
,
195 struct v4l2_format
*fmt
)
197 struct vivid_dev
*dev
= video_drvdata(file
);
198 struct v4l2_sliced_vbi_format
*vbi
= &fmt
->fmt
.sliced
;
199 int ret
= vidioc_try_fmt_sliced_vbi_out(file
, fh
, fmt
);
203 if (vb2_is_busy(&dev
->vb_vbi_out_q
))
205 dev
->service_set_out
= vbi
->service_set
;
206 dev
->stream_sliced_vbi_out
= true;
207 dev
->vbi_out_dev
.queue
->type
= V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
;
211 void vivid_sliced_vbi_out_process(struct vivid_dev
*dev
,
212 struct vivid_buffer
*buf
)
214 struct v4l2_sliced_vbi_data
*vbi
=
215 vb2_plane_vaddr(&buf
->vb
.vb2_buf
, 0);
217 vb2_get_plane_payload(&buf
->vb
.vb2_buf
, 0) / sizeof(*vbi
);
219 dev
->vbi_out_have_cc
[0] = false;
220 dev
->vbi_out_have_cc
[1] = false;
221 dev
->vbi_out_have_wss
= false;
224 case V4L2_SLICED_CAPTION_525
:
225 if ((dev
->std_out
& V4L2_STD_525_60
) && vbi
->line
== 21) {
226 dev
->vbi_out_have_cc
[!!vbi
->field
] = true;
227 dev
->vbi_out_cc
[!!vbi
->field
][0] = vbi
->data
[0];
228 dev
->vbi_out_cc
[!!vbi
->field
][1] = vbi
->data
[1];
231 case V4L2_SLICED_WSS_625
:
232 if ((dev
->std_out
& V4L2_STD_625_50
) &&
233 vbi
->field
== 0 && vbi
->line
== 23) {
234 dev
->vbi_out_have_wss
= true;
235 dev
->vbi_out_wss
[0] = vbi
->data
[0];
236 dev
->vbi_out_wss
[1] = vbi
->data
[1];