vivid-vbi-out.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * vivid-vbi-out.c - vbi output support functions.
  4. *
  5. * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
  6. */
  7. #include <linux/errno.h>
  8. #include <linux/kernel.h>
  9. #include <linux/videodev2.h>
  10. #include <media/v4l2-common.h>
  11. #include "vivid-core.h"
  12. #include "vivid-kthread-out.h"
  13. #include "vivid-vbi-out.h"
  14. #include "vivid-vbi-cap.h"
  15. static int vbi_out_queue_setup(struct vb2_queue *vq,
  16. unsigned *nbuffers, unsigned *nplanes,
  17. unsigned sizes[], struct device *alloc_devs[])
  18. {
  19. struct vivid_dev *dev = vb2_get_drv_priv(vq);
  20. bool is_60hz = dev->std_out & V4L2_STD_525_60;
  21. unsigned size = vq->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ?
  22. 36 * sizeof(struct v4l2_sliced_vbi_data) :
  23. 1440 * 2 * (is_60hz ? 12 : 18);
  24. if (!vivid_is_svid_out(dev))
  25. return -EINVAL;
  26. sizes[0] = size;
  27. if (vq->num_buffers + *nbuffers < 2)
  28. *nbuffers = 2 - vq->num_buffers;
  29. *nplanes = 1;
  30. return 0;
  31. }
  32. static int vbi_out_buf_prepare(struct vb2_buffer *vb)
  33. {
  34. struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
  35. bool is_60hz = dev->std_out & V4L2_STD_525_60;
  36. unsigned size = vb->vb2_queue->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ?
  37. 36 * sizeof(struct v4l2_sliced_vbi_data) :
  38. 1440 * 2 * (is_60hz ? 12 : 18);
  39. dprintk(dev, 1, "%s\n", __func__);
  40. if (dev->buf_prepare_error) {
  41. /*
  42. * Error injection: test what happens if buf_prepare() returns
  43. * an error.
  44. */
  45. dev->buf_prepare_error = false;
  46. return -EINVAL;
  47. }
  48. if (vb2_plane_size(vb, 0) < size) {
  49. dprintk(dev, 1, "%s data will not fit into plane (%lu < %u)\n",
  50. __func__, vb2_plane_size(vb, 0), size);
  51. return -EINVAL;
  52. }
  53. vb2_set_plane_payload(vb, 0, size);
  54. return 0;
  55. }
  56. static void vbi_out_buf_queue(struct vb2_buffer *vb)
  57. {
  58. struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
  59. struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
  60. struct vivid_buffer *buf = container_of(vbuf, struct vivid_buffer, vb);
  61. dprintk(dev, 1, "%s\n", __func__);
  62. spin_lock(&dev->slock);
  63. list_add_tail(&buf->list, &dev->vbi_out_active);
  64. spin_unlock(&dev->slock);
  65. }
  66. static int vbi_out_start_streaming(struct vb2_queue *vq, unsigned count)
  67. {
  68. struct vivid_dev *dev = vb2_get_drv_priv(vq);
  69. int err;
  70. dprintk(dev, 1, "%s\n", __func__);
  71. dev->vbi_out_seq_count = 0;
  72. if (dev->start_streaming_error) {
  73. dev->start_streaming_error = false;
  74. err = -EINVAL;
  75. } else {
  76. err = vivid_start_generating_vid_out(dev, &dev->vbi_out_streaming);
  77. }
  78. if (err) {
  79. struct vivid_buffer *buf, *tmp;
  80. list_for_each_entry_safe(buf, tmp, &dev->vbi_out_active, list) {
  81. list_del(&buf->list);
  82. vb2_buffer_done(&buf->vb.vb2_buf,
  83. VB2_BUF_STATE_QUEUED);
  84. }
  85. }
  86. return err;
  87. }
  88. /* abort streaming and wait for last buffer */
  89. static void vbi_out_stop_streaming(struct vb2_queue *vq)
  90. {
  91. struct vivid_dev *dev = vb2_get_drv_priv(vq);
  92. dprintk(dev, 1, "%s\n", __func__);
  93. vivid_stop_generating_vid_out(dev, &dev->vbi_out_streaming);
  94. dev->vbi_out_have_wss = false;
  95. dev->vbi_out_have_cc[0] = false;
  96. dev->vbi_out_have_cc[1] = false;
  97. }
  98. const struct vb2_ops vivid_vbi_out_qops = {
  99. .queue_setup = vbi_out_queue_setup,
  100. .buf_prepare = vbi_out_buf_prepare,
  101. .buf_queue = vbi_out_buf_queue,
  102. .start_streaming = vbi_out_start_streaming,
  103. .stop_streaming = vbi_out_stop_streaming,
  104. .wait_prepare = vb2_ops_wait_prepare,
  105. .wait_finish = vb2_ops_wait_finish,
  106. };
  107. int vidioc_g_fmt_vbi_out(struct file *file, void *priv,
  108. struct v4l2_format *f)
  109. {
  110. struct vivid_dev *dev = video_drvdata(file);
  111. struct v4l2_vbi_format *vbi = &f->fmt.vbi;
  112. bool is_60hz = dev->std_out & V4L2_STD_525_60;
  113. if (!vivid_is_svid_out(dev) || !dev->has_raw_vbi_out)
  114. return -EINVAL;
  115. vbi->sampling_rate = 25000000;
  116. vbi->offset = 24;
  117. vbi->samples_per_line = 1440;
  118. vbi->sample_format = V4L2_PIX_FMT_GREY;
  119. vbi->start[0] = is_60hz ? V4L2_VBI_ITU_525_F1_START + 9 : V4L2_VBI_ITU_625_F1_START + 5;
  120. vbi->start[1] = is_60hz ? V4L2_VBI_ITU_525_F2_START + 9 : V4L2_VBI_ITU_625_F2_START + 5;
  121. vbi->count[0] = vbi->count[1] = is_60hz ? 12 : 18;
  122. vbi->flags = dev->vbi_cap_interlaced ? V4L2_VBI_INTERLACED : 0;
  123. vbi->reserved[0] = 0;
  124. vbi->reserved[1] = 0;
  125. return 0;
  126. }
  127. int vidioc_s_fmt_vbi_out(struct file *file, void *priv,
  128. struct v4l2_format *f)
  129. {
  130. struct vivid_dev *dev = video_drvdata(file);
  131. int ret = vidioc_g_fmt_vbi_out(file, priv, f);
  132. if (ret)
  133. return ret;
  134. if (vb2_is_busy(&dev->vb_vbi_out_q))
  135. return -EBUSY;
  136. dev->stream_sliced_vbi_out = false;
  137. dev->vbi_out_dev.queue->type = V4L2_BUF_TYPE_VBI_OUTPUT;
  138. return 0;
  139. }
  140. int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
  141. {
  142. struct vivid_dev *dev = video_drvdata(file);
  143. struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
  144. if (!vivid_is_svid_out(dev) || !dev->has_sliced_vbi_out)
  145. return -EINVAL;
  146. vivid_fill_service_lines(vbi, dev->service_set_out);
  147. return 0;
  148. }
  149. int vidioc_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
  150. {
  151. struct vivid_dev *dev = video_drvdata(file);
  152. struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
  153. bool is_60hz = dev->std_out & V4L2_STD_525_60;
  154. u32 service_set = vbi->service_set;
  155. if (!vivid_is_svid_out(dev) || !dev->has_sliced_vbi_out)
  156. return -EINVAL;
  157. service_set &= is_60hz ? V4L2_SLICED_CAPTION_525 :
  158. V4L2_SLICED_WSS_625 | V4L2_SLICED_TELETEXT_B;
  159. vivid_fill_service_lines(vbi, service_set);
  160. return 0;
  161. }
  162. int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh,
  163. struct v4l2_format *fmt)
  164. {
  165. struct vivid_dev *dev = video_drvdata(file);
  166. struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
  167. int ret = vidioc_try_fmt_sliced_vbi_out(file, fh, fmt);
  168. if (ret)
  169. return ret;
  170. if (vb2_is_busy(&dev->vb_vbi_out_q))
  171. return -EBUSY;
  172. dev->service_set_out = vbi->service_set;
  173. dev->stream_sliced_vbi_out = true;
  174. dev->vbi_out_dev.queue->type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
  175. return 0;
  176. }
  177. void vivid_sliced_vbi_out_process(struct vivid_dev *dev,
  178. struct vivid_buffer *buf)
  179. {
  180. struct v4l2_sliced_vbi_data *vbi =
  181. vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
  182. unsigned elems =
  183. vb2_get_plane_payload(&buf->vb.vb2_buf, 0) / sizeof(*vbi);
  184. dev->vbi_out_have_cc[0] = false;
  185. dev->vbi_out_have_cc[1] = false;
  186. dev->vbi_out_have_wss = false;
  187. while (elems--) {
  188. switch (vbi->id) {
  189. case V4L2_SLICED_CAPTION_525:
  190. if ((dev->std_out & V4L2_STD_525_60) && vbi->line == 21) {
  191. dev->vbi_out_have_cc[!!vbi->field] = true;
  192. dev->vbi_out_cc[!!vbi->field][0] = vbi->data[0];
  193. dev->vbi_out_cc[!!vbi->field][1] = vbi->data[1];
  194. }
  195. break;
  196. case V4L2_SLICED_WSS_625:
  197. if ((dev->std_out & V4L2_STD_625_50) &&
  198. vbi->field == 0 && vbi->line == 23) {
  199. dev->vbi_out_have_wss = true;
  200. dev->vbi_out_wss[0] = vbi->data[0];
  201. dev->vbi_out_wss[1] = vbi->data[1];
  202. }
  203. break;
  204. }
  205. vbi++;
  206. }
  207. }