vivid-kthread-out.c (10838B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * vivid-kthread-out.h - video/vbi output thread support functions. 4 * 5 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 6 */ 7 8#include <linux/module.h> 9#include <linux/errno.h> 10#include <linux/kernel.h> 11#include <linux/init.h> 12#include <linux/sched.h> 13#include <linux/slab.h> 14#include <linux/font.h> 15#include <linux/mutex.h> 16#include <linux/videodev2.h> 17#include <linux/kthread.h> 18#include <linux/freezer.h> 19#include <linux/random.h> 20#include <linux/v4l2-dv-timings.h> 21#include <linux/jiffies.h> 22#include <asm/div64.h> 23#include <media/videobuf2-vmalloc.h> 24#include <media/v4l2-dv-timings.h> 25#include <media/v4l2-ioctl.h> 26#include <media/v4l2-fh.h> 27#include <media/v4l2-event.h> 28 29#include "vivid-core.h" 30#include "vivid-vid-common.h" 31#include "vivid-vid-cap.h" 32#include "vivid-vid-out.h" 33#include "vivid-radio-common.h" 34#include "vivid-radio-rx.h" 35#include "vivid-radio-tx.h" 36#include "vivid-sdr-cap.h" 37#include "vivid-vbi-cap.h" 38#include "vivid-vbi-out.h" 39#include "vivid-osd.h" 40#include "vivid-ctrls.h" 41#include "vivid-kthread-out.h" 42#include "vivid-meta-out.h" 43 44static void vivid_thread_vid_out_tick(struct vivid_dev *dev) 45{ 46 struct vivid_buffer *vid_out_buf = NULL; 47 struct vivid_buffer *vbi_out_buf = NULL; 48 struct vivid_buffer *meta_out_buf = NULL; 49 50 dprintk(dev, 1, "Video Output Thread Tick\n"); 51 52 /* Drop a certain percentage of buffers. */ 53 if (dev->perc_dropped_buffers && 54 prandom_u32_max(100) < dev->perc_dropped_buffers) 55 return; 56 57 spin_lock(&dev->slock); 58 /* 59 * Only dequeue buffer if there is at least one more pending. 60 * This makes video loopback possible. 61 */ 62 if (!list_empty(&dev->vid_out_active) && 63 !list_is_singular(&dev->vid_out_active)) { 64 vid_out_buf = list_entry(dev->vid_out_active.next, 65 struct vivid_buffer, list); 66 list_del(&vid_out_buf->list); 67 } 68 if (!list_empty(&dev->vbi_out_active) && 69 (dev->field_out != V4L2_FIELD_ALTERNATE || 70 (dev->vbi_out_seq_count & 1))) { 71 vbi_out_buf = list_entry(dev->vbi_out_active.next, 72 struct vivid_buffer, list); 73 list_del(&vbi_out_buf->list); 74 } 75 if (!list_empty(&dev->meta_out_active)) { 76 meta_out_buf = list_entry(dev->meta_out_active.next, 77 struct vivid_buffer, list); 78 list_del(&meta_out_buf->list); 79 } 80 spin_unlock(&dev->slock); 81 82 if (!vid_out_buf && !vbi_out_buf && !meta_out_buf) 83 return; 84 85 if (vid_out_buf) { 86 v4l2_ctrl_request_setup(vid_out_buf->vb.vb2_buf.req_obj.req, 87 &dev->ctrl_hdl_vid_out); 88 v4l2_ctrl_request_complete(vid_out_buf->vb.vb2_buf.req_obj.req, 89 &dev->ctrl_hdl_vid_out); 90 vid_out_buf->vb.sequence = dev->vid_out_seq_count; 91 if (dev->field_out == V4L2_FIELD_ALTERNATE) { 92 /* 93 * The sequence counter counts frames, not fields. 94 * So divide by two. 95 */ 96 vid_out_buf->vb.sequence /= 2; 97 } 98 vid_out_buf->vb.vb2_buf.timestamp = 99 ktime_get_ns() + dev->time_wrap_offset; 100 vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ? 101 VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); 102 dprintk(dev, 2, "vid_out buffer %d done\n", 103 vid_out_buf->vb.vb2_buf.index); 104 } 105 106 if (vbi_out_buf) { 107 v4l2_ctrl_request_setup(vbi_out_buf->vb.vb2_buf.req_obj.req, 108 &dev->ctrl_hdl_vbi_out); 109 v4l2_ctrl_request_complete(vbi_out_buf->vb.vb2_buf.req_obj.req, 110 &dev->ctrl_hdl_vbi_out); 111 if (dev->stream_sliced_vbi_out) 112 vivid_sliced_vbi_out_process(dev, vbi_out_buf); 113 114 vbi_out_buf->vb.sequence = dev->vbi_out_seq_count; 115 vbi_out_buf->vb.vb2_buf.timestamp = 116 ktime_get_ns() + dev->time_wrap_offset; 117 vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ? 118 VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); 119 dprintk(dev, 2, "vbi_out buffer %d done\n", 120 vbi_out_buf->vb.vb2_buf.index); 121 } 122 if (meta_out_buf) { 123 v4l2_ctrl_request_setup(meta_out_buf->vb.vb2_buf.req_obj.req, 124 &dev->ctrl_hdl_meta_out); 125 v4l2_ctrl_request_complete(meta_out_buf->vb.vb2_buf.req_obj.req, 126 &dev->ctrl_hdl_meta_out); 127 vivid_meta_out_process(dev, meta_out_buf); 128 meta_out_buf->vb.sequence = dev->meta_out_seq_count; 129 meta_out_buf->vb.vb2_buf.timestamp = 130 ktime_get_ns() + dev->time_wrap_offset; 131 vb2_buffer_done(&meta_out_buf->vb.vb2_buf, dev->dqbuf_error ? 132 VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); 133 dprintk(dev, 2, "meta_out buffer %d done\n", 134 meta_out_buf->vb.vb2_buf.index); 135 } 136 137 dev->dqbuf_error = false; 138} 139 140static int vivid_thread_vid_out(void *data) 141{ 142 struct vivid_dev *dev = data; 143 u64 numerators_since_start; 144 u64 buffers_since_start; 145 u64 next_jiffies_since_start; 146 unsigned long jiffies_since_start; 147 unsigned long cur_jiffies; 148 unsigned wait_jiffies; 149 unsigned numerator; 150 unsigned denominator; 151 152 dprintk(dev, 1, "Video Output Thread Start\n"); 153 154 set_freezable(); 155 156 /* Resets frame counters */ 157 dev->out_seq_offset = 0; 158 dev->out_seq_count = 0; 159 dev->jiffies_vid_out = jiffies; 160 dev->out_seq_resync = false; 161 if (dev->time_wrap) 162 dev->time_wrap_offset = dev->time_wrap - ktime_get_ns(); 163 else 164 dev->time_wrap_offset = 0; 165 166 for (;;) { 167 try_to_freeze(); 168 if (kthread_should_stop()) 169 break; 170 171 if (!mutex_trylock(&dev->mutex)) { 172 schedule(); 173 continue; 174 } 175 176 cur_jiffies = jiffies; 177 if (dev->out_seq_resync) { 178 dev->jiffies_vid_out = cur_jiffies; 179 dev->out_seq_offset = dev->out_seq_count + 1; 180 dev->out_seq_count = 0; 181 dev->out_seq_resync = false; 182 } 183 numerator = dev->timeperframe_vid_out.numerator; 184 denominator = dev->timeperframe_vid_out.denominator; 185 186 if (dev->field_out == V4L2_FIELD_ALTERNATE) 187 denominator *= 2; 188 189 /* Calculate the number of jiffies since we started streaming */ 190 jiffies_since_start = cur_jiffies - dev->jiffies_vid_out; 191 /* Get the number of buffers streamed since the start */ 192 buffers_since_start = (u64)jiffies_since_start * denominator + 193 (HZ * numerator) / 2; 194 do_div(buffers_since_start, HZ * numerator); 195 196 /* 197 * After more than 0xf0000000 (rounded down to a multiple of 198 * 'jiffies-per-day' to ease jiffies_to_msecs calculation) 199 * jiffies have passed since we started streaming reset the 200 * counters and keep track of the sequence offset. 201 */ 202 if (jiffies_since_start > JIFFIES_RESYNC) { 203 dev->jiffies_vid_out = cur_jiffies; 204 dev->out_seq_offset = buffers_since_start; 205 buffers_since_start = 0; 206 } 207 dev->out_seq_count = buffers_since_start + dev->out_seq_offset; 208 dev->vid_out_seq_count = dev->out_seq_count - dev->vid_out_seq_start; 209 dev->vbi_out_seq_count = dev->out_seq_count - dev->vbi_out_seq_start; 210 dev->meta_out_seq_count = dev->out_seq_count - dev->meta_out_seq_start; 211 212 vivid_thread_vid_out_tick(dev); 213 mutex_unlock(&dev->mutex); 214 215 /* 216 * Calculate the number of 'numerators' streamed since we started, 217 * not including the current buffer. 218 */ 219 numerators_since_start = buffers_since_start * numerator; 220 221 /* And the number of jiffies since we started */ 222 jiffies_since_start = jiffies - dev->jiffies_vid_out; 223 224 /* Increase by the 'numerator' of one buffer */ 225 numerators_since_start += numerator; 226 /* 227 * Calculate when that next buffer is supposed to start 228 * in jiffies since we started streaming. 229 */ 230 next_jiffies_since_start = numerators_since_start * HZ + 231 denominator / 2; 232 do_div(next_jiffies_since_start, denominator); 233 /* If it is in the past, then just schedule asap */ 234 if (next_jiffies_since_start < jiffies_since_start) 235 next_jiffies_since_start = jiffies_since_start; 236 237 wait_jiffies = next_jiffies_since_start - jiffies_since_start; 238 while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && 239 !kthread_should_stop()) 240 schedule(); 241 } 242 dprintk(dev, 1, "Video Output Thread End\n"); 243 return 0; 244} 245 246static void vivid_grab_controls(struct vivid_dev *dev, bool grab) 247{ 248 v4l2_ctrl_grab(dev->ctrl_has_crop_out, grab); 249 v4l2_ctrl_grab(dev->ctrl_has_compose_out, grab); 250 v4l2_ctrl_grab(dev->ctrl_has_scaler_out, grab); 251 v4l2_ctrl_grab(dev->ctrl_tx_mode, grab); 252 v4l2_ctrl_grab(dev->ctrl_tx_rgb_range, grab); 253} 254 255int vivid_start_generating_vid_out(struct vivid_dev *dev, bool *pstreaming) 256{ 257 dprintk(dev, 1, "%s\n", __func__); 258 259 if (dev->kthread_vid_out) { 260 u32 seq_count = dev->out_seq_count + dev->seq_wrap * 128; 261 262 if (pstreaming == &dev->vid_out_streaming) 263 dev->vid_out_seq_start = seq_count; 264 else if (pstreaming == &dev->vbi_out_streaming) 265 dev->vbi_out_seq_start = seq_count; 266 else 267 dev->meta_out_seq_start = seq_count; 268 *pstreaming = true; 269 return 0; 270 } 271 272 /* Resets frame counters */ 273 dev->jiffies_vid_out = jiffies; 274 dev->vid_out_seq_start = dev->seq_wrap * 128; 275 dev->vbi_out_seq_start = dev->seq_wrap * 128; 276 dev->meta_out_seq_start = dev->seq_wrap * 128; 277 278 dev->kthread_vid_out = kthread_run(vivid_thread_vid_out, dev, 279 "%s-vid-out", dev->v4l2_dev.name); 280 281 if (IS_ERR(dev->kthread_vid_out)) { 282 int err = PTR_ERR(dev->kthread_vid_out); 283 284 dev->kthread_vid_out = NULL; 285 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); 286 return err; 287 } 288 *pstreaming = true; 289 vivid_grab_controls(dev, true); 290 291 dprintk(dev, 1, "returning from %s\n", __func__); 292 return 0; 293} 294 295void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming) 296{ 297 dprintk(dev, 1, "%s\n", __func__); 298 299 if (dev->kthread_vid_out == NULL) 300 return; 301 302 *pstreaming = false; 303 if (pstreaming == &dev->vid_out_streaming) { 304 /* Release all active buffers */ 305 while (!list_empty(&dev->vid_out_active)) { 306 struct vivid_buffer *buf; 307 308 buf = list_entry(dev->vid_out_active.next, 309 struct vivid_buffer, list); 310 list_del(&buf->list); 311 v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req, 312 &dev->ctrl_hdl_vid_out); 313 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 314 dprintk(dev, 2, "vid_out buffer %d done\n", 315 buf->vb.vb2_buf.index); 316 } 317 } 318 319 if (pstreaming == &dev->vbi_out_streaming) { 320 while (!list_empty(&dev->vbi_out_active)) { 321 struct vivid_buffer *buf; 322 323 buf = list_entry(dev->vbi_out_active.next, 324 struct vivid_buffer, list); 325 list_del(&buf->list); 326 v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req, 327 &dev->ctrl_hdl_vbi_out); 328 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 329 dprintk(dev, 2, "vbi_out buffer %d done\n", 330 buf->vb.vb2_buf.index); 331 } 332 } 333 334 if (pstreaming == &dev->meta_out_streaming) { 335 while (!list_empty(&dev->meta_out_active)) { 336 struct vivid_buffer *buf; 337 338 buf = list_entry(dev->meta_out_active.next, 339 struct vivid_buffer, list); 340 list_del(&buf->list); 341 v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req, 342 &dev->ctrl_hdl_meta_out); 343 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 344 dprintk(dev, 2, "meta_out buffer %d done\n", 345 buf->vb.vb2_buf.index); 346 } 347 } 348 349 if (dev->vid_out_streaming || dev->vbi_out_streaming || 350 dev->meta_out_streaming) 351 return; 352 353 /* shutdown control thread */ 354 vivid_grab_controls(dev, false); 355 kthread_stop(dev->kthread_vid_out); 356 dev->kthread_vid_out = NULL; 357}