1dacca5f0SHans Verkuil // SPDX-License-Identifier: GPL-2.0-only 2dacca5f0SHans Verkuil /* 3dacca5f0SHans Verkuil * vivid-kthread-cap.h - video/vbi capture thread support functions. 4dacca5f0SHans Verkuil * 5dacca5f0SHans Verkuil * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 6dacca5f0SHans Verkuil */ 7dacca5f0SHans Verkuil 8dacca5f0SHans Verkuil #include <linux/module.h> 9dacca5f0SHans Verkuil #include <linux/errno.h> 10dacca5f0SHans Verkuil #include <linux/kernel.h> 11dacca5f0SHans Verkuil #include <linux/init.h> 12dacca5f0SHans Verkuil #include <linux/sched.h> 13dacca5f0SHans Verkuil #include <linux/slab.h> 14dacca5f0SHans Verkuil #include <linux/font.h> 15dacca5f0SHans Verkuil #include <linux/mutex.h> 16dacca5f0SHans Verkuil #include <linux/videodev2.h> 17dacca5f0SHans Verkuil #include <linux/kthread.h> 18dacca5f0SHans Verkuil #include <linux/freezer.h> 19dacca5f0SHans Verkuil #include <linux/random.h> 20dacca5f0SHans Verkuil #include <linux/v4l2-dv-timings.h> 21dacca5f0SHans Verkuil #include <asm/div64.h> 22dacca5f0SHans Verkuil #include <media/videobuf2-vmalloc.h> 23dacca5f0SHans Verkuil #include <media/v4l2-dv-timings.h> 24dacca5f0SHans Verkuil #include <media/v4l2-ioctl.h> 25dacca5f0SHans Verkuil #include <media/v4l2-fh.h> 26dacca5f0SHans Verkuil #include <media/v4l2-event.h> 27dacca5f0SHans Verkuil #include <media/v4l2-rect.h> 28dacca5f0SHans Verkuil 29dacca5f0SHans Verkuil #include "vivid-core.h" 30dacca5f0SHans Verkuil #include "vivid-vid-common.h" 31dacca5f0SHans Verkuil #include "vivid-vid-cap.h" 32dacca5f0SHans Verkuil #include "vivid-vid-out.h" 33dacca5f0SHans Verkuil #include "vivid-radio-common.h" 34dacca5f0SHans Verkuil #include "vivid-radio-rx.h" 35dacca5f0SHans Verkuil #include "vivid-radio-tx.h" 36dacca5f0SHans Verkuil #include "vivid-sdr-cap.h" 37dacca5f0SHans Verkuil #include "vivid-vbi-cap.h" 38dacca5f0SHans Verkuil #include "vivid-vbi-out.h" 39dacca5f0SHans Verkuil #include "vivid-osd.h" 40dacca5f0SHans Verkuil #include "vivid-ctrls.h" 41dacca5f0SHans Verkuil #include "vivid-kthread-cap.h" 42dacca5f0SHans Verkuil #include "vivid-meta-cap.h" 43dacca5f0SHans Verkuil 44dacca5f0SHans Verkuil static inline v4l2_std_id vivid_get_std_cap(const struct vivid_dev *dev) 45dacca5f0SHans Verkuil { 46dacca5f0SHans Verkuil if (vivid_is_sdtv_cap(dev)) 47dacca5f0SHans Verkuil return dev->std_cap[dev->input]; 48dacca5f0SHans Verkuil return 0; 49dacca5f0SHans Verkuil } 50dacca5f0SHans Verkuil 51dacca5f0SHans Verkuil static void copy_pix(struct vivid_dev *dev, int win_y, int win_x, 52dacca5f0SHans Verkuil u16 *cap, const u16 *osd) 53dacca5f0SHans Verkuil { 54dacca5f0SHans Verkuil u16 out; 55dacca5f0SHans Verkuil int left = dev->overlay_out_left; 56dacca5f0SHans Verkuil int top = dev->overlay_out_top; 57dacca5f0SHans Verkuil int fb_x = win_x + left; 58dacca5f0SHans Verkuil int fb_y = win_y + top; 59dacca5f0SHans Verkuil int i; 60dacca5f0SHans Verkuil 61dacca5f0SHans Verkuil out = *cap; 62dacca5f0SHans Verkuil *cap = *osd; 63dacca5f0SHans Verkuil if (dev->bitmap_out) { 64dacca5f0SHans Verkuil const u8 *p = dev->bitmap_out; 65dacca5f0SHans Verkuil unsigned stride = (dev->compose_out.width + 7) / 8; 66dacca5f0SHans Verkuil 67dacca5f0SHans Verkuil win_x -= dev->compose_out.left; 68dacca5f0SHans Verkuil win_y -= dev->compose_out.top; 69dacca5f0SHans Verkuil if (!(p[stride * win_y + win_x / 8] & (1 << (win_x & 7)))) 70dacca5f0SHans Verkuil return; 71dacca5f0SHans Verkuil } 72dacca5f0SHans Verkuil 73dacca5f0SHans Verkuil for (i = 0; i < dev->clipcount_out; i++) { 74dacca5f0SHans Verkuil struct v4l2_rect *r = &dev->clips_out[i].c; 75dacca5f0SHans Verkuil 76dacca5f0SHans Verkuil if (fb_y >= r->top && fb_y < r->top + r->height && 77dacca5f0SHans Verkuil fb_x >= r->left && fb_x < r->left + r->width) 78dacca5f0SHans Verkuil return; 79dacca5f0SHans Verkuil } 80dacca5f0SHans Verkuil if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_CHROMAKEY) && 81dacca5f0SHans Verkuil *osd != dev->chromakey_out) 82dacca5f0SHans Verkuil return; 83dacca5f0SHans Verkuil if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) && 84dacca5f0SHans Verkuil out == dev->chromakey_out) 85dacca5f0SHans Verkuil return; 86dacca5f0SHans Verkuil if (dev->fmt_cap->alpha_mask) { 87dacca5f0SHans Verkuil if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) && 88dacca5f0SHans Verkuil dev->global_alpha_out) 89dacca5f0SHans Verkuil return; 90dacca5f0SHans Verkuil if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) && 91dacca5f0SHans Verkuil *cap & dev->fmt_cap->alpha_mask) 92dacca5f0SHans Verkuil return; 93dacca5f0SHans Verkuil if ((dev->fbuf_out_flags & V4L2_FBUF_FLAG_LOCAL_INV_ALPHA) && 94dacca5f0SHans Verkuil !(*cap & dev->fmt_cap->alpha_mask)) 95dacca5f0SHans Verkuil return; 96dacca5f0SHans Verkuil } 97dacca5f0SHans Verkuil *cap = out; 98dacca5f0SHans Verkuil } 99dacca5f0SHans Verkuil 100dacca5f0SHans Verkuil static void blend_line(struct vivid_dev *dev, unsigned y_offset, unsigned x_offset, 101dacca5f0SHans Verkuil u8 *vcapbuf, const u8 *vosdbuf, 102dacca5f0SHans Verkuil unsigned width, unsigned pixsize) 103dacca5f0SHans Verkuil { 104dacca5f0SHans Verkuil unsigned x; 105dacca5f0SHans Verkuil 106dacca5f0SHans Verkuil for (x = 0; x < width; x++, vcapbuf += pixsize, vosdbuf += pixsize) { 107dacca5f0SHans Verkuil copy_pix(dev, y_offset, x_offset + x, 108dacca5f0SHans Verkuil (u16 *)vcapbuf, (const u16 *)vosdbuf); 109dacca5f0SHans Verkuil } 110dacca5f0SHans Verkuil } 111dacca5f0SHans Verkuil 112dacca5f0SHans Verkuil static void scale_line(const u8 *src, u8 *dst, unsigned srcw, unsigned dstw, unsigned twopixsize) 113dacca5f0SHans Verkuil { 114dacca5f0SHans Verkuil /* Coarse scaling with Bresenham */ 115dacca5f0SHans Verkuil unsigned int_part; 116dacca5f0SHans Verkuil unsigned fract_part; 117dacca5f0SHans Verkuil unsigned src_x = 0; 118dacca5f0SHans Verkuil unsigned error = 0; 119dacca5f0SHans Verkuil unsigned x; 120dacca5f0SHans Verkuil 121dacca5f0SHans Verkuil /* 122dacca5f0SHans Verkuil * We always combine two pixels to prevent color bleed in the packed 123dacca5f0SHans Verkuil * yuv case. 124dacca5f0SHans Verkuil */ 125dacca5f0SHans Verkuil srcw /= 2; 126dacca5f0SHans Verkuil dstw /= 2; 127dacca5f0SHans Verkuil int_part = srcw / dstw; 128dacca5f0SHans Verkuil fract_part = srcw % dstw; 129dacca5f0SHans Verkuil for (x = 0; x < dstw; x++, dst += twopixsize) { 130dacca5f0SHans Verkuil memcpy(dst, src + src_x * twopixsize, twopixsize); 131dacca5f0SHans Verkuil src_x += int_part; 132dacca5f0SHans Verkuil error += fract_part; 133dacca5f0SHans Verkuil if (error >= dstw) { 134dacca5f0SHans Verkuil error -= dstw; 135dacca5f0SHans Verkuil src_x++; 136dacca5f0SHans Verkuil } 137dacca5f0SHans Verkuil } 138dacca5f0SHans Verkuil } 139dacca5f0SHans Verkuil 140dacca5f0SHans Verkuil /* 141dacca5f0SHans Verkuil * Precalculate the rectangles needed to perform video looping: 142dacca5f0SHans Verkuil * 143dacca5f0SHans Verkuil * The nominal pipeline is that the video output buffer is cropped by 144dacca5f0SHans Verkuil * crop_out, scaled to compose_out, overlaid with the output overlay, 145dacca5f0SHans Verkuil * cropped on the capture side by crop_cap and scaled again to the video 146dacca5f0SHans Verkuil * capture buffer using compose_cap. 147dacca5f0SHans Verkuil * 148dacca5f0SHans Verkuil * To keep things efficient we calculate the intersection of compose_out 149dacca5f0SHans Verkuil * and crop_cap (since that's the only part of the video that will 150dacca5f0SHans Verkuil * actually end up in the capture buffer), determine which part of the 151dacca5f0SHans Verkuil * video output buffer that is and which part of the video capture buffer 152dacca5f0SHans Verkuil * so we can scale the video straight from the output buffer to the capture 153dacca5f0SHans Verkuil * buffer without any intermediate steps. 154dacca5f0SHans Verkuil * 155dacca5f0SHans Verkuil * If we need to deal with an output overlay, then there is no choice and 156dacca5f0SHans Verkuil * that intermediate step still has to be taken. For the output overlay 157dacca5f0SHans Verkuil * support we calculate the intersection of the framebuffer and the overlay 158dacca5f0SHans Verkuil * window (which may be partially or wholly outside of the framebuffer 159dacca5f0SHans Verkuil * itself) and the intersection of that with loop_vid_copy (i.e. the part of 160dacca5f0SHans Verkuil * the actual looped video that will be overlaid). The result is calculated 161dacca5f0SHans Verkuil * both in framebuffer coordinates (loop_fb_copy) and compose_out coordinates 162dacca5f0SHans Verkuil * (loop_vid_overlay). Finally calculate the part of the capture buffer that 163dacca5f0SHans Verkuil * will receive that overlaid video. 164dacca5f0SHans Verkuil */ 165dacca5f0SHans Verkuil static void vivid_precalc_copy_rects(struct vivid_dev *dev) 166dacca5f0SHans Verkuil { 167dacca5f0SHans Verkuil /* Framebuffer rectangle */ 168dacca5f0SHans Verkuil struct v4l2_rect r_fb = { 169dacca5f0SHans Verkuil 0, 0, dev->display_width, dev->display_height 170dacca5f0SHans Verkuil }; 171dacca5f0SHans Verkuil /* Overlay window rectangle in framebuffer coordinates */ 172dacca5f0SHans Verkuil struct v4l2_rect r_overlay = { 173dacca5f0SHans Verkuil dev->overlay_out_left, dev->overlay_out_top, 174dacca5f0SHans Verkuil dev->compose_out.width, dev->compose_out.height 175dacca5f0SHans Verkuil }; 176dacca5f0SHans Verkuil 177dacca5f0SHans Verkuil v4l2_rect_intersect(&dev->loop_vid_copy, &dev->crop_cap, &dev->compose_out); 178dacca5f0SHans Verkuil 179dacca5f0SHans Verkuil dev->loop_vid_out = dev->loop_vid_copy; 180dacca5f0SHans Verkuil v4l2_rect_scale(&dev->loop_vid_out, &dev->compose_out, &dev->crop_out); 181dacca5f0SHans Verkuil dev->loop_vid_out.left += dev->crop_out.left; 182dacca5f0SHans Verkuil dev->loop_vid_out.top += dev->crop_out.top; 183dacca5f0SHans Verkuil 184dacca5f0SHans Verkuil dev->loop_vid_cap = dev->loop_vid_copy; 185dacca5f0SHans Verkuil v4l2_rect_scale(&dev->loop_vid_cap, &dev->crop_cap, &dev->compose_cap); 186dacca5f0SHans Verkuil 187dacca5f0SHans Verkuil dprintk(dev, 1, 188dacca5f0SHans Verkuil "loop_vid_copy: %dx%d@%dx%d loop_vid_out: %dx%d@%dx%d loop_vid_cap: %dx%d@%dx%d\n", 189dacca5f0SHans Verkuil dev->loop_vid_copy.width, dev->loop_vid_copy.height, 190dacca5f0SHans Verkuil dev->loop_vid_copy.left, dev->loop_vid_copy.top, 191dacca5f0SHans Verkuil dev->loop_vid_out.width, dev->loop_vid_out.height, 192dacca5f0SHans Verkuil dev->loop_vid_out.left, dev->loop_vid_out.top, 193dacca5f0SHans Verkuil dev->loop_vid_cap.width, dev->loop_vid_cap.height, 194dacca5f0SHans Verkuil dev->loop_vid_cap.left, dev->loop_vid_cap.top); 195dacca5f0SHans Verkuil 196dacca5f0SHans Verkuil v4l2_rect_intersect(&r_overlay, &r_fb, &r_overlay); 197dacca5f0SHans Verkuil 198dacca5f0SHans Verkuil /* shift r_overlay to the same origin as compose_out */ 199dacca5f0SHans Verkuil r_overlay.left += dev->compose_out.left - dev->overlay_out_left; 200dacca5f0SHans Verkuil r_overlay.top += dev->compose_out.top - dev->overlay_out_top; 201dacca5f0SHans Verkuil 202dacca5f0SHans Verkuil v4l2_rect_intersect(&dev->loop_vid_overlay, &r_overlay, &dev->loop_vid_copy); 203dacca5f0SHans Verkuil dev->loop_fb_copy = dev->loop_vid_overlay; 204dacca5f0SHans Verkuil 205dacca5f0SHans Verkuil /* shift dev->loop_fb_copy back again to the fb origin */ 206dacca5f0SHans Verkuil dev->loop_fb_copy.left -= dev->compose_out.left - dev->overlay_out_left; 207dacca5f0SHans Verkuil dev->loop_fb_copy.top -= dev->compose_out.top - dev->overlay_out_top; 208dacca5f0SHans Verkuil 209dacca5f0SHans Verkuil dev->loop_vid_overlay_cap = dev->loop_vid_overlay; 210dacca5f0SHans Verkuil v4l2_rect_scale(&dev->loop_vid_overlay_cap, &dev->crop_cap, &dev->compose_cap); 211dacca5f0SHans Verkuil 212dacca5f0SHans Verkuil dprintk(dev, 1, 213dacca5f0SHans Verkuil "loop_fb_copy: %dx%d@%dx%d loop_vid_overlay: %dx%d@%dx%d loop_vid_overlay_cap: %dx%d@%dx%d\n", 214dacca5f0SHans Verkuil dev->loop_fb_copy.width, dev->loop_fb_copy.height, 215dacca5f0SHans Verkuil dev->loop_fb_copy.left, dev->loop_fb_copy.top, 216dacca5f0SHans Verkuil dev->loop_vid_overlay.width, dev->loop_vid_overlay.height, 217dacca5f0SHans Verkuil dev->loop_vid_overlay.left, dev->loop_vid_overlay.top, 218dacca5f0SHans Verkuil dev->loop_vid_overlay_cap.width, dev->loop_vid_overlay_cap.height, 219dacca5f0SHans Verkuil dev->loop_vid_overlay_cap.left, dev->loop_vid_overlay_cap.top); 220dacca5f0SHans Verkuil } 221dacca5f0SHans Verkuil 222dacca5f0SHans Verkuil static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf, 223dacca5f0SHans Verkuil unsigned p, unsigned bpl[TPG_MAX_PLANES], unsigned h) 224dacca5f0SHans Verkuil { 225dacca5f0SHans Verkuil unsigned i; 226dacca5f0SHans Verkuil void *vbuf; 227dacca5f0SHans Verkuil 228dacca5f0SHans Verkuil if (p == 0 || tpg_g_buffers(tpg) > 1) 229dacca5f0SHans Verkuil return vb2_plane_vaddr(&buf->vb.vb2_buf, p); 230dacca5f0SHans Verkuil vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); 231dacca5f0SHans Verkuil for (i = 0; i < p; i++) 232dacca5f0SHans Verkuil vbuf += bpl[i] * h / tpg->vdownsampling[i]; 233dacca5f0SHans Verkuil return vbuf; 234dacca5f0SHans Verkuil } 235dacca5f0SHans Verkuil 236dacca5f0SHans Verkuil static noinline_for_stack int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, 237dacca5f0SHans Verkuil u8 *vcapbuf, struct vivid_buffer *vid_cap_buf) 238dacca5f0SHans Verkuil { 239dacca5f0SHans Verkuil bool blank = dev->must_blank[vid_cap_buf->vb.vb2_buf.index]; 240dacca5f0SHans Verkuil struct tpg_data *tpg = &dev->tpg; 241dacca5f0SHans Verkuil struct vivid_buffer *vid_out_buf = NULL; 242dacca5f0SHans Verkuil unsigned vdiv = dev->fmt_out->vdownsampling[p]; 243dacca5f0SHans Verkuil unsigned twopixsize = tpg_g_twopixelsize(tpg, p); 244dacca5f0SHans Verkuil unsigned img_width = tpg_hdiv(tpg, p, dev->compose_cap.width); 245dacca5f0SHans Verkuil unsigned img_height = dev->compose_cap.height; 246dacca5f0SHans Verkuil unsigned stride_cap = tpg->bytesperline[p]; 247dacca5f0SHans Verkuil unsigned stride_out = dev->bytesperline_out[p]; 248dacca5f0SHans Verkuil unsigned stride_osd = dev->display_byte_stride; 249dacca5f0SHans Verkuil unsigned hmax = (img_height * tpg->perc_fill) / 100; 250dacca5f0SHans Verkuil u8 *voutbuf; 251dacca5f0SHans Verkuil u8 *vosdbuf = NULL; 252dacca5f0SHans Verkuil unsigned y; 253dacca5f0SHans Verkuil bool blend = dev->bitmap_out || dev->clipcount_out || dev->fbuf_out_flags; 254dacca5f0SHans Verkuil /* Coarse scaling with Bresenham */ 255dacca5f0SHans Verkuil unsigned vid_out_int_part; 256dacca5f0SHans Verkuil unsigned vid_out_fract_part; 257dacca5f0SHans Verkuil unsigned vid_out_y = 0; 258dacca5f0SHans Verkuil unsigned vid_out_error = 0; 259dacca5f0SHans Verkuil unsigned vid_overlay_int_part = 0; 260dacca5f0SHans Verkuil unsigned vid_overlay_fract_part = 0; 261dacca5f0SHans Verkuil unsigned vid_overlay_y = 0; 262dacca5f0SHans Verkuil unsigned vid_overlay_error = 0; 263dacca5f0SHans Verkuil unsigned vid_cap_left = tpg_hdiv(tpg, p, dev->loop_vid_cap.left); 264dacca5f0SHans Verkuil unsigned vid_cap_right; 265dacca5f0SHans Verkuil bool quick; 266dacca5f0SHans Verkuil 267dacca5f0SHans Verkuil vid_out_int_part = dev->loop_vid_out.height / dev->loop_vid_cap.height; 268dacca5f0SHans Verkuil vid_out_fract_part = dev->loop_vid_out.height % dev->loop_vid_cap.height; 269dacca5f0SHans Verkuil 270dacca5f0SHans Verkuil if (!list_empty(&dev->vid_out_active)) 271dacca5f0SHans Verkuil vid_out_buf = list_entry(dev->vid_out_active.next, 272dacca5f0SHans Verkuil struct vivid_buffer, list); 273dacca5f0SHans Verkuil if (vid_out_buf == NULL) 274dacca5f0SHans Verkuil return -ENODATA; 275dacca5f0SHans Verkuil 276dacca5f0SHans Verkuil vid_cap_buf->vb.field = vid_out_buf->vb.field; 277dacca5f0SHans Verkuil 278dacca5f0SHans Verkuil voutbuf = plane_vaddr(tpg, vid_out_buf, p, 279dacca5f0SHans Verkuil dev->bytesperline_out, dev->fmt_out_rect.height); 280dacca5f0SHans Verkuil if (p < dev->fmt_out->buffers) 281dacca5f0SHans Verkuil voutbuf += vid_out_buf->vb.vb2_buf.planes[p].data_offset; 282dacca5f0SHans Verkuil voutbuf += tpg_hdiv(tpg, p, dev->loop_vid_out.left) + 283dacca5f0SHans Verkuil (dev->loop_vid_out.top / vdiv) * stride_out; 284dacca5f0SHans Verkuil vcapbuf += tpg_hdiv(tpg, p, dev->compose_cap.left) + 285dacca5f0SHans Verkuil (dev->compose_cap.top / vdiv) * stride_cap; 286dacca5f0SHans Verkuil 287dacca5f0SHans Verkuil if (dev->loop_vid_copy.width == 0 || dev->loop_vid_copy.height == 0) { 288dacca5f0SHans Verkuil /* 289dacca5f0SHans Verkuil * If there is nothing to copy, then just fill the capture window 290dacca5f0SHans Verkuil * with black. 291dacca5f0SHans Verkuil */ 292dacca5f0SHans Verkuil for (y = 0; y < hmax / vdiv; y++, vcapbuf += stride_cap) 293dacca5f0SHans Verkuil memcpy(vcapbuf, tpg->black_line[p], img_width); 294dacca5f0SHans Verkuil return 0; 295dacca5f0SHans Verkuil } 296dacca5f0SHans Verkuil 297dacca5f0SHans Verkuil if (dev->overlay_out_enabled && 298dacca5f0SHans Verkuil dev->loop_vid_overlay.width && dev->loop_vid_overlay.height) { 299dacca5f0SHans Verkuil vosdbuf = dev->video_vbase; 300dacca5f0SHans Verkuil vosdbuf += (dev->loop_fb_copy.left * twopixsize) / 2 + 301dacca5f0SHans Verkuil dev->loop_fb_copy.top * stride_osd; 302dacca5f0SHans Verkuil vid_overlay_int_part = dev->loop_vid_overlay.height / 303dacca5f0SHans Verkuil dev->loop_vid_overlay_cap.height; 304dacca5f0SHans Verkuil vid_overlay_fract_part = dev->loop_vid_overlay.height % 305dacca5f0SHans Verkuil dev->loop_vid_overlay_cap.height; 306dacca5f0SHans Verkuil } 307dacca5f0SHans Verkuil 308dacca5f0SHans Verkuil vid_cap_right = tpg_hdiv(tpg, p, dev->loop_vid_cap.left + dev->loop_vid_cap.width); 309dacca5f0SHans Verkuil /* quick is true if no video scaling is needed */ 310dacca5f0SHans Verkuil quick = dev->loop_vid_out.width == dev->loop_vid_cap.width; 311dacca5f0SHans Verkuil 312dacca5f0SHans Verkuil dev->cur_scaled_line = dev->loop_vid_out.height; 313dacca5f0SHans Verkuil for (y = 0; y < hmax; y += vdiv, vcapbuf += stride_cap) { 314dacca5f0SHans Verkuil /* osdline is true if this line requires overlay blending */ 315dacca5f0SHans Verkuil bool osdline = vosdbuf && y >= dev->loop_vid_overlay_cap.top && 316dacca5f0SHans Verkuil y < dev->loop_vid_overlay_cap.top + dev->loop_vid_overlay_cap.height; 317dacca5f0SHans Verkuil 318dacca5f0SHans Verkuil /* 319dacca5f0SHans Verkuil * If this line of the capture buffer doesn't get any video, then 320dacca5f0SHans Verkuil * just fill with black. 321dacca5f0SHans Verkuil */ 322dacca5f0SHans Verkuil if (y < dev->loop_vid_cap.top || 323dacca5f0SHans Verkuil y >= dev->loop_vid_cap.top + dev->loop_vid_cap.height) { 324dacca5f0SHans Verkuil memcpy(vcapbuf, tpg->black_line[p], img_width); 325dacca5f0SHans Verkuil continue; 326dacca5f0SHans Verkuil } 327dacca5f0SHans Verkuil 328dacca5f0SHans Verkuil /* fill the left border with black */ 329dacca5f0SHans Verkuil if (dev->loop_vid_cap.left) 330dacca5f0SHans Verkuil memcpy(vcapbuf, tpg->black_line[p], vid_cap_left); 331dacca5f0SHans Verkuil 332dacca5f0SHans Verkuil /* fill the right border with black */ 333dacca5f0SHans Verkuil if (vid_cap_right < img_width) 334dacca5f0SHans Verkuil memcpy(vcapbuf + vid_cap_right, tpg->black_line[p], 335dacca5f0SHans Verkuil img_width - vid_cap_right); 336dacca5f0SHans Verkuil 337dacca5f0SHans Verkuil if (quick && !osdline) { 338dacca5f0SHans Verkuil memcpy(vcapbuf + vid_cap_left, 339dacca5f0SHans Verkuil voutbuf + vid_out_y * stride_out, 340dacca5f0SHans Verkuil tpg_hdiv(tpg, p, dev->loop_vid_cap.width)); 341dacca5f0SHans Verkuil goto update_vid_out_y; 342dacca5f0SHans Verkuil } 343dacca5f0SHans Verkuil if (dev->cur_scaled_line == vid_out_y) { 344dacca5f0SHans Verkuil memcpy(vcapbuf + vid_cap_left, dev->scaled_line, 345dacca5f0SHans Verkuil tpg_hdiv(tpg, p, dev->loop_vid_cap.width)); 346dacca5f0SHans Verkuil goto update_vid_out_y; 347dacca5f0SHans Verkuil } 348dacca5f0SHans Verkuil if (!osdline) { 349dacca5f0SHans Verkuil scale_line(voutbuf + vid_out_y * stride_out, dev->scaled_line, 350dacca5f0SHans Verkuil tpg_hdiv(tpg, p, dev->loop_vid_out.width), 351dacca5f0SHans Verkuil tpg_hdiv(tpg, p, dev->loop_vid_cap.width), 352dacca5f0SHans Verkuil tpg_g_twopixelsize(tpg, p)); 353dacca5f0SHans Verkuil } else { 354dacca5f0SHans Verkuil /* 355dacca5f0SHans Verkuil * Offset in bytes within loop_vid_copy to the start of the 356dacca5f0SHans Verkuil * loop_vid_overlay rectangle. 357dacca5f0SHans Verkuil */ 358dacca5f0SHans Verkuil unsigned offset = 359dacca5f0SHans Verkuil ((dev->loop_vid_overlay.left - dev->loop_vid_copy.left) * 360dacca5f0SHans Verkuil twopixsize) / 2; 361dacca5f0SHans Verkuil u8 *osd = vosdbuf + vid_overlay_y * stride_osd; 362dacca5f0SHans Verkuil 363dacca5f0SHans Verkuil scale_line(voutbuf + vid_out_y * stride_out, dev->blended_line, 364dacca5f0SHans Verkuil dev->loop_vid_out.width, dev->loop_vid_copy.width, 365dacca5f0SHans Verkuil tpg_g_twopixelsize(tpg, p)); 366dacca5f0SHans Verkuil if (blend) 367dacca5f0SHans Verkuil blend_line(dev, vid_overlay_y + dev->loop_vid_overlay.top, 368dacca5f0SHans Verkuil dev->loop_vid_overlay.left, 369dacca5f0SHans Verkuil dev->blended_line + offset, osd, 370dacca5f0SHans Verkuil dev->loop_vid_overlay.width, twopixsize / 2); 371dacca5f0SHans Verkuil else 372dacca5f0SHans Verkuil memcpy(dev->blended_line + offset, 373dacca5f0SHans Verkuil osd, (dev->loop_vid_overlay.width * twopixsize) / 2); 374dacca5f0SHans Verkuil scale_line(dev->blended_line, dev->scaled_line, 375dacca5f0SHans Verkuil dev->loop_vid_copy.width, dev->loop_vid_cap.width, 376dacca5f0SHans Verkuil tpg_g_twopixelsize(tpg, p)); 377dacca5f0SHans Verkuil } 378dacca5f0SHans Verkuil dev->cur_scaled_line = vid_out_y; 379dacca5f0SHans Verkuil memcpy(vcapbuf + vid_cap_left, dev->scaled_line, 380dacca5f0SHans Verkuil tpg_hdiv(tpg, p, dev->loop_vid_cap.width)); 381dacca5f0SHans Verkuil 382dacca5f0SHans Verkuil update_vid_out_y: 383dacca5f0SHans Verkuil if (osdline) { 384dacca5f0SHans Verkuil vid_overlay_y += vid_overlay_int_part; 385dacca5f0SHans Verkuil vid_overlay_error += vid_overlay_fract_part; 386dacca5f0SHans Verkuil if (vid_overlay_error >= dev->loop_vid_overlay_cap.height) { 387dacca5f0SHans Verkuil vid_overlay_error -= dev->loop_vid_overlay_cap.height; 388dacca5f0SHans Verkuil vid_overlay_y++; 389dacca5f0SHans Verkuil } 390dacca5f0SHans Verkuil } 391dacca5f0SHans Verkuil vid_out_y += vid_out_int_part; 392dacca5f0SHans Verkuil vid_out_error += vid_out_fract_part; 393dacca5f0SHans Verkuil if (vid_out_error >= dev->loop_vid_cap.height / vdiv) { 394dacca5f0SHans Verkuil vid_out_error -= dev->loop_vid_cap.height / vdiv; 395dacca5f0SHans Verkuil vid_out_y++; 396dacca5f0SHans Verkuil } 397dacca5f0SHans Verkuil } 398dacca5f0SHans Verkuil 399dacca5f0SHans Verkuil if (!blank) 400dacca5f0SHans Verkuil return 0; 401dacca5f0SHans Verkuil for (; y < img_height; y += vdiv, vcapbuf += stride_cap) 402dacca5f0SHans Verkuil memcpy(vcapbuf, tpg->contrast_line[p], img_width); 403dacca5f0SHans Verkuil return 0; 404dacca5f0SHans Verkuil } 405dacca5f0SHans Verkuil 406dacca5f0SHans Verkuil static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) 407dacca5f0SHans Verkuil { 408dacca5f0SHans Verkuil struct tpg_data *tpg = &dev->tpg; 409dacca5f0SHans Verkuil unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1; 410dacca5f0SHans Verkuil unsigned line_height = 16 / factor; 411dacca5f0SHans Verkuil bool is_tv = vivid_is_sdtv_cap(dev); 412dacca5f0SHans Verkuil bool is_60hz = is_tv && (dev->std_cap[dev->input] & V4L2_STD_525_60); 413dacca5f0SHans Verkuil unsigned p; 414dacca5f0SHans Verkuil int line = 1; 415dacca5f0SHans Verkuil u8 *basep[TPG_MAX_PLANES][2]; 416dacca5f0SHans Verkuil unsigned ms; 417dacca5f0SHans Verkuil char str[100]; 418dacca5f0SHans Verkuil s32 gain; 419dacca5f0SHans Verkuil bool is_loop = false; 420dacca5f0SHans Verkuil 421dacca5f0SHans Verkuil if (dev->loop_video && dev->can_loop_video && 422dacca5f0SHans Verkuil ((vivid_is_svid_cap(dev) && 423dacca5f0SHans Verkuil !VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) || 424dacca5f0SHans Verkuil (vivid_is_hdmi_cap(dev) && 425dacca5f0SHans Verkuil !VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode[dev->input])))) 426dacca5f0SHans Verkuil is_loop = true; 427dacca5f0SHans Verkuil 428dacca5f0SHans Verkuil buf->vb.sequence = dev->vid_cap_seq_count; 429bb65e3d9SHans Verkuil v4l2_ctrl_s_ctrl(dev->ro_int32, buf->vb.sequence & 0xff); 430dacca5f0SHans Verkuil if (dev->field_cap == V4L2_FIELD_ALTERNATE) { 431dacca5f0SHans Verkuil /* 432dacca5f0SHans Verkuil * 60 Hz standards start with the bottom field, 50 Hz standards 433dacca5f0SHans Verkuil * with the top field. So if the 0-based seq_count is even, 434dacca5f0SHans Verkuil * then the field is TOP for 50 Hz and BOTTOM for 60 Hz 435dacca5f0SHans Verkuil * standards. 436dacca5f0SHans Verkuil */ 437dacca5f0SHans Verkuil buf->vb.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ? 438dacca5f0SHans Verkuil V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP; 439dacca5f0SHans Verkuil /* 440dacca5f0SHans Verkuil * The sequence counter counts frames, not fields. So divide 441dacca5f0SHans Verkuil * by two. 442dacca5f0SHans Verkuil */ 443dacca5f0SHans Verkuil buf->vb.sequence /= 2; 444dacca5f0SHans Verkuil } else { 445dacca5f0SHans Verkuil buf->vb.field = dev->field_cap; 446dacca5f0SHans Verkuil } 447dacca5f0SHans Verkuil tpg_s_field(tpg, buf->vb.field, 448dacca5f0SHans Verkuil dev->field_cap == V4L2_FIELD_ALTERNATE); 449dacca5f0SHans Verkuil tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.vb2_buf.index]); 450dacca5f0SHans Verkuil 451dacca5f0SHans Verkuil vivid_precalc_copy_rects(dev); 452dacca5f0SHans Verkuil 453dacca5f0SHans Verkuil for (p = 0; p < tpg_g_planes(tpg); p++) { 454dacca5f0SHans Verkuil void *vbuf = plane_vaddr(tpg, buf, p, 455dacca5f0SHans Verkuil tpg->bytesperline, tpg->buf_height); 456dacca5f0SHans Verkuil 457dacca5f0SHans Verkuil /* 458dacca5f0SHans Verkuil * The first plane of a multiplanar format has a non-zero 459dacca5f0SHans Verkuil * data_offset. This helps testing whether the application 460dacca5f0SHans Verkuil * correctly supports non-zero data offsets. 461dacca5f0SHans Verkuil */ 462dacca5f0SHans Verkuil if (p < tpg_g_buffers(tpg) && dev->fmt_cap->data_offset[p]) { 463dacca5f0SHans Verkuil memset(vbuf, dev->fmt_cap->data_offset[p] & 0xff, 464dacca5f0SHans Verkuil dev->fmt_cap->data_offset[p]); 465dacca5f0SHans Verkuil vbuf += dev->fmt_cap->data_offset[p]; 466dacca5f0SHans Verkuil } 467dacca5f0SHans Verkuil tpg_calc_text_basep(tpg, basep, p, vbuf); 468dacca5f0SHans Verkuil if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf)) 469dacca5f0SHans Verkuil tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev), 470dacca5f0SHans Verkuil p, vbuf); 471dacca5f0SHans Verkuil } 472dacca5f0SHans Verkuil dev->must_blank[buf->vb.vb2_buf.index] = false; 473dacca5f0SHans Verkuil 474dacca5f0SHans Verkuil /* Updates stream time, only update at the start of a new frame. */ 475dacca5f0SHans Verkuil if (dev->field_cap != V4L2_FIELD_ALTERNATE || 476dacca5f0SHans Verkuil (dev->vid_cap_seq_count & 1) == 0) 477dacca5f0SHans Verkuil dev->ms_vid_cap = 478dacca5f0SHans Verkuil jiffies_to_msecs(jiffies - dev->jiffies_vid_cap); 479dacca5f0SHans Verkuil 480dacca5f0SHans Verkuil ms = dev->ms_vid_cap; 481dacca5f0SHans Verkuil if (dev->osd_mode <= 1) { 482dacca5f0SHans Verkuil snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d %u%s", 483dacca5f0SHans Verkuil (ms / (60 * 60 * 1000)) % 24, 484dacca5f0SHans Verkuil (ms / (60 * 1000)) % 60, 485dacca5f0SHans Verkuil (ms / 1000) % 60, 486dacca5f0SHans Verkuil ms % 1000, 487dacca5f0SHans Verkuil buf->vb.sequence, 488dacca5f0SHans Verkuil (dev->field_cap == V4L2_FIELD_ALTERNATE) ? 489dacca5f0SHans Verkuil (buf->vb.field == V4L2_FIELD_TOP ? 490dacca5f0SHans Verkuil " top" : " bottom") : ""); 491dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 492dacca5f0SHans Verkuil } 493dacca5f0SHans Verkuil if (dev->osd_mode == 0) { 494dacca5f0SHans Verkuil snprintf(str, sizeof(str), " %dx%d, input %d ", 495dacca5f0SHans Verkuil dev->src_rect.width, dev->src_rect.height, dev->input); 496dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 497dacca5f0SHans Verkuil 498dacca5f0SHans Verkuil gain = v4l2_ctrl_g_ctrl(dev->gain); 499dacca5f0SHans Verkuil mutex_lock(dev->ctrl_hdl_user_vid.lock); 500dacca5f0SHans Verkuil snprintf(str, sizeof(str), 501dacca5f0SHans Verkuil " brightness %3d, contrast %3d, saturation %3d, hue %d ", 502dacca5f0SHans Verkuil dev->brightness->cur.val, 503dacca5f0SHans Verkuil dev->contrast->cur.val, 504dacca5f0SHans Verkuil dev->saturation->cur.val, 505dacca5f0SHans Verkuil dev->hue->cur.val); 506dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 507dacca5f0SHans Verkuil snprintf(str, sizeof(str), 508dacca5f0SHans Verkuil " autogain %d, gain %3d, alpha 0x%02x ", 509dacca5f0SHans Verkuil dev->autogain->cur.val, gain, dev->alpha->cur.val); 510dacca5f0SHans Verkuil mutex_unlock(dev->ctrl_hdl_user_vid.lock); 511dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 512dacca5f0SHans Verkuil mutex_lock(dev->ctrl_hdl_user_aud.lock); 513dacca5f0SHans Verkuil snprintf(str, sizeof(str), 514dacca5f0SHans Verkuil " volume %3d, mute %d ", 515dacca5f0SHans Verkuil dev->volume->cur.val, dev->mute->cur.val); 516dacca5f0SHans Verkuil mutex_unlock(dev->ctrl_hdl_user_aud.lock); 517dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 518dacca5f0SHans Verkuil mutex_lock(dev->ctrl_hdl_user_gen.lock); 519bb65e3d9SHans Verkuil snprintf(str, sizeof(str), " int32 %d, ro_int32 %d, int64 %lld, bitmask %08x ", 520dacca5f0SHans Verkuil dev->int32->cur.val, 521bb65e3d9SHans Verkuil dev->ro_int32->cur.val, 522dacca5f0SHans Verkuil *dev->int64->p_cur.p_s64, 523dacca5f0SHans Verkuil dev->bitmask->cur.val); 524dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 525dacca5f0SHans Verkuil snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ", 526dacca5f0SHans Verkuil dev->boolean->cur.val, 527dacca5f0SHans Verkuil dev->menu->qmenu[dev->menu->cur.val], 528dacca5f0SHans Verkuil dev->string->p_cur.p_char); 529dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 530dacca5f0SHans Verkuil snprintf(str, sizeof(str), " integer_menu %lld, value %d ", 531dacca5f0SHans Verkuil dev->int_menu->qmenu_int[dev->int_menu->cur.val], 532dacca5f0SHans Verkuil dev->int_menu->cur.val); 533dacca5f0SHans Verkuil mutex_unlock(dev->ctrl_hdl_user_gen.lock); 534dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 535dacca5f0SHans Verkuil if (dev->button_pressed) { 536dacca5f0SHans Verkuil dev->button_pressed--; 537dacca5f0SHans Verkuil snprintf(str, sizeof(str), " button pressed!"); 538dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 539dacca5f0SHans Verkuil } 540dacca5f0SHans Verkuil if (dev->osd[0]) { 541dacca5f0SHans Verkuil if (vivid_is_hdmi_cap(dev)) { 542dacca5f0SHans Verkuil snprintf(str, sizeof(str), 543dacca5f0SHans Verkuil " OSD \"%s\"", dev->osd); 544dacca5f0SHans Verkuil tpg_gen_text(tpg, basep, line++ * line_height, 545dacca5f0SHans Verkuil 16, str); 546dacca5f0SHans Verkuil } 547dacca5f0SHans Verkuil if (dev->osd_jiffies && 548dacca5f0SHans Verkuil time_is_before_jiffies(dev->osd_jiffies + 5 * HZ)) { 549dacca5f0SHans Verkuil dev->osd[0] = 0; 550dacca5f0SHans Verkuil dev->osd_jiffies = 0; 551dacca5f0SHans Verkuil } 552dacca5f0SHans Verkuil } 553dacca5f0SHans Verkuil } 554dacca5f0SHans Verkuil } 555dacca5f0SHans Verkuil 556dacca5f0SHans Verkuil /* 557dacca5f0SHans Verkuil * Return true if this pixel coordinate is a valid video pixel. 558dacca5f0SHans Verkuil */ 559dacca5f0SHans Verkuil static bool valid_pix(struct vivid_dev *dev, int win_y, int win_x, int fb_y, int fb_x) 560dacca5f0SHans Verkuil { 561dacca5f0SHans Verkuil int i; 562dacca5f0SHans Verkuil 563dacca5f0SHans Verkuil if (dev->bitmap_cap) { 564dacca5f0SHans Verkuil /* 565dacca5f0SHans Verkuil * Only if the corresponding bit in the bitmap is set can 566dacca5f0SHans Verkuil * the video pixel be shown. Coordinates are relative to 567dacca5f0SHans Verkuil * the overlay window set by VIDIOC_S_FMT. 568dacca5f0SHans Verkuil */ 569dacca5f0SHans Verkuil const u8 *p = dev->bitmap_cap; 570dacca5f0SHans Verkuil unsigned stride = (dev->compose_cap.width + 7) / 8; 571dacca5f0SHans Verkuil 572dacca5f0SHans Verkuil if (!(p[stride * win_y + win_x / 8] & (1 << (win_x & 7)))) 573dacca5f0SHans Verkuil return false; 574dacca5f0SHans Verkuil } 575dacca5f0SHans Verkuil 576dacca5f0SHans Verkuil for (i = 0; i < dev->clipcount_cap; i++) { 577dacca5f0SHans Verkuil /* 578dacca5f0SHans Verkuil * Only if the framebuffer coordinate is not in any of the 579dacca5f0SHans Verkuil * clip rectangles will be video pixel be shown. 580dacca5f0SHans Verkuil */ 581dacca5f0SHans Verkuil struct v4l2_rect *r = &dev->clips_cap[i].c; 582dacca5f0SHans Verkuil 583dacca5f0SHans Verkuil if (fb_y >= r->top && fb_y < r->top + r->height && 584dacca5f0SHans Verkuil fb_x >= r->left && fb_x < r->left + r->width) 585dacca5f0SHans Verkuil return false; 586dacca5f0SHans Verkuil } 587dacca5f0SHans Verkuil return true; 588dacca5f0SHans Verkuil } 589dacca5f0SHans Verkuil 590dacca5f0SHans Verkuil /* 591dacca5f0SHans Verkuil * Draw the image into the overlay buffer. 592dacca5f0SHans Verkuil * Note that the combination of overlay and multiplanar is not supported. 593dacca5f0SHans Verkuil */ 594dacca5f0SHans Verkuil static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf) 595dacca5f0SHans Verkuil { 596dacca5f0SHans Verkuil struct tpg_data *tpg = &dev->tpg; 597dacca5f0SHans Verkuil unsigned pixsize = tpg_g_twopixelsize(tpg, 0) / 2; 598dacca5f0SHans Verkuil void *vbase = dev->fb_vbase_cap; 599dacca5f0SHans Verkuil void *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); 600dacca5f0SHans Verkuil unsigned img_width = dev->compose_cap.width; 601dacca5f0SHans Verkuil unsigned img_height = dev->compose_cap.height; 602dacca5f0SHans Verkuil unsigned stride = tpg->bytesperline[0]; 603dacca5f0SHans Verkuil /* if quick is true, then valid_pix() doesn't have to be called */ 604dacca5f0SHans Verkuil bool quick = dev->bitmap_cap == NULL && dev->clipcount_cap == 0; 605dacca5f0SHans Verkuil int x, y, w, out_x = 0; 606dacca5f0SHans Verkuil 607dacca5f0SHans Verkuil /* 608dacca5f0SHans Verkuil * Overlay support is only supported for formats that have a twopixelsize 609dacca5f0SHans Verkuil * that's >= 2. Warn and bail out if that's not the case. 610dacca5f0SHans Verkuil */ 611dacca5f0SHans Verkuil if (WARN_ON(pixsize == 0)) 612dacca5f0SHans Verkuil return; 613dacca5f0SHans Verkuil if ((dev->overlay_cap_field == V4L2_FIELD_TOP || 614dacca5f0SHans Verkuil dev->overlay_cap_field == V4L2_FIELD_BOTTOM) && 615dacca5f0SHans Verkuil dev->overlay_cap_field != buf->vb.field) 616dacca5f0SHans Verkuil return; 617dacca5f0SHans Verkuil 618dacca5f0SHans Verkuil vbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride; 619dacca5f0SHans Verkuil x = dev->overlay_cap_left; 620dacca5f0SHans Verkuil w = img_width; 621dacca5f0SHans Verkuil if (x < 0) { 622dacca5f0SHans Verkuil out_x = -x; 623dacca5f0SHans Verkuil w = w - out_x; 624dacca5f0SHans Verkuil x = 0; 625dacca5f0SHans Verkuil } else { 626dacca5f0SHans Verkuil w = dev->fb_cap.fmt.width - x; 627dacca5f0SHans Verkuil if (w > img_width) 628dacca5f0SHans Verkuil w = img_width; 629dacca5f0SHans Verkuil } 630dacca5f0SHans Verkuil if (w <= 0) 631dacca5f0SHans Verkuil return; 632dacca5f0SHans Verkuil if (dev->overlay_cap_top >= 0) 633dacca5f0SHans Verkuil vbase += dev->overlay_cap_top * dev->fb_cap.fmt.bytesperline; 634dacca5f0SHans Verkuil for (y = dev->overlay_cap_top; 635dacca5f0SHans Verkuil y < dev->overlay_cap_top + (int)img_height; 636dacca5f0SHans Verkuil y++, vbuf += stride) { 637dacca5f0SHans Verkuil int px; 638dacca5f0SHans Verkuil 639dacca5f0SHans Verkuil if (y < 0 || y > dev->fb_cap.fmt.height) 640dacca5f0SHans Verkuil continue; 641dacca5f0SHans Verkuil if (quick) { 642dacca5f0SHans Verkuil memcpy(vbase + x * pixsize, 643dacca5f0SHans Verkuil vbuf + out_x * pixsize, w * pixsize); 644dacca5f0SHans Verkuil vbase += dev->fb_cap.fmt.bytesperline; 645dacca5f0SHans Verkuil continue; 646dacca5f0SHans Verkuil } 647dacca5f0SHans Verkuil for (px = 0; px < w; px++) { 648dacca5f0SHans Verkuil if (!valid_pix(dev, y - dev->overlay_cap_top, 649dacca5f0SHans Verkuil px + out_x, y, px + x)) 650dacca5f0SHans Verkuil continue; 651dacca5f0SHans Verkuil memcpy(vbase + (px + x) * pixsize, 652dacca5f0SHans Verkuil vbuf + (px + out_x) * pixsize, 653dacca5f0SHans Verkuil pixsize); 654dacca5f0SHans Verkuil } 655dacca5f0SHans Verkuil vbase += dev->fb_cap.fmt.bytesperline; 656dacca5f0SHans Verkuil } 657dacca5f0SHans Verkuil } 658dacca5f0SHans Verkuil 659dacca5f0SHans Verkuil static void vivid_cap_update_frame_period(struct vivid_dev *dev) 660dacca5f0SHans Verkuil { 661dacca5f0SHans Verkuil u64 f_period; 662dacca5f0SHans Verkuil 663dacca5f0SHans Verkuil f_period = (u64)dev->timeperframe_vid_cap.numerator * 1000000000; 664dacca5f0SHans Verkuil if (WARN_ON(dev->timeperframe_vid_cap.denominator == 0)) 665dacca5f0SHans Verkuil dev->timeperframe_vid_cap.denominator = 1; 666dacca5f0SHans Verkuil do_div(f_period, dev->timeperframe_vid_cap.denominator); 667dacca5f0SHans Verkuil if (dev->field_cap == V4L2_FIELD_ALTERNATE) 668dacca5f0SHans Verkuil f_period >>= 1; 669dacca5f0SHans Verkuil /* 670dacca5f0SHans Verkuil * If "End of Frame", then offset the exposure time by 0.9 671dacca5f0SHans Verkuil * of the frame period. 672dacca5f0SHans Verkuil */ 673dacca5f0SHans Verkuil dev->cap_frame_eof_offset = f_period * 9; 674dacca5f0SHans Verkuil do_div(dev->cap_frame_eof_offset, 10); 675dacca5f0SHans Verkuil dev->cap_frame_period = f_period; 676dacca5f0SHans Verkuil } 677dacca5f0SHans Verkuil 678dacca5f0SHans Verkuil static noinline_for_stack void vivid_thread_vid_cap_tick(struct vivid_dev *dev, 679dacca5f0SHans Verkuil int dropped_bufs) 680dacca5f0SHans Verkuil { 681dacca5f0SHans Verkuil struct vivid_buffer *vid_cap_buf = NULL; 682dacca5f0SHans Verkuil struct vivid_buffer *vbi_cap_buf = NULL; 683dacca5f0SHans Verkuil struct vivid_buffer *meta_cap_buf = NULL; 684dacca5f0SHans Verkuil u64 f_time = 0; 685dacca5f0SHans Verkuil 686dacca5f0SHans Verkuil dprintk(dev, 1, "Video Capture Thread Tick\n"); 687dacca5f0SHans Verkuil 688dacca5f0SHans Verkuil while (dropped_bufs-- > 1) 689dacca5f0SHans Verkuil tpg_update_mv_count(&dev->tpg, 690dacca5f0SHans Verkuil dev->field_cap == V4L2_FIELD_NONE || 691dacca5f0SHans Verkuil dev->field_cap == V4L2_FIELD_ALTERNATE); 692dacca5f0SHans Verkuil 693dacca5f0SHans Verkuil /* Drop a certain percentage of buffers. */ 694dacca5f0SHans Verkuil if (dev->perc_dropped_buffers && 695dacca5f0SHans Verkuil prandom_u32_max(100) < dev->perc_dropped_buffers) 696dacca5f0SHans Verkuil goto update_mv; 697dacca5f0SHans Verkuil 698dacca5f0SHans Verkuil spin_lock(&dev->slock); 699dacca5f0SHans Verkuil if (!list_empty(&dev->vid_cap_active)) { 700dacca5f0SHans Verkuil vid_cap_buf = list_entry(dev->vid_cap_active.next, struct vivid_buffer, list); 701dacca5f0SHans Verkuil list_del(&vid_cap_buf->list); 702dacca5f0SHans Verkuil } 703dacca5f0SHans Verkuil if (!list_empty(&dev->vbi_cap_active)) { 704dacca5f0SHans Verkuil if (dev->field_cap != V4L2_FIELD_ALTERNATE || 705dacca5f0SHans Verkuil (dev->vbi_cap_seq_count & 1)) { 706dacca5f0SHans Verkuil vbi_cap_buf = list_entry(dev->vbi_cap_active.next, 707dacca5f0SHans Verkuil struct vivid_buffer, list); 708dacca5f0SHans Verkuil list_del(&vbi_cap_buf->list); 709dacca5f0SHans Verkuil } 710dacca5f0SHans Verkuil } 711dacca5f0SHans Verkuil if (!list_empty(&dev->meta_cap_active)) { 712dacca5f0SHans Verkuil meta_cap_buf = list_entry(dev->meta_cap_active.next, 713dacca5f0SHans Verkuil struct vivid_buffer, list); 714dacca5f0SHans Verkuil list_del(&meta_cap_buf->list); 715dacca5f0SHans Verkuil } 716dacca5f0SHans Verkuil 717dacca5f0SHans Verkuil spin_unlock(&dev->slock); 718dacca5f0SHans Verkuil 719dacca5f0SHans Verkuil if (!vid_cap_buf && !vbi_cap_buf && !meta_cap_buf) 720dacca5f0SHans Verkuil goto update_mv; 721dacca5f0SHans Verkuil 722dacca5f0SHans Verkuil f_time = dev->cap_frame_period * dev->vid_cap_seq_count + 723dacca5f0SHans Verkuil dev->cap_stream_start + dev->time_wrap_offset; 724dacca5f0SHans Verkuil 725dacca5f0SHans Verkuil if (vid_cap_buf) { 726dacca5f0SHans Verkuil v4l2_ctrl_request_setup(vid_cap_buf->vb.vb2_buf.req_obj.req, 727dacca5f0SHans Verkuil &dev->ctrl_hdl_vid_cap); 728dacca5f0SHans Verkuil /* Fill buffer */ 729dacca5f0SHans Verkuil vivid_fillbuff(dev, vid_cap_buf); 730dacca5f0SHans Verkuil dprintk(dev, 1, "filled buffer %d\n", 731dacca5f0SHans Verkuil vid_cap_buf->vb.vb2_buf.index); 732dacca5f0SHans Verkuil 733dacca5f0SHans Verkuil /* Handle overlay */ 734dacca5f0SHans Verkuil if (dev->overlay_cap_owner && dev->fb_cap.base && 735dacca5f0SHans Verkuil dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc) 736dacca5f0SHans Verkuil vivid_overlay(dev, vid_cap_buf); 737dacca5f0SHans Verkuil 738dacca5f0SHans Verkuil v4l2_ctrl_request_complete(vid_cap_buf->vb.vb2_buf.req_obj.req, 739dacca5f0SHans Verkuil &dev->ctrl_hdl_vid_cap); 740dacca5f0SHans Verkuil vb2_buffer_done(&vid_cap_buf->vb.vb2_buf, dev->dqbuf_error ? 741dacca5f0SHans Verkuil VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); 742dacca5f0SHans Verkuil dprintk(dev, 2, "vid_cap buffer %d done\n", 743dacca5f0SHans Verkuil vid_cap_buf->vb.vb2_buf.index); 744dacca5f0SHans Verkuil 745dacca5f0SHans Verkuil vid_cap_buf->vb.vb2_buf.timestamp = f_time; 746dacca5f0SHans Verkuil if (!dev->tstamp_src_is_soe) 747dacca5f0SHans Verkuil vid_cap_buf->vb.vb2_buf.timestamp += dev->cap_frame_eof_offset; 748dacca5f0SHans Verkuil } 749dacca5f0SHans Verkuil 750dacca5f0SHans Verkuil if (vbi_cap_buf) { 751dacca5f0SHans Verkuil u64 vbi_period; 752dacca5f0SHans Verkuil 753dacca5f0SHans Verkuil v4l2_ctrl_request_setup(vbi_cap_buf->vb.vb2_buf.req_obj.req, 754dacca5f0SHans Verkuil &dev->ctrl_hdl_vbi_cap); 755*2d8b2a64STomi Valkeinen if (vbi_cap_buf->vb.vb2_buf.type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) 756dacca5f0SHans Verkuil vivid_sliced_vbi_cap_process(dev, vbi_cap_buf); 757dacca5f0SHans Verkuil else 758dacca5f0SHans Verkuil vivid_raw_vbi_cap_process(dev, vbi_cap_buf); 759dacca5f0SHans Verkuil v4l2_ctrl_request_complete(vbi_cap_buf->vb.vb2_buf.req_obj.req, 760dacca5f0SHans Verkuil &dev->ctrl_hdl_vbi_cap); 761dacca5f0SHans Verkuil vb2_buffer_done(&vbi_cap_buf->vb.vb2_buf, dev->dqbuf_error ? 762dacca5f0SHans Verkuil VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); 763dacca5f0SHans Verkuil dprintk(dev, 2, "vbi_cap %d done\n", 764dacca5f0SHans Verkuil vbi_cap_buf->vb.vb2_buf.index); 765dacca5f0SHans Verkuil 766dacca5f0SHans Verkuil /* If capturing a VBI, offset by 0.05 */ 767dacca5f0SHans Verkuil vbi_period = dev->cap_frame_period * 5; 768dacca5f0SHans Verkuil do_div(vbi_period, 100); 769dacca5f0SHans Verkuil vbi_cap_buf->vb.vb2_buf.timestamp = f_time + dev->cap_frame_eof_offset + vbi_period; 770dacca5f0SHans Verkuil } 771dacca5f0SHans Verkuil 772dacca5f0SHans Verkuil if (meta_cap_buf) { 773dacca5f0SHans Verkuil v4l2_ctrl_request_setup(meta_cap_buf->vb.vb2_buf.req_obj.req, 774dacca5f0SHans Verkuil &dev->ctrl_hdl_meta_cap); 775dacca5f0SHans Verkuil vivid_meta_cap_fillbuff(dev, meta_cap_buf, f_time); 776dacca5f0SHans Verkuil v4l2_ctrl_request_complete(meta_cap_buf->vb.vb2_buf.req_obj.req, 777dacca5f0SHans Verkuil &dev->ctrl_hdl_meta_cap); 778dacca5f0SHans Verkuil vb2_buffer_done(&meta_cap_buf->vb.vb2_buf, dev->dqbuf_error ? 779dacca5f0SHans Verkuil VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); 780dacca5f0SHans Verkuil dprintk(dev, 2, "meta_cap %d done\n", 781dacca5f0SHans Verkuil meta_cap_buf->vb.vb2_buf.index); 782dacca5f0SHans Verkuil meta_cap_buf->vb.vb2_buf.timestamp = f_time + dev->cap_frame_eof_offset; 783dacca5f0SHans Verkuil } 784dacca5f0SHans Verkuil 785dacca5f0SHans Verkuil dev->dqbuf_error = false; 786dacca5f0SHans Verkuil 787dacca5f0SHans Verkuil update_mv: 788dacca5f0SHans Verkuil /* Update the test pattern movement counters */ 789dacca5f0SHans Verkuil tpg_update_mv_count(&dev->tpg, dev->field_cap == V4L2_FIELD_NONE || 790dacca5f0SHans Verkuil dev->field_cap == V4L2_FIELD_ALTERNATE); 791dacca5f0SHans Verkuil } 792dacca5f0SHans Verkuil 793dacca5f0SHans Verkuil static int vivid_thread_vid_cap(void *data) 794dacca5f0SHans Verkuil { 795dacca5f0SHans Verkuil struct vivid_dev *dev = data; 796dacca5f0SHans Verkuil u64 numerators_since_start; 797dacca5f0SHans Verkuil u64 buffers_since_start; 798dacca5f0SHans Verkuil u64 next_jiffies_since_start; 799dacca5f0SHans Verkuil unsigned long jiffies_since_start; 800dacca5f0SHans Verkuil unsigned long cur_jiffies; 801dacca5f0SHans Verkuil unsigned wait_jiffies; 802dacca5f0SHans Verkuil unsigned numerator; 803dacca5f0SHans Verkuil unsigned denominator; 804dacca5f0SHans Verkuil int dropped_bufs; 805dacca5f0SHans Verkuil 806dacca5f0SHans Verkuil dprintk(dev, 1, "Video Capture Thread Start\n"); 807dacca5f0SHans Verkuil 808dacca5f0SHans Verkuil set_freezable(); 809dacca5f0SHans Verkuil 810dacca5f0SHans Verkuil /* Resets frame counters */ 811dacca5f0SHans Verkuil dev->cap_seq_offset = 0; 812dacca5f0SHans Verkuil dev->cap_seq_count = 0; 813dacca5f0SHans Verkuil dev->cap_seq_resync = false; 814dacca5f0SHans Verkuil dev->jiffies_vid_cap = jiffies; 815dacca5f0SHans Verkuil dev->cap_stream_start = ktime_get_ns(); 816dacca5f0SHans Verkuil vivid_cap_update_frame_period(dev); 817dacca5f0SHans Verkuil 818dacca5f0SHans Verkuil for (;;) { 819dacca5f0SHans Verkuil try_to_freeze(); 820dacca5f0SHans Verkuil if (kthread_should_stop()) 821dacca5f0SHans Verkuil break; 822dacca5f0SHans Verkuil 823dacca5f0SHans Verkuil if (!mutex_trylock(&dev->mutex)) { 8246e8c09bbSHans Verkuil schedule(); 825dacca5f0SHans Verkuil continue; 826dacca5f0SHans Verkuil } 827dacca5f0SHans Verkuil 828dacca5f0SHans Verkuil cur_jiffies = jiffies; 829dacca5f0SHans Verkuil if (dev->cap_seq_resync) { 830dacca5f0SHans Verkuil dev->jiffies_vid_cap = cur_jiffies; 831dacca5f0SHans Verkuil dev->cap_seq_offset = dev->cap_seq_count + 1; 832dacca5f0SHans Verkuil dev->cap_seq_count = 0; 833dacca5f0SHans Verkuil dev->cap_stream_start += dev->cap_frame_period * 834dacca5f0SHans Verkuil dev->cap_seq_offset; 835dacca5f0SHans Verkuil vivid_cap_update_frame_period(dev); 836dacca5f0SHans Verkuil dev->cap_seq_resync = false; 837dacca5f0SHans Verkuil } 838dacca5f0SHans Verkuil numerator = dev->timeperframe_vid_cap.numerator; 839dacca5f0SHans Verkuil denominator = dev->timeperframe_vid_cap.denominator; 840dacca5f0SHans Verkuil 841dacca5f0SHans Verkuil if (dev->field_cap == V4L2_FIELD_ALTERNATE) 842dacca5f0SHans Verkuil denominator *= 2; 843dacca5f0SHans Verkuil 844dacca5f0SHans Verkuil /* Calculate the number of jiffies since we started streaming */ 845dacca5f0SHans Verkuil jiffies_since_start = cur_jiffies - dev->jiffies_vid_cap; 846dacca5f0SHans Verkuil /* Get the number of buffers streamed since the start */ 847dacca5f0SHans Verkuil buffers_since_start = (u64)jiffies_since_start * denominator + 848dacca5f0SHans Verkuil (HZ * numerator) / 2; 849dacca5f0SHans Verkuil do_div(buffers_since_start, HZ * numerator); 850dacca5f0SHans Verkuil 851dacca5f0SHans Verkuil /* 852dacca5f0SHans Verkuil * After more than 0xf0000000 (rounded down to a multiple of 853dacca5f0SHans Verkuil * 'jiffies-per-day' to ease jiffies_to_msecs calculation) 854dacca5f0SHans Verkuil * jiffies have passed since we started streaming reset the 855dacca5f0SHans Verkuil * counters and keep track of the sequence offset. 856dacca5f0SHans Verkuil */ 857dacca5f0SHans Verkuil if (jiffies_since_start > JIFFIES_RESYNC) { 858dacca5f0SHans Verkuil dev->jiffies_vid_cap = cur_jiffies; 859dacca5f0SHans Verkuil dev->cap_seq_offset = buffers_since_start; 860dacca5f0SHans Verkuil buffers_since_start = 0; 861dacca5f0SHans Verkuil } 862dacca5f0SHans Verkuil dropped_bufs = buffers_since_start + dev->cap_seq_offset - dev->cap_seq_count; 863dacca5f0SHans Verkuil dev->cap_seq_count = buffers_since_start + dev->cap_seq_offset; 864dacca5f0SHans Verkuil dev->vid_cap_seq_count = dev->cap_seq_count - dev->vid_cap_seq_start; 865dacca5f0SHans Verkuil dev->vbi_cap_seq_count = dev->cap_seq_count - dev->vbi_cap_seq_start; 866dacca5f0SHans Verkuil dev->meta_cap_seq_count = dev->cap_seq_count - dev->meta_cap_seq_start; 867dacca5f0SHans Verkuil 868dacca5f0SHans Verkuil vivid_thread_vid_cap_tick(dev, dropped_bufs); 869dacca5f0SHans Verkuil 870dacca5f0SHans Verkuil /* 871dacca5f0SHans Verkuil * Calculate the number of 'numerators' streamed since we started, 872dacca5f0SHans Verkuil * including the current buffer. 873dacca5f0SHans Verkuil */ 874dacca5f0SHans Verkuil numerators_since_start = ++buffers_since_start * numerator; 875dacca5f0SHans Verkuil 876dacca5f0SHans Verkuil /* And the number of jiffies since we started */ 877dacca5f0SHans Verkuil jiffies_since_start = jiffies - dev->jiffies_vid_cap; 878dacca5f0SHans Verkuil 879dacca5f0SHans Verkuil mutex_unlock(&dev->mutex); 880dacca5f0SHans Verkuil 881dacca5f0SHans Verkuil /* 882dacca5f0SHans Verkuil * Calculate when that next buffer is supposed to start 883dacca5f0SHans Verkuil * in jiffies since we started streaming. 884dacca5f0SHans Verkuil */ 885dacca5f0SHans Verkuil next_jiffies_since_start = numerators_since_start * HZ + 886dacca5f0SHans Verkuil denominator / 2; 887dacca5f0SHans Verkuil do_div(next_jiffies_since_start, denominator); 888dacca5f0SHans Verkuil /* If it is in the past, then just schedule asap */ 889dacca5f0SHans Verkuil if (next_jiffies_since_start < jiffies_since_start) 890dacca5f0SHans Verkuil next_jiffies_since_start = jiffies_since_start; 891dacca5f0SHans Verkuil 892dacca5f0SHans Verkuil wait_jiffies = next_jiffies_since_start - jiffies_since_start; 8936e8c09bbSHans Verkuil while (jiffies - cur_jiffies < wait_jiffies && 8946e8c09bbSHans Verkuil !kthread_should_stop()) 8956e8c09bbSHans Verkuil schedule(); 896dacca5f0SHans Verkuil } 897dacca5f0SHans Verkuil dprintk(dev, 1, "Video Capture Thread End\n"); 898dacca5f0SHans Verkuil return 0; 899dacca5f0SHans Verkuil } 900dacca5f0SHans Verkuil 901dacca5f0SHans Verkuil static void vivid_grab_controls(struct vivid_dev *dev, bool grab) 902dacca5f0SHans Verkuil { 903dacca5f0SHans Verkuil v4l2_ctrl_grab(dev->ctrl_has_crop_cap, grab); 904dacca5f0SHans Verkuil v4l2_ctrl_grab(dev->ctrl_has_compose_cap, grab); 905dacca5f0SHans Verkuil v4l2_ctrl_grab(dev->ctrl_has_scaler_cap, grab); 906dacca5f0SHans Verkuil } 907dacca5f0SHans Verkuil 908dacca5f0SHans Verkuil int vivid_start_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming) 909dacca5f0SHans Verkuil { 910dacca5f0SHans Verkuil dprintk(dev, 1, "%s\n", __func__); 911dacca5f0SHans Verkuil 912dacca5f0SHans Verkuil if (dev->kthread_vid_cap) { 913dacca5f0SHans Verkuil u32 seq_count = dev->cap_seq_count + dev->seq_wrap * 128; 914dacca5f0SHans Verkuil 915dacca5f0SHans Verkuil if (pstreaming == &dev->vid_cap_streaming) 916dacca5f0SHans Verkuil dev->vid_cap_seq_start = seq_count; 917dacca5f0SHans Verkuil else if (pstreaming == &dev->vbi_cap_streaming) 918dacca5f0SHans Verkuil dev->vbi_cap_seq_start = seq_count; 919dacca5f0SHans Verkuil else 920dacca5f0SHans Verkuil dev->meta_cap_seq_start = seq_count; 921dacca5f0SHans Verkuil *pstreaming = true; 922dacca5f0SHans Verkuil return 0; 923dacca5f0SHans Verkuil } 924dacca5f0SHans Verkuil 925dacca5f0SHans Verkuil /* Resets frame counters */ 926dacca5f0SHans Verkuil tpg_init_mv_count(&dev->tpg); 927dacca5f0SHans Verkuil 928dacca5f0SHans Verkuil dev->vid_cap_seq_start = dev->seq_wrap * 128; 929dacca5f0SHans Verkuil dev->vbi_cap_seq_start = dev->seq_wrap * 128; 930dacca5f0SHans Verkuil dev->meta_cap_seq_start = dev->seq_wrap * 128; 931dacca5f0SHans Verkuil 932dacca5f0SHans Verkuil dev->kthread_vid_cap = kthread_run(vivid_thread_vid_cap, dev, 933dacca5f0SHans Verkuil "%s-vid-cap", dev->v4l2_dev.name); 934dacca5f0SHans Verkuil 935dacca5f0SHans Verkuil if (IS_ERR(dev->kthread_vid_cap)) { 936dacca5f0SHans Verkuil int err = PTR_ERR(dev->kthread_vid_cap); 937dacca5f0SHans Verkuil 938dacca5f0SHans Verkuil dev->kthread_vid_cap = NULL; 939dacca5f0SHans Verkuil v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); 940dacca5f0SHans Verkuil return err; 941dacca5f0SHans Verkuil } 942dacca5f0SHans Verkuil *pstreaming = true; 943dacca5f0SHans Verkuil vivid_grab_controls(dev, true); 944dacca5f0SHans Verkuil 945dacca5f0SHans Verkuil dprintk(dev, 1, "returning from %s\n", __func__); 946dacca5f0SHans Verkuil return 0; 947dacca5f0SHans Verkuil } 948dacca5f0SHans Verkuil 949dacca5f0SHans Verkuil void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming) 950dacca5f0SHans Verkuil { 951dacca5f0SHans Verkuil dprintk(dev, 1, "%s\n", __func__); 952dacca5f0SHans Verkuil 953dacca5f0SHans Verkuil if (dev->kthread_vid_cap == NULL) 954dacca5f0SHans Verkuil return; 955dacca5f0SHans Verkuil 956dacca5f0SHans Verkuil *pstreaming = false; 957dacca5f0SHans Verkuil if (pstreaming == &dev->vid_cap_streaming) { 958dacca5f0SHans Verkuil /* Release all active buffers */ 959dacca5f0SHans Verkuil while (!list_empty(&dev->vid_cap_active)) { 960dacca5f0SHans Verkuil struct vivid_buffer *buf; 961dacca5f0SHans Verkuil 962dacca5f0SHans Verkuil buf = list_entry(dev->vid_cap_active.next, 963dacca5f0SHans Verkuil struct vivid_buffer, list); 964dacca5f0SHans Verkuil list_del(&buf->list); 965dacca5f0SHans Verkuil v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req, 966dacca5f0SHans Verkuil &dev->ctrl_hdl_vid_cap); 967dacca5f0SHans Verkuil vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 968dacca5f0SHans Verkuil dprintk(dev, 2, "vid_cap buffer %d done\n", 969dacca5f0SHans Verkuil buf->vb.vb2_buf.index); 970dacca5f0SHans Verkuil } 971dacca5f0SHans Verkuil } 972dacca5f0SHans Verkuil 973dacca5f0SHans Verkuil if (pstreaming == &dev->vbi_cap_streaming) { 974dacca5f0SHans Verkuil while (!list_empty(&dev->vbi_cap_active)) { 975dacca5f0SHans Verkuil struct vivid_buffer *buf; 976dacca5f0SHans Verkuil 977dacca5f0SHans Verkuil buf = list_entry(dev->vbi_cap_active.next, 978dacca5f0SHans Verkuil struct vivid_buffer, list); 979dacca5f0SHans Verkuil list_del(&buf->list); 980dacca5f0SHans Verkuil v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req, 981dacca5f0SHans Verkuil &dev->ctrl_hdl_vbi_cap); 982dacca5f0SHans Verkuil vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 983dacca5f0SHans Verkuil dprintk(dev, 2, "vbi_cap buffer %d done\n", 984dacca5f0SHans Verkuil buf->vb.vb2_buf.index); 985dacca5f0SHans Verkuil } 986dacca5f0SHans Verkuil } 987dacca5f0SHans Verkuil 988dacca5f0SHans Verkuil if (pstreaming == &dev->meta_cap_streaming) { 989dacca5f0SHans Verkuil while (!list_empty(&dev->meta_cap_active)) { 990dacca5f0SHans Verkuil struct vivid_buffer *buf; 991dacca5f0SHans Verkuil 992dacca5f0SHans Verkuil buf = list_entry(dev->meta_cap_active.next, 993dacca5f0SHans Verkuil struct vivid_buffer, list); 994dacca5f0SHans Verkuil list_del(&buf->list); 995dacca5f0SHans Verkuil v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req, 996dacca5f0SHans Verkuil &dev->ctrl_hdl_meta_cap); 997dacca5f0SHans Verkuil vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 998dacca5f0SHans Verkuil dprintk(dev, 2, "meta_cap buffer %d done\n", 999dacca5f0SHans Verkuil buf->vb.vb2_buf.index); 1000dacca5f0SHans Verkuil } 1001dacca5f0SHans Verkuil } 1002dacca5f0SHans Verkuil 1003dacca5f0SHans Verkuil if (dev->vid_cap_streaming || dev->vbi_cap_streaming || 1004dacca5f0SHans Verkuil dev->meta_cap_streaming) 1005dacca5f0SHans Verkuil return; 1006dacca5f0SHans Verkuil 1007dacca5f0SHans Verkuil /* shutdown control thread */ 1008dacca5f0SHans Verkuil vivid_grab_controls(dev, false); 1009dacca5f0SHans Verkuil kthread_stop(dev->kthread_vid_cap); 1010dacca5f0SHans Verkuil dev->kthread_vid_cap = NULL; 1011dacca5f0SHans Verkuil } 1012