root/drivers/media/platform/vivid/vivid-vbi-cap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vivid_sliced_vbi_cap_fill
  2. vivid_g_fmt_vbi_cap
  3. vivid_raw_vbi_cap_process
  4. vivid_sliced_vbi_cap_process
  5. vbi_cap_queue_setup
  6. vbi_cap_buf_prepare
  7. vbi_cap_buf_queue
  8. vbi_cap_start_streaming
  9. vbi_cap_stop_streaming
  10. vbi_cap_buf_request_complete
  11. vidioc_g_fmt_vbi_cap
  12. vidioc_s_fmt_vbi_cap
  13. vivid_fill_service_lines
  14. vidioc_g_fmt_sliced_vbi_cap
  15. vidioc_try_fmt_sliced_vbi_cap
  16. vidioc_s_fmt_sliced_vbi_cap
  17. vidioc_g_sliced_vbi_cap

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * vivid-vbi-cap.c - vbi capture support functions.
   4  *
   5  * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
   6  */
   7 
   8 #include <linux/errno.h>
   9 #include <linux/kernel.h>
  10 #include <linux/videodev2.h>
  11 #include <media/v4l2-common.h>
  12 
  13 #include "vivid-core.h"
  14 #include "vivid-kthread-cap.h"
  15 #include "vivid-vbi-cap.h"
  16 #include "vivid-vbi-gen.h"
  17 
  18 static void vivid_sliced_vbi_cap_fill(struct vivid_dev *dev, unsigned seqnr)
  19 {
  20         struct vivid_vbi_gen_data *vbi_gen = &dev->vbi_gen;
  21         bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
  22 
  23         vivid_vbi_gen_sliced(vbi_gen, is_60hz, seqnr);
  24 
  25         if (!is_60hz) {
  26                 if (dev->loop_video) {
  27                         if (dev->vbi_out_have_wss) {
  28                                 vbi_gen->data[12].data[0] = dev->vbi_out_wss[0];
  29                                 vbi_gen->data[12].data[1] = dev->vbi_out_wss[1];
  30                         } else {
  31                                 vbi_gen->data[12].id = 0;
  32                         }
  33                 } else {
  34                         switch (tpg_g_video_aspect(&dev->tpg)) {
  35                         case TPG_VIDEO_ASPECT_14X9_CENTRE:
  36                                 vbi_gen->data[12].data[0] = 0x01;
  37                                 break;
  38                         case TPG_VIDEO_ASPECT_16X9_CENTRE:
  39                                 vbi_gen->data[12].data[0] = 0x0b;
  40                                 break;
  41                         case TPG_VIDEO_ASPECT_16X9_ANAMORPHIC:
  42                                 vbi_gen->data[12].data[0] = 0x07;
  43                                 break;
  44                         case TPG_VIDEO_ASPECT_4X3:
  45                         default:
  46                                 vbi_gen->data[12].data[0] = 0x08;
  47                                 break;
  48                         }
  49                 }
  50         } else if (dev->loop_video && is_60hz) {
  51                 if (dev->vbi_out_have_cc[0]) {
  52                         vbi_gen->data[0].data[0] = dev->vbi_out_cc[0][0];
  53                         vbi_gen->data[0].data[1] = dev->vbi_out_cc[0][1];
  54                 } else {
  55                         vbi_gen->data[0].id = 0;
  56                 }
  57                 if (dev->vbi_out_have_cc[1]) {
  58                         vbi_gen->data[1].data[0] = dev->vbi_out_cc[1][0];
  59                         vbi_gen->data[1].data[1] = dev->vbi_out_cc[1][1];
  60                 } else {
  61                         vbi_gen->data[1].id = 0;
  62                 }
  63         }
  64 }
  65 
  66 static void vivid_g_fmt_vbi_cap(struct vivid_dev *dev, struct v4l2_vbi_format *vbi)
  67 {
  68         bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
  69 
  70         vbi->sampling_rate = 27000000;
  71         vbi->offset = 24;
  72         vbi->samples_per_line = 1440;
  73         vbi->sample_format = V4L2_PIX_FMT_GREY;
  74         vbi->start[0] = is_60hz ? V4L2_VBI_ITU_525_F1_START + 9 : V4L2_VBI_ITU_625_F1_START + 5;
  75         vbi->start[1] = is_60hz ? V4L2_VBI_ITU_525_F2_START + 9 : V4L2_VBI_ITU_625_F2_START + 5;
  76         vbi->count[0] = vbi->count[1] = is_60hz ? 12 : 18;
  77         vbi->flags = dev->vbi_cap_interlaced ? V4L2_VBI_INTERLACED : 0;
  78         vbi->reserved[0] = 0;
  79         vbi->reserved[1] = 0;
  80 }
  81 
  82 void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
  83 {
  84         struct v4l2_vbi_format vbi;
  85         u8 *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
  86 
  87         vivid_g_fmt_vbi_cap(dev, &vbi);
  88         buf->vb.sequence = dev->vbi_cap_seq_count;
  89         if (dev->field_cap == V4L2_FIELD_ALTERNATE)
  90                 buf->vb.sequence /= 2;
  91 
  92         vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
  93 
  94         memset(vbuf, 0x10, vb2_plane_size(&buf->vb.vb2_buf, 0));
  95 
  96         if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input]))
  97                 vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
  98 }
  99 
 100 
 101 void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,
 102                         struct vivid_buffer *buf)
 103 {
 104         struct v4l2_sliced_vbi_data *vbuf =
 105                         vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 106 
 107         buf->vb.sequence = dev->vbi_cap_seq_count;
 108         if (dev->field_cap == V4L2_FIELD_ALTERNATE)
 109                 buf->vb.sequence /= 2;
 110 
 111         vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
 112 
 113         memset(vbuf, 0, vb2_plane_size(&buf->vb.vb2_buf, 0));
 114         if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) {
 115                 unsigned i;
 116 
 117                 for (i = 0; i < 25; i++)
 118                         vbuf[i] = dev->vbi_gen.data[i];
 119         }
 120 }
 121 
 122 static int vbi_cap_queue_setup(struct vb2_queue *vq,
 123                        unsigned *nbuffers, unsigned *nplanes,
 124                        unsigned sizes[], struct device *alloc_devs[])
 125 {
 126         struct vivid_dev *dev = vb2_get_drv_priv(vq);
 127         bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 128         unsigned size = vq->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ?
 129                 36 * sizeof(struct v4l2_sliced_vbi_data) :
 130                 1440 * 2 * (is_60hz ? 12 : 18);
 131 
 132         if (!vivid_is_sdtv_cap(dev))
 133                 return -EINVAL;
 134 
 135         sizes[0] = size;
 136 
 137         if (vq->num_buffers + *nbuffers < 2)
 138                 *nbuffers = 2 - vq->num_buffers;
 139 
 140         *nplanes = 1;
 141         return 0;
 142 }
 143 
 144 static int vbi_cap_buf_prepare(struct vb2_buffer *vb)
 145 {
 146         struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 147         bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 148         unsigned size = vb->vb2_queue->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ?
 149                 36 * sizeof(struct v4l2_sliced_vbi_data) :
 150                 1440 * 2 * (is_60hz ? 12 : 18);
 151 
 152         dprintk(dev, 1, "%s\n", __func__);
 153 
 154         if (dev->buf_prepare_error) {
 155                 /*
 156                  * Error injection: test what happens if buf_prepare() returns
 157                  * an error.
 158                  */
 159                 dev->buf_prepare_error = false;
 160                 return -EINVAL;
 161         }
 162         if (vb2_plane_size(vb, 0) < size) {
 163                 dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
 164                                 __func__, vb2_plane_size(vb, 0), size);
 165                 return -EINVAL;
 166         }
 167         vb2_set_plane_payload(vb, 0, size);
 168 
 169         return 0;
 170 }
 171 
 172 static void vbi_cap_buf_queue(struct vb2_buffer *vb)
 173 {
 174         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 175         struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 176         struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
 177 
 178         dprintk(dev, 1, "%s\n", __func__);
 179 
 180         spin_lock(&dev->slock);
 181         list_add_tail(&buf->list, &dev->vbi_cap_active);
 182         spin_unlock(&dev->slock);
 183 }
 184 
 185 static int vbi_cap_start_streaming(struct vb2_queue *vq, unsigned count)
 186 {
 187         struct vivid_dev *dev = vb2_get_drv_priv(vq);
 188         int err;
 189 
 190         dprintk(dev, 1, "%s\n", __func__);
 191         dev->vbi_cap_seq_count = 0;
 192         if (dev->start_streaming_error) {
 193                 dev->start_streaming_error = false;
 194                 err = -EINVAL;
 195         } else {
 196                 err = vivid_start_generating_vid_cap(dev, &dev->vbi_cap_streaming);
 197         }
 198         if (err) {
 199                 struct vivid_buffer *buf, *tmp;
 200 
 201                 list_for_each_entry_safe(buf, tmp, &dev->vbi_cap_active, list) {
 202                         list_del(&buf->list);
 203                         vb2_buffer_done(&buf->vb.vb2_buf,
 204                                         VB2_BUF_STATE_QUEUED);
 205                 }
 206         }
 207         return err;
 208 }
 209 
 210 /* abort streaming and wait for last buffer */
 211 static void vbi_cap_stop_streaming(struct vb2_queue *vq)
 212 {
 213         struct vivid_dev *dev = vb2_get_drv_priv(vq);
 214 
 215         dprintk(dev, 1, "%s\n", __func__);
 216         vivid_stop_generating_vid_cap(dev, &dev->vbi_cap_streaming);
 217 }
 218 
 219 static void vbi_cap_buf_request_complete(struct vb2_buffer *vb)
 220 {
 221         struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 222 
 223         v4l2_ctrl_request_complete(vb->req_obj.req, &dev->ctrl_hdl_vbi_cap);
 224 }
 225 
 226 const struct vb2_ops vivid_vbi_cap_qops = {
 227         .queue_setup            = vbi_cap_queue_setup,
 228         .buf_prepare            = vbi_cap_buf_prepare,
 229         .buf_queue              = vbi_cap_buf_queue,
 230         .start_streaming        = vbi_cap_start_streaming,
 231         .stop_streaming         = vbi_cap_stop_streaming,
 232         .buf_request_complete   = vbi_cap_buf_request_complete,
 233         .wait_prepare           = vb2_ops_wait_prepare,
 234         .wait_finish            = vb2_ops_wait_finish,
 235 };
 236 
 237 int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 238                                         struct v4l2_format *f)
 239 {
 240         struct vivid_dev *dev = video_drvdata(file);
 241         struct v4l2_vbi_format *vbi = &f->fmt.vbi;
 242 
 243         if (!vivid_is_sdtv_cap(dev) || !dev->has_raw_vbi_cap)
 244                 return -EINVAL;
 245 
 246         vivid_g_fmt_vbi_cap(dev, vbi);
 247         return 0;
 248 }
 249 
 250 int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
 251                                         struct v4l2_format *f)
 252 {
 253         struct vivid_dev *dev = video_drvdata(file);
 254         int ret = vidioc_g_fmt_vbi_cap(file, priv, f);
 255 
 256         if (ret)
 257                 return ret;
 258         if (dev->stream_sliced_vbi_cap && vb2_is_busy(&dev->vb_vbi_cap_q))
 259                 return -EBUSY;
 260         dev->stream_sliced_vbi_cap = false;
 261         dev->vbi_cap_dev.queue->type = V4L2_BUF_TYPE_VBI_CAPTURE;
 262         return 0;
 263 }
 264 
 265 void vivid_fill_service_lines(struct v4l2_sliced_vbi_format *vbi, u32 service_set)
 266 {
 267         vbi->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
 268         vbi->service_set = service_set;
 269         memset(vbi->service_lines, 0, sizeof(vbi->service_lines));
 270         memset(vbi->reserved, 0, sizeof(vbi->reserved));
 271 
 272         if (vbi->service_set == 0)
 273                 return;
 274 
 275         if (vbi->service_set & V4L2_SLICED_CAPTION_525) {
 276                 vbi->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
 277                 vbi->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
 278         }
 279         if (vbi->service_set & V4L2_SLICED_WSS_625) {
 280                 unsigned i;
 281 
 282                 for (i = 7; i <= 18; i++)
 283                         vbi->service_lines[0][i] =
 284                         vbi->service_lines[1][i] = V4L2_SLICED_TELETEXT_B;
 285                 vbi->service_lines[0][23] = V4L2_SLICED_WSS_625;
 286         }
 287 }
 288 
 289 int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 290 {
 291         struct vivid_dev *dev = video_drvdata(file);
 292         struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
 293 
 294         if (!vivid_is_sdtv_cap(dev) || !dev->has_sliced_vbi_cap)
 295                 return -EINVAL;
 296 
 297         vivid_fill_service_lines(vbi, dev->service_set_cap);
 298         return 0;
 299 }
 300 
 301 int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 302 {
 303         struct vivid_dev *dev = video_drvdata(file);
 304         struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
 305         bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 306         u32 service_set = vbi->service_set;
 307 
 308         if (!vivid_is_sdtv_cap(dev) || !dev->has_sliced_vbi_cap)
 309                 return -EINVAL;
 310 
 311         service_set &= is_60hz ? V4L2_SLICED_CAPTION_525 :
 312                                  V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
 313         vivid_fill_service_lines(vbi, service_set);
 314         return 0;
 315 }
 316 
 317 int vidioc_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 318 {
 319         struct vivid_dev *dev = video_drvdata(file);
 320         struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
 321         int ret = vidioc_try_fmt_sliced_vbi_cap(file, fh, fmt);
 322 
 323         if (ret)
 324                 return ret;
 325         if (!dev->stream_sliced_vbi_cap && vb2_is_busy(&dev->vb_vbi_cap_q))
 326                 return -EBUSY;
 327         dev->service_set_cap = vbi->service_set;
 328         dev->stream_sliced_vbi_cap = true;
 329         dev->vbi_cap_dev.queue->type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
 330         return 0;
 331 }
 332 
 333 int vidioc_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
 334 {
 335         struct vivid_dev *dev = video_drvdata(file);
 336         struct video_device *vdev = video_devdata(file);
 337         bool is_60hz;
 338 
 339         if (vdev->vfl_dir == VFL_DIR_RX) {
 340                 is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 341                 if (!vivid_is_sdtv_cap(dev) || !dev->has_sliced_vbi_cap ||
 342                     cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
 343                         return -EINVAL;
 344         } else {
 345                 is_60hz = dev->std_out & V4L2_STD_525_60;
 346                 if (!vivid_is_svid_out(dev) || !dev->has_sliced_vbi_out ||
 347                     cap->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
 348                         return -EINVAL;
 349         }
 350 
 351         cap->service_set = is_60hz ? V4L2_SLICED_CAPTION_525 :
 352                                      V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
 353         if (is_60hz) {
 354                 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
 355                 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
 356         } else {
 357                 unsigned i;
 358 
 359                 for (i = 7; i <= 18; i++)
 360                         cap->service_lines[0][i] =
 361                         cap->service_lines[1][i] = V4L2_SLICED_TELETEXT_B;
 362                 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
 363         }
 364         return 0;
 365 }

/* [<][>][^][v][top][bottom][index][help] */