root/drivers/media/platform/vivid/vivid-kthread-out.c

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

DEFINITIONS

This source file includes following definitions.
  1. vivid_thread_vid_out_tick
  2. vivid_thread_vid_out
  3. vivid_grab_controls
  4. vivid_start_generating_vid_out
  5. vivid_stop_generating_vid_out

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

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