linux/drivers/media/platform/vivid/vivid-kthread-out.c
<<
>>
Prefs
   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
  42static 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                vid_out_buf->vb.sequence = dev->vid_out_seq_count;
  79                if (dev->field_out == V4L2_FIELD_ALTERNATE) {
  80                        /*
  81                         * The sequence counter counts frames, not fields.
  82                         * So divide by two.
  83                         */
  84                        vid_out_buf->vb.sequence /= 2;
  85                }
  86                vid_out_buf->vb.vb2_buf.timestamp =
  87                        ktime_get_ns() + dev->time_wrap_offset;
  88                vb2_buffer_done(&vid_out_buf->vb.vb2_buf, dev->dqbuf_error ?
  89                                VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
  90                dprintk(dev, 2, "vid_out buffer %d done\n",
  91                        vid_out_buf->vb.vb2_buf.index);
  92        }
  93
  94        if (vbi_out_buf) {
  95                if (dev->stream_sliced_vbi_out)
  96                        vivid_sliced_vbi_out_process(dev, vbi_out_buf);
  97
  98                vbi_out_buf->vb.sequence = dev->vbi_out_seq_count;
  99                vbi_out_buf->vb.vb2_buf.timestamp =
 100                        ktime_get_ns() + dev->time_wrap_offset;
 101                vb2_buffer_done(&vbi_out_buf->vb.vb2_buf, dev->dqbuf_error ?
 102                                VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 103                dprintk(dev, 2, "vbi_out buffer %d done\n",
 104                        vbi_out_buf->vb.vb2_buf.index);
 105        }
 106        dev->dqbuf_error = false;
 107}
 108
 109static int vivid_thread_vid_out(void *data)
 110{
 111        struct vivid_dev *dev = data;
 112        u64 numerators_since_start;
 113        u64 buffers_since_start;
 114        u64 next_jiffies_since_start;
 115        unsigned long jiffies_since_start;
 116        unsigned long cur_jiffies;
 117        unsigned wait_jiffies;
 118        unsigned numerator;
 119        unsigned denominator;
 120
 121        dprintk(dev, 1, "Video Output Thread Start\n");
 122
 123        set_freezable();
 124
 125        /* Resets frame counters */
 126        dev->out_seq_offset = 0;
 127        if (dev->seq_wrap)
 128                dev->out_seq_count = 0xffffff80U;
 129        dev->jiffies_vid_out = jiffies;
 130        dev->vid_out_seq_start = dev->vbi_out_seq_start = 0;
 131        dev->out_seq_resync = false;
 132
 133        for (;;) {
 134                try_to_freeze();
 135                if (kthread_should_stop())
 136                        break;
 137
 138                mutex_lock(&dev->mutex);
 139                cur_jiffies = jiffies;
 140                if (dev->out_seq_resync) {
 141                        dev->jiffies_vid_out = cur_jiffies;
 142                        dev->out_seq_offset = dev->out_seq_count + 1;
 143                        dev->out_seq_count = 0;
 144                        dev->out_seq_resync = false;
 145                }
 146                numerator = dev->timeperframe_vid_out.numerator;
 147                denominator = dev->timeperframe_vid_out.denominator;
 148
 149                if (dev->field_out == V4L2_FIELD_ALTERNATE)
 150                        denominator *= 2;
 151
 152                /* Calculate the number of jiffies since we started streaming */
 153                jiffies_since_start = cur_jiffies - dev->jiffies_vid_out;
 154                /* Get the number of buffers streamed since the start */
 155                buffers_since_start = (u64)jiffies_since_start * denominator +
 156                                      (HZ * numerator) / 2;
 157                do_div(buffers_since_start, HZ * numerator);
 158
 159                /*
 160                 * After more than 0xf0000000 (rounded down to a multiple of
 161                 * 'jiffies-per-day' to ease jiffies_to_msecs calculation)
 162                 * jiffies have passed since we started streaming reset the
 163                 * counters and keep track of the sequence offset.
 164                 */
 165                if (jiffies_since_start > JIFFIES_RESYNC) {
 166                        dev->jiffies_vid_out = cur_jiffies;
 167                        dev->out_seq_offset = buffers_since_start;
 168                        buffers_since_start = 0;
 169                }
 170                dev->out_seq_count = buffers_since_start + dev->out_seq_offset;
 171                dev->vid_out_seq_count = dev->out_seq_count - dev->vid_out_seq_start;
 172                dev->vbi_out_seq_count = dev->out_seq_count - dev->vbi_out_seq_start;
 173
 174                vivid_thread_vid_out_tick(dev);
 175                mutex_unlock(&dev->mutex);
 176
 177                /*
 178                 * Calculate the number of 'numerators' streamed since we started,
 179                 * not including the current buffer.
 180                 */
 181                numerators_since_start = buffers_since_start * numerator;
 182
 183                /* And the number of jiffies since we started */
 184                jiffies_since_start = jiffies - dev->jiffies_vid_out;
 185
 186                /* Increase by the 'numerator' of one buffer */
 187                numerators_since_start += numerator;
 188                /*
 189                 * Calculate when that next buffer is supposed to start
 190                 * in jiffies since we started streaming.
 191                 */
 192                next_jiffies_since_start = numerators_since_start * HZ +
 193                                           denominator / 2;
 194                do_div(next_jiffies_since_start, denominator);
 195                /* If it is in the past, then just schedule asap */
 196                if (next_jiffies_since_start < jiffies_since_start)
 197                        next_jiffies_since_start = jiffies_since_start;
 198
 199                wait_jiffies = next_jiffies_since_start - jiffies_since_start;
 200                schedule_timeout_interruptible(wait_jiffies ? wait_jiffies : 1);
 201        }
 202        dprintk(dev, 1, "Video Output Thread End\n");
 203        return 0;
 204}
 205
 206static void vivid_grab_controls(struct vivid_dev *dev, bool grab)
 207{
 208        v4l2_ctrl_grab(dev->ctrl_has_crop_out, grab);
 209        v4l2_ctrl_grab(dev->ctrl_has_compose_out, grab);
 210        v4l2_ctrl_grab(dev->ctrl_has_scaler_out, grab);
 211        v4l2_ctrl_grab(dev->ctrl_tx_mode, grab);
 212        v4l2_ctrl_grab(dev->ctrl_tx_rgb_range, grab);
 213}
 214
 215int vivid_start_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
 216{
 217        dprintk(dev, 1, "%s\n", __func__);
 218
 219        if (dev->kthread_vid_out) {
 220                u32 seq_count = dev->out_seq_count + dev->seq_wrap * 128;
 221
 222                if (pstreaming == &dev->vid_out_streaming)
 223                        dev->vid_out_seq_start = seq_count;
 224                else
 225                        dev->vbi_out_seq_start = seq_count;
 226                *pstreaming = true;
 227                return 0;
 228        }
 229
 230        /* Resets frame counters */
 231        dev->jiffies_vid_out = jiffies;
 232        dev->vid_out_seq_start = dev->seq_wrap * 128;
 233        dev->vbi_out_seq_start = dev->seq_wrap * 128;
 234
 235        dev->kthread_vid_out = kthread_run(vivid_thread_vid_out, dev,
 236                        "%s-vid-out", dev->v4l2_dev.name);
 237
 238        if (IS_ERR(dev->kthread_vid_out)) {
 239                v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
 240                return PTR_ERR(dev->kthread_vid_out);
 241        }
 242        *pstreaming = true;
 243        vivid_grab_controls(dev, true);
 244
 245        dprintk(dev, 1, "returning from %s\n", __func__);
 246        return 0;
 247}
 248
 249void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
 250{
 251        dprintk(dev, 1, "%s\n", __func__);
 252
 253        if (dev->kthread_vid_out == NULL)
 254                return;
 255
 256        *pstreaming = false;
 257        if (pstreaming == &dev->vid_out_streaming) {
 258                /* Release all active buffers */
 259                while (!list_empty(&dev->vid_out_active)) {
 260                        struct vivid_buffer *buf;
 261
 262                        buf = list_entry(dev->vid_out_active.next,
 263                                         struct vivid_buffer, list);
 264                        list_del(&buf->list);
 265                        vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 266                        dprintk(dev, 2, "vid_out buffer %d done\n",
 267                                buf->vb.vb2_buf.index);
 268                }
 269        }
 270
 271        if (pstreaming == &dev->vbi_out_streaming) {
 272                while (!list_empty(&dev->vbi_out_active)) {
 273                        struct vivid_buffer *buf;
 274
 275                        buf = list_entry(dev->vbi_out_active.next,
 276                                         struct vivid_buffer, list);
 277                        list_del(&buf->list);
 278                        vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 279                        dprintk(dev, 2, "vbi_out buffer %d done\n",
 280                                buf->vb.vb2_buf.index);
 281                }
 282        }
 283
 284        if (dev->vid_out_streaming || dev->vbi_out_streaming)
 285                return;
 286
 287        /* shutdown control thread */
 288        vivid_grab_controls(dev, false);
 289        mutex_unlock(&dev->mutex);
 290        kthread_stop(dev->kthread_vid_out);
 291        dev->kthread_vid_out = NULL;
 292        mutex_lock(&dev->mutex);
 293}
 294