| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices |
|---|
| 3 | 4 | |
|---|
| 4 | 5 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> |
|---|
| 5 | 6 | Based on cx88 driver |
|---|
| 6 | 7 | |
|---|
| 7 | | - This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - (at your option) any later version. |
|---|
| 11 | | - |
|---|
| 12 | | - This program is distributed in the hope that it will be useful, |
|---|
| 13 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | | - GNU General Public License for more details. |
|---|
| 16 | | - |
|---|
| 17 | | - You should have received a copy of the GNU General Public License |
|---|
| 18 | | - along with this program; if not, write to the Free Software |
|---|
| 19 | | - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 20 | 8 | */ |
|---|
| 21 | 9 | |
|---|
| 22 | 10 | #include "cx231xx.h" |
|---|
| .. | .. |
|---|
| 165 | 153 | Vbi buf operations |
|---|
| 166 | 154 | ------------------------------------------------------------------*/ |
|---|
| 167 | 155 | |
|---|
| 168 | | -static int |
|---|
| 169 | | -vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, |
|---|
| 170 | | - unsigned int *size) |
|---|
| 156 | +static int vbi_queue_setup(struct vb2_queue *vq, |
|---|
| 157 | + unsigned int *nbuffers, unsigned int *nplanes, |
|---|
| 158 | + unsigned int sizes[], struct device *alloc_devs[]) |
|---|
| 171 | 159 | { |
|---|
| 172 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 173 | | - struct cx231xx *dev = fh->dev; |
|---|
| 160 | + struct cx231xx *dev = vb2_get_drv_priv(vq); |
|---|
| 174 | 161 | u32 height = 0; |
|---|
| 175 | 162 | |
|---|
| 176 | 163 | height = ((dev->norm & V4L2_STD_625_50) ? |
|---|
| 177 | 164 | PAL_VBI_LINES : NTSC_VBI_LINES); |
|---|
| 178 | 165 | |
|---|
| 179 | | - *size = (dev->width * height * 2 * 2); |
|---|
| 180 | | - if (0 == *count) |
|---|
| 181 | | - *count = CX231XX_DEF_VBI_BUF; |
|---|
| 182 | | - |
|---|
| 183 | | - if (*count < CX231XX_MIN_BUF) |
|---|
| 184 | | - *count = CX231XX_MIN_BUF; |
|---|
| 185 | | - |
|---|
| 166 | + *nplanes = 1; |
|---|
| 167 | + sizes[0] = (dev->width * height * 2 * 2); |
|---|
| 186 | 168 | return 0; |
|---|
| 187 | 169 | } |
|---|
| 188 | 170 | |
|---|
| 189 | 171 | /* This is called *without* dev->slock held; please keep it that way */ |
|---|
| 190 | | -static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) |
|---|
| 172 | +static int vbi_buf_prepare(struct vb2_buffer *vb) |
|---|
| 191 | 173 | { |
|---|
| 192 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 193 | | - struct cx231xx *dev = fh->dev; |
|---|
| 194 | | - unsigned long flags = 0; |
|---|
| 195 | | - BUG_ON(in_interrupt()); |
|---|
| 196 | | - |
|---|
| 197 | | - /* We used to wait for the buffer to finish here, but this didn't work |
|---|
| 198 | | - because, as we were keeping the state as VIDEOBUF_QUEUED, |
|---|
| 199 | | - videobuf_queue_cancel marked it as finished for us. |
|---|
| 200 | | - (Also, it could wedge forever if the hardware was misconfigured.) |
|---|
| 201 | | - |
|---|
| 202 | | - This should be safe; by the time we get here, the buffer isn't |
|---|
| 203 | | - queued anymore. If we ever start marking the buffers as |
|---|
| 204 | | - VIDEOBUF_ACTIVE, it won't be, though. |
|---|
| 205 | | - */ |
|---|
| 206 | | - spin_lock_irqsave(&dev->vbi_mode.slock, flags); |
|---|
| 207 | | - if (dev->vbi_mode.bulk_ctl.buf == buf) |
|---|
| 208 | | - dev->vbi_mode.bulk_ctl.buf = NULL; |
|---|
| 209 | | - spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); |
|---|
| 210 | | - |
|---|
| 211 | | - videobuf_vmalloc_free(&buf->vb); |
|---|
| 212 | | - buf->vb.state = VIDEOBUF_NEEDS_INIT; |
|---|
| 213 | | -} |
|---|
| 214 | | - |
|---|
| 215 | | -static int |
|---|
| 216 | | -vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, |
|---|
| 217 | | - enum v4l2_field field) |
|---|
| 218 | | -{ |
|---|
| 219 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 220 | | - struct cx231xx_buffer *buf = |
|---|
| 221 | | - container_of(vb, struct cx231xx_buffer, vb); |
|---|
| 222 | | - struct cx231xx *dev = fh->dev; |
|---|
| 223 | | - int rc = 0, urb_init = 0; |
|---|
| 174 | + struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue); |
|---|
| 224 | 175 | u32 height = 0; |
|---|
| 176 | + u32 size; |
|---|
| 225 | 177 | |
|---|
| 226 | 178 | height = ((dev->norm & V4L2_STD_625_50) ? |
|---|
| 227 | 179 | PAL_VBI_LINES : NTSC_VBI_LINES); |
|---|
| 228 | | - buf->vb.size = ((dev->width << 1) * height * 2); |
|---|
| 180 | + size = ((dev->width << 1) * height * 2); |
|---|
| 229 | 181 | |
|---|
| 230 | | - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
|---|
| 182 | + if (vb2_plane_size(vb, 0) < size) |
|---|
| 231 | 183 | return -EINVAL; |
|---|
| 232 | | - |
|---|
| 233 | | - buf->vb.width = dev->width; |
|---|
| 234 | | - buf->vb.height = height; |
|---|
| 235 | | - buf->vb.field = field; |
|---|
| 236 | | - buf->vb.field = V4L2_FIELD_SEQ_TB; |
|---|
| 237 | | - |
|---|
| 238 | | - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
|---|
| 239 | | - rc = videobuf_iolock(vq, &buf->vb, NULL); |
|---|
| 240 | | - if (rc < 0) |
|---|
| 241 | | - goto fail; |
|---|
| 242 | | - } |
|---|
| 243 | | - |
|---|
| 244 | | - if (!dev->vbi_mode.bulk_ctl.num_bufs) |
|---|
| 245 | | - urb_init = 1; |
|---|
| 246 | | - |
|---|
| 247 | | - if (urb_init) { |
|---|
| 248 | | - rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, |
|---|
| 249 | | - CX231XX_NUM_VBI_BUFS, |
|---|
| 250 | | - dev->vbi_mode.alt_max_pkt_size[0], |
|---|
| 251 | | - cx231xx_isoc_vbi_copy); |
|---|
| 252 | | - if (rc < 0) |
|---|
| 253 | | - goto fail; |
|---|
| 254 | | - } |
|---|
| 255 | | - |
|---|
| 256 | | - buf->vb.state = VIDEOBUF_PREPARED; |
|---|
| 184 | + vb2_set_plane_payload(vb, 0, size); |
|---|
| 257 | 185 | return 0; |
|---|
| 258 | | - |
|---|
| 259 | | -fail: |
|---|
| 260 | | - free_buffer(vq, buf); |
|---|
| 261 | | - return rc; |
|---|
| 262 | 186 | } |
|---|
| 263 | 187 | |
|---|
| 264 | | -static void |
|---|
| 265 | | -vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) |
|---|
| 188 | +static void vbi_buf_queue(struct vb2_buffer *vb) |
|---|
| 266 | 189 | { |
|---|
| 190 | + struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue); |
|---|
| 267 | 191 | struct cx231xx_buffer *buf = |
|---|
| 268 | | - container_of(vb, struct cx231xx_buffer, vb); |
|---|
| 269 | | - struct cx231xx_fh *fh = vq->priv_data; |
|---|
| 270 | | - struct cx231xx *dev = fh->dev; |
|---|
| 192 | + container_of(vb, struct cx231xx_buffer, vb.vb2_buf); |
|---|
| 271 | 193 | struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; |
|---|
| 194 | + unsigned long flags; |
|---|
| 272 | 195 | |
|---|
| 273 | | - buf->vb.state = VIDEOBUF_QUEUED; |
|---|
| 274 | | - list_add_tail(&buf->vb.queue, &vidq->active); |
|---|
| 275 | | - |
|---|
| 196 | + spin_lock_irqsave(&dev->vbi_mode.slock, flags); |
|---|
| 197 | + list_add_tail(&buf->list, &vidq->active); |
|---|
| 198 | + spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); |
|---|
| 276 | 199 | } |
|---|
| 277 | 200 | |
|---|
| 278 | | -static void vbi_buffer_release(struct videobuf_queue *vq, |
|---|
| 279 | | - struct videobuf_buffer *vb) |
|---|
| 201 | +static void return_all_buffers(struct cx231xx *dev, |
|---|
| 202 | + enum vb2_buffer_state state) |
|---|
| 280 | 203 | { |
|---|
| 281 | | - struct cx231xx_buffer *buf = |
|---|
| 282 | | - container_of(vb, struct cx231xx_buffer, vb); |
|---|
| 204 | + struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; |
|---|
| 205 | + struct cx231xx_buffer *buf, *node; |
|---|
| 206 | + unsigned long flags; |
|---|
| 283 | 207 | |
|---|
| 284 | | - |
|---|
| 285 | | - free_buffer(vq, buf); |
|---|
| 208 | + spin_lock_irqsave(&dev->vbi_mode.slock, flags); |
|---|
| 209 | + dev->vbi_mode.bulk_ctl.buf = NULL; |
|---|
| 210 | + list_for_each_entry_safe(buf, node, &vidq->active, list) { |
|---|
| 211 | + list_del(&buf->list); |
|---|
| 212 | + vb2_buffer_done(&buf->vb.vb2_buf, state); |
|---|
| 213 | + } |
|---|
| 214 | + spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); |
|---|
| 286 | 215 | } |
|---|
| 287 | 216 | |
|---|
| 288 | | -const struct videobuf_queue_ops cx231xx_vbi_qops = { |
|---|
| 289 | | - .buf_setup = vbi_buffer_setup, |
|---|
| 290 | | - .buf_prepare = vbi_buffer_prepare, |
|---|
| 291 | | - .buf_queue = vbi_buffer_queue, |
|---|
| 292 | | - .buf_release = vbi_buffer_release, |
|---|
| 217 | +static int vbi_start_streaming(struct vb2_queue *vq, unsigned int count) |
|---|
| 218 | +{ |
|---|
| 219 | + struct cx231xx *dev = vb2_get_drv_priv(vq); |
|---|
| 220 | + struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; |
|---|
| 221 | + int ret; |
|---|
| 222 | + |
|---|
| 223 | + vidq->sequence = 0; |
|---|
| 224 | + ret = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, |
|---|
| 225 | + CX231XX_NUM_VBI_BUFS, |
|---|
| 226 | + dev->vbi_mode.alt_max_pkt_size[0], |
|---|
| 227 | + cx231xx_isoc_vbi_copy); |
|---|
| 228 | + if (ret) |
|---|
| 229 | + return_all_buffers(dev, VB2_BUF_STATE_QUEUED); |
|---|
| 230 | + return ret; |
|---|
| 231 | +} |
|---|
| 232 | + |
|---|
| 233 | +static void vbi_stop_streaming(struct vb2_queue *vq) |
|---|
| 234 | +{ |
|---|
| 235 | + struct cx231xx *dev = vb2_get_drv_priv(vq); |
|---|
| 236 | + |
|---|
| 237 | + return_all_buffers(dev, VB2_BUF_STATE_ERROR); |
|---|
| 238 | +} |
|---|
| 239 | + |
|---|
| 240 | +struct vb2_ops cx231xx_vbi_qops = { |
|---|
| 241 | + .queue_setup = vbi_queue_setup, |
|---|
| 242 | + .buf_prepare = vbi_buf_prepare, |
|---|
| 243 | + .buf_queue = vbi_buf_queue, |
|---|
| 244 | + .start_streaming = vbi_start_streaming, |
|---|
| 245 | + .stop_streaming = vbi_stop_streaming, |
|---|
| 246 | + .wait_prepare = vb2_ops_wait_prepare, |
|---|
| 247 | + .wait_finish = vb2_ops_wait_finish, |
|---|
| 293 | 248 | }; |
|---|
| 294 | 249 | |
|---|
| 295 | 250 | /* ------------------------------------------------------------------ |
|---|
| .. | .. |
|---|
| 524 | 479 | struct cx231xx_buffer *buf) |
|---|
| 525 | 480 | { |
|---|
| 526 | 481 | /* Advice that buffer was filled */ |
|---|
| 527 | | - /* dev_dbg(dev->dev, "[%p/%d] wakeup\n", buf, buf->vb.i); */ |
|---|
| 482 | + /* dev_dbg(dev->dev, "[%p/%d] wakeup\n", buf, buf->vb.index); */ |
|---|
| 528 | 483 | |
|---|
| 529 | | - buf->vb.state = VIDEOBUF_DONE; |
|---|
| 530 | | - buf->vb.field_count++; |
|---|
| 531 | | - v4l2_get_timestamp(&buf->vb.ts); |
|---|
| 484 | + buf->vb.sequence = dma_q->sequence++; |
|---|
| 485 | + buf->vb.vb2_buf.timestamp = ktime_get_ns(); |
|---|
| 532 | 486 | |
|---|
| 533 | 487 | dev->vbi_mode.bulk_ctl.buf = NULL; |
|---|
| 534 | 488 | |
|---|
| 535 | | - list_del(&buf->vb.queue); |
|---|
| 536 | | - wake_up(&buf->vb.done); |
|---|
| 489 | + list_del(&buf->list); |
|---|
| 490 | + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); |
|---|
| 537 | 491 | } |
|---|
| 538 | 492 | |
|---|
| 539 | 493 | u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, |
|---|
| .. | .. |
|---|
| 623 | 577 | } |
|---|
| 624 | 578 | |
|---|
| 625 | 579 | /* Get the next buffer */ |
|---|
| 626 | | - *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); |
|---|
| 580 | + *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list); |
|---|
| 627 | 581 | |
|---|
| 628 | 582 | /* Cleans up buffer - Useful for testing for frame/URB loss */ |
|---|
| 629 | | - outp = videobuf_to_vmalloc(&(*buf)->vb); |
|---|
| 630 | | - memset(outp, 0, (*buf)->vb.size); |
|---|
| 583 | + outp = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0); |
|---|
| 584 | + memset(outp, 0, vb2_plane_size(&(*buf)->vb.vb2_buf, 0)); |
|---|
| 631 | 585 | |
|---|
| 632 | 586 | dev->vbi_mode.bulk_ctl.buf = *buf; |
|---|
| 633 | 587 | |
|---|
| .. | .. |
|---|
| 668 | 622 | if (buf == NULL) |
|---|
| 669 | 623 | return -EINVAL; |
|---|
| 670 | 624 | |
|---|
| 671 | | - p_out_buffer = videobuf_to_vmalloc(&buf->vb); |
|---|
| 625 | + p_out_buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); |
|---|
| 672 | 626 | |
|---|
| 673 | 627 | if (dma_q->bytes_left_in_line != _line_size) { |
|---|
| 674 | 628 | current_line_bytes_copied = |
|---|