From patchwork Wed Feb 1 16:11:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 649507 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34B41C38142 for ; Wed, 1 Feb 2023 16:12:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232695AbjBAQMF (ORCPT ); Wed, 1 Feb 2023 11:12:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47998 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230301AbjBAQMA (ORCPT ); Wed, 1 Feb 2023 11:12:00 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7438A14497 for ; Wed, 1 Feb 2023 08:11:59 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 28AA5B821C6 for ; Wed, 1 Feb 2023 16:11:58 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 175ABC433D2; Wed, 1 Feb 2023 16:11:55 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Andy Walls , Hans Verkuil Subject: [PATCH 1/8] vb2: set owner before calling vb2_read Date: Wed, 1 Feb 2023 17:11:46 +0100 Message-Id: <20230201161153.883376-2-hverkuil-cisco@xs4all.nl> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> References: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil Before vb2_read is called, the owner must be set since vb2_read will actually start streaming. If vb2_read returns an error and q->fileio is NULL, then it failed to start streaming and the owner is set back to NULL. When the vb2 start_streaming callback is called, it expects the owner pointer to be set, and that wasn't the case in this particular situation. Signed-off-by: Hans Verkuil --- drivers/media/common/videobuf2/videobuf2-v4l2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 1f5d235a8441..c7a54d82a55e 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -1171,10 +1171,11 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf, return -ERESTARTSYS; if (vb2_queue_is_busy(vdev->queue, file)) goto exit; + vdev->queue->owner = file->private_data; err = vb2_read(vdev->queue, buf, count, ppos, file->f_flags & O_NONBLOCK); - if (vdev->queue->fileio) - vdev->queue->owner = file->private_data; + if (!vdev->queue->fileio) + vdev->queue->owner = NULL; exit: if (lock) mutex_unlock(lock); From patchwork Wed Feb 1 16:11:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 650766 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 946D4C05027 for ; Wed, 1 Feb 2023 16:12:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232280AbjBAQMC (ORCPT ); Wed, 1 Feb 2023 11:12:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47996 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230200AbjBAQMA (ORCPT ); Wed, 1 Feb 2023 11:12:00 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F289F6A735 for ; Wed, 1 Feb 2023 08:11:58 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 9022D6185D for ; Wed, 1 Feb 2023 16:11:58 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 413AEC433EF; Wed, 1 Feb 2023 16:11:57 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Andy Walls , Hans Verkuil Subject: [PATCH 2/8] v4l2-dev.c: check for V4L2_CAP_STREAMING to enable streaming ioctls Date: Wed, 1 Feb 2023 17:11:47 +0100 Message-Id: <20230201161153.883376-3-hverkuil-cisco@xs4all.nl> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> References: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil Rather than checking which device type it is, just check the STREAMING cap since that indicates support for streaming ioctls. Some drivers only support READWRITE (typically MPEG encoders). Signed-off-by: Hans Verkuil --- drivers/media/v4l2-core/v4l2-dev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 397d553177fa..f81279492682 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -556,6 +556,7 @@ static void determine_valid_ioctls(struct video_device *vdev) bool is_rx = vdev->vfl_dir != VFL_DIR_TX; bool is_tx = vdev->vfl_dir != VFL_DIR_RX; bool is_io_mc = vdev->device_caps & V4L2_CAP_IO_MC; + bool has_streaming = vdev->device_caps & V4L2_CAP_STREAMING; bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE); @@ -708,8 +709,8 @@ static void determine_valid_ioctls(struct video_device *vdev) SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_sdr_out); } - if (is_vid || is_vbi || is_sdr || is_tch || is_meta) { - /* ioctls valid for video, vbi, sdr, touch and metadata */ + if (has_streaming) { + /* ioctls valid for streaming I/O */ SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs); SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf); SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf); From patchwork Wed Feb 1 16:11:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 649505 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96132C64EC3 for ; Wed, 1 Feb 2023 16:12:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232833AbjBAQMI (ORCPT ); Wed, 1 Feb 2023 11:12:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232659AbjBAQMF (ORCPT ); Wed, 1 Feb 2023 11:12:05 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 405967640A for ; Wed, 1 Feb 2023 08:12:02 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id AC725B821CA for ; Wed, 1 Feb 2023 16:12:00 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6CBFAC4339B; Wed, 1 Feb 2023 16:11:58 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Andy Walls , Hans Verkuil Subject: [PATCH 3/8] cx18: convert to vb2 Date: Wed, 1 Feb 2023 17:11:48 +0100 Message-Id: <20230201161153.883376-4-hverkuil-cisco@xs4all.nl> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> References: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil This patch converts cx18 from the old deprecated videobuf framework to the 'new' vb2 framework. Signed-off-by: Hans Verkuil --- drivers/media/pci/cx18/Kconfig | 2 +- drivers/media/pci/cx18/cx18-driver.h | 25 +-- drivers/media/pci/cx18/cx18-fileops.c | 85 ++------ drivers/media/pci/cx18/cx18-fileops.h | 3 +- drivers/media/pci/cx18/cx18-ioctl.c | 128 +----------- drivers/media/pci/cx18/cx18-mailbox.c | 27 +-- drivers/media/pci/cx18/cx18-streams.c | 273 +++++++++++++------------- 7 files changed, 197 insertions(+), 346 deletions(-) diff --git a/drivers/media/pci/cx18/Kconfig b/drivers/media/pci/cx18/Kconfig index a4e32fdcfd3d..5c959bb5e233 100644 --- a/drivers/media/pci/cx18/Kconfig +++ b/drivers/media/pci/cx18/Kconfig @@ -3,7 +3,7 @@ config VIDEO_CX18 tristate "Conexant cx23418 MPEG encoder support" depends on VIDEO_DEV && DVB_CORE && PCI && I2C select I2C_ALGOBIT - select VIDEOBUF_VMALLOC + select VIDEOBUF2_VMALLOC depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h index ef545b96121d..a40d830329f7 100644 --- a/drivers/media/pci/cx18/cx18-driver.h +++ b/drivers/media/pci/cx18/cx18-driver.h @@ -48,9 +48,8 @@ #include #include -/* Videobuf / YUV support */ -#include -#include +/* vb2 YUV support */ +#include #ifndef CONFIG_PCI # error "This driver requires kernel PCI support." @@ -284,6 +283,15 @@ struct cx18_options { #define list_entry_is_past_end(pos, head, member) \ (&pos->member == (head)) + +struct cx18_vb2_buffer { + /* Common video buffer sub-system struct */ + struct vb2_v4l2_buffer vb; + struct list_head list; + v4l2_std_id tvnorm; /* selected tv norm */ + u32 bytes_used; +}; + struct cx18_buffer { struct list_head list; dma_addr_t dma_handle; @@ -399,19 +407,12 @@ struct cx18_stream { struct list_head vb_capture; /* video capture queue */ spinlock_t vb_lock; struct timer_list vb_timeout; + u32 sequence; - struct videobuf_queue vbuf_q; - spinlock_t vbuf_q_lock; /* Protect vbuf_q */ + struct vb2_queue vidq; enum v4l2_buf_type vb_type; }; -struct cx18_videobuf_buffer { - /* Common video buffer sub-system struct */ - struct videobuf_buffer vb; - v4l2_std_id tvnorm; /* selected tv norm */ - u32 bytes_used; -}; - struct cx18_open_id { struct v4l2_fh fh; u32 open_id; diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c index 4cf5b9ca92e7..7e742733391b 100644 --- a/drivers/media/pci/cx18/cx18-fileops.c +++ b/drivers/media/pci/cx18/cx18-fileops.c @@ -584,12 +584,6 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count, if (rc) return rc; - if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->type == CX18_ENC_STREAM_TYPE_YUV)) { - return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); } @@ -618,17 +612,6 @@ __poll_t cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) CX18_DEBUG_FILE("Encoder poll started capture\n"); } - if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->type == CX18_ENC_STREAM_TYPE_YUV)) { - __poll_t videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait); - - if (v4l2_event_pending(&id->fh)) - res |= EPOLLPRI; - if (eof && videobuf_poll == EPOLLERR) - return res | EPOLLHUP; - return res | videobuf_poll; - } - /* add stream's waitq to the poll list */ CX18_DEBUG_HI_FILE("Encoder poll\n"); if (v4l2_event_pending(&id->fh)) @@ -643,62 +626,20 @@ __poll_t cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) return res; } -int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct cx18_open_id *id = file->private_data; - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags); - - if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (id->type == CX18_ENC_STREAM_TYPE_YUV)) { - - /* Start a capture if there is none */ - if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) { - int rc; - - mutex_lock(&cx->serialize_lock); - rc = cx18_start_capture(id); - mutex_unlock(&cx->serialize_lock); - if (rc) { - CX18_DEBUG_INFO( - "Could not start capture for %s (%d)\n", - s->name, rc); - return -EINVAL; - } - CX18_DEBUG_FILE("Encoder mmap started capture\n"); - } - - return videobuf_mmap_mapper(&s->vbuf_q, vma); - } - - return -EINVAL; -} - void cx18_vb_timeout(struct timer_list *t) { struct cx18_stream *s = from_timer(s, t, vb_timeout); - struct cx18_videobuf_buffer *buf; - unsigned long flags; - /* Return all of the buffers in error state, so the vbi/vid inode + /* + * Return all of the buffers in error state, so the vbi/vid inode * can return from blocking. */ - spin_lock_irqsave(&s->vb_lock, flags); - while (!list_empty(&s->vb_capture)) { - buf = list_entry(s->vb_capture.next, - struct cx18_videobuf_buffer, vb.queue); - list_del(&buf->vb.queue); - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - } - spin_unlock_irqrestore(&s->vb_lock, flags); + cx18_clear_queue(s, VB2_BUF_STATE_ERROR); } -void cx18_stop_capture(struct cx18_open_id *id, int gop_end) +void cx18_stop_capture(struct cx18_stream *s, int gop_end) { - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; + struct cx18 *cx = s->cx; struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; @@ -709,7 +650,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) /* Stop capturing */ if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { CX18_DEBUG_INFO("close stopping capture\n"); - if (id->type == CX18_ENC_STREAM_TYPE_MPG) { + if (s->type == CX18_ENC_STREAM_TYPE_MPG) { /* Stop internal use associated VBI and IDX streams */ if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { @@ -721,7 +662,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) cx18_stop_v4l2_encode_stream(s_idx, 0); } } - if (id->type == CX18_ENC_STREAM_TYPE_VBI && + if (s->type == CX18_ENC_STREAM_TYPE_VBI && test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) /* Also used internally, don't stop capturing */ s->id = -1; @@ -741,13 +682,14 @@ int cx18_v4l2_close(struct file *filp) struct cx18_open_id *id = fh2id(fh); struct cx18 *cx = id->cx; struct cx18_stream *s = &cx->streams[id->type]; + struct video_device *vdev = &s->video_dev; CX18_DEBUG_IOCTL("close() of %s\n", s->name); mutex_lock(&cx->serialize_lock); /* Stop radio */ if (id->type == CX18_ENC_STREAM_TYPE_RAD && - v4l2_fh_is_singular_file(filp)) { + v4l2_fh_is_singular_file(filp)) { /* Closing radio device, return to TV mode */ cx18_mute(cx); /* Mark that the radio is no longer in use */ @@ -766,12 +708,17 @@ int cx18_v4l2_close(struct file *filp) cx18_unmute(cx); } + if (id->type == CX18_ENC_STREAM_TYPE_YUV && + filp->private_data == vdev->queue->owner) { + vb2_queue_release(vdev->queue); + vdev->queue->owner = NULL; + } v4l2_fh_del(fh); v4l2_fh_exit(fh); /* 'Unclaim' this stream */ - if (s->id == id->open_id) - cx18_stop_capture(id, 0); + if (id->type != CX18_ENC_STREAM_TYPE_YUV && s->id == id->open_id) + cx18_stop_capture(s, 0); kfree(id); mutex_unlock(&cx->serialize_lock); return 0; diff --git a/drivers/media/pci/cx18/cx18-fileops.h b/drivers/media/pci/cx18/cx18-fileops.h index 1985d6422347..943057b83d94 100644 --- a/drivers/media/pci/cx18/cx18-fileops.h +++ b/drivers/media/pci/cx18/cx18-fileops.h @@ -16,10 +16,11 @@ ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count, int cx18_v4l2_close(struct file *filp); __poll_t cx18_v4l2_enc_poll(struct file *filp, poll_table *wait); int cx18_start_capture(struct cx18_open_id *id); -void cx18_stop_capture(struct cx18_open_id *id, int gop_end); +void cx18_stop_capture(struct cx18_stream *s, int gop_end); void cx18_mute(struct cx18 *cx); void cx18_unmute(struct cx18 *cx); int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma); +void cx18_clear_queue(struct cx18_stream *s, enum vb2_buffer_state state); void cx18_vb_timeout(struct timer_list *t); /* Shared with cx18-alsa module */ diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index c8ba7841c720..af6e72ffe4b7 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -803,117 +803,6 @@ static int cx18_g_enc_index(struct file *file, void *fh, return 0; } -static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id) -{ - struct videobuf_queue *q = NULL; - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - - switch (s->vb_type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - q = &s->vbuf_q; - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - break; - default: - break; - } - return q; -} - -static int cx18_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct cx18_open_id *id = file->private_data; - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - - /* Start the hardware only if we're the video device */ - if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - if (id->type != CX18_ENC_STREAM_TYPE_YUV) - return -EINVAL; - - /* Establish a buffer timeout */ - mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies); - - return videobuf_streamon(cx18_vb_queue(id)); -} - -static int cx18_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct cx18_open_id *id = file->private_data; - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - - /* Start the hardware only if we're the video device */ - if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - if (id->type != CX18_ENC_STREAM_TYPE_YUV) - return -EINVAL; - - return videobuf_streamoff(cx18_vb_queue(id)); -} - -static int cx18_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct cx18_open_id *id = file->private_data; - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - - if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - return videobuf_reqbufs(cx18_vb_queue(id), rb); -} - -static int cx18_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct cx18_open_id *id = file->private_data; - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - - if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - return videobuf_querybuf(cx18_vb_queue(id), b); -} - -static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx18_open_id *id = file->private_data; - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - - if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - return videobuf_qbuf(cx18_vb_queue(id), b); -} - -static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx18_open_id *id = file->private_data; - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - - if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK); -} - static int cx18_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) { @@ -930,7 +819,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh, case V4L2_ENC_CMD_STOP: CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; - cx18_stop_capture(id, + cx18_stop_capture(&cx->streams[id->type], enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END); break; @@ -1106,12 +995,15 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = { .vidioc_s_register = cx18_s_register, #endif .vidioc_default = cx18_default, - .vidioc_streamon = cx18_streamon, - .vidioc_streamoff = cx18_streamoff, - .vidioc_reqbufs = cx18_reqbufs, - .vidioc_querybuf = cx18_querybuf, - .vidioc_qbuf = cx18_qbuf, - .vidioc_dqbuf = cx18_dqbuf, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; diff --git a/drivers/media/pci/cx18/cx18-mailbox.c b/drivers/media/pci/cx18/cx18-mailbox.c index 162480ec68ca..3b283f3c6726 100644 --- a/drivers/media/pci/cx18/cx18-mailbox.c +++ b/drivers/media/pci/cx18/cx18-mailbox.c @@ -145,36 +145,37 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) } } -static void cx18_mdl_send_to_videobuf(struct cx18_stream *s, - struct cx18_mdl *mdl) +static void cx18_mdl_send_to_vb2(struct cx18_stream *s, struct cx18_mdl *mdl) { - struct cx18_videobuf_buffer *vb_buf; + struct cx18_vb2_buffer *vb_buf; struct cx18_buffer *buf; u8 *p; u32 offset = 0; int dispatch = 0; + unsigned long bsize; if (mdl->bytesused == 0) return; - /* Acquire a videobuf buffer, clone to and and release it */ + /* Acquire a vb2 buffer, clone to and release it */ spin_lock(&s->vb_lock); if (list_empty(&s->vb_capture)) goto out; - vb_buf = list_first_entry(&s->vb_capture, struct cx18_videobuf_buffer, - vb.queue); + vb_buf = list_first_entry(&s->vb_capture, struct cx18_vb2_buffer, + list); - p = videobuf_to_vmalloc(&vb_buf->vb); + p = vb2_plane_vaddr(&vb_buf->vb.vb2_buf, 0); if (!p) goto out; + bsize = vb2_get_plane_payload(&vb_buf->vb.vb2_buf, 0); offset = vb_buf->bytes_used; list_for_each_entry(buf, &mdl->buf_list, list) { if (buf->bytesused == 0) break; - if ((offset + buf->bytesused) <= vb_buf->vb.bsize) { + if ((offset + buf->bytesused) <= bsize) { memcpy(p + offset, buf->buf, buf->bytesused); offset += buf->bytesused; vb_buf->bytes_used += buf->bytesused; @@ -188,10 +189,10 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s, } if (dispatch) { - vb_buf->vb.ts = ktime_get_ns(); - list_del(&vb_buf->vb.queue); - vb_buf->vb.state = VIDEOBUF_DONE; - wake_up(&vb_buf->vb.done); + vb_buf->vb.vb2_buf.timestamp = ktime_get_ns(); + vb_buf->vb.sequence = s->sequence++; + list_del(&vb_buf->list); + vb2_buffer_done(&vb_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); } mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies); @@ -304,7 +305,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) cx18_enqueue(s, mdl, &s->q_full); } } else if (s->type == CX18_ENC_STREAM_TYPE_YUV) { - cx18_mdl_send_to_videobuf(s, mdl); + cx18_mdl_send_to_vb2(s, mdl); cx18_enqueue(s, mdl, &s->q_free); } else { cx18_enqueue(s, mdl, &s->q_full); diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c index 87ff554bb2d2..240d58d36d4b 100644 --- a/drivers/media/pci/cx18/cx18-streams.c +++ b/drivers/media/pci/cx18/cx18-streams.c @@ -29,9 +29,19 @@ static const struct v4l2_file_operations cx18_v4l2_enc_fops = { .unlocked_ioctl = video_ioctl2, .release = cx18_v4l2_close, .poll = cx18_v4l2_enc_poll, - .mmap = cx18_v4l2_mmap, }; +static const struct v4l2_file_operations cx18_v4l2_enc_yuv_fops = { + .owner = THIS_MODULE, + .open = cx18_v4l2_open, + .unlocked_ioctl = video_ioctl2, + .release = cx18_v4l2_close, + .poll = vb2_fop_poll, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, +}; + + /* offset from 0 to register ts v4l2 minors on */ #define CX18_V4L2_ENC_TS_OFFSET 16 /* offset from 0 to register pcm v4l2 minors on */ @@ -91,156 +101,138 @@ static struct { }, }; - -static void cx18_dma_free(struct videobuf_queue *q, - struct cx18_stream *s, struct cx18_videobuf_buffer *buf) -{ - videobuf_waiton(q, &buf->vb, 0, 0); - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int cx18_prepare_buffer(struct videobuf_queue *q, - struct cx18_stream *s, - struct cx18_videobuf_buffer *buf, - u32 pixelformat, - unsigned int width, unsigned int height, - enum v4l2_field field) +static int cx18_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) { + struct cx18_stream *s = vb2_get_drv_priv(vq); struct cx18 *cx = s->cx; - int rc = 0; - - /* check settings */ - buf->bytes_used = 0; - - if ((width < 48) || (height < 32)) - return -EINVAL; + unsigned int szimage; - buf->vb.size = (width * height * 2); - if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size)) - return -EINVAL; - - /* alloc + fill struct (if changed) */ - if (buf->vb.width != width || buf->vb.height != height || - buf->vb.field != field || s->pixelformat != pixelformat || - buf->tvnorm != cx->std) { + /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) + UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ + if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) + szimage = cx->cxhdl.height * 720 * 3 / 2; + else + szimage = cx->cxhdl.height * 720 * 2; - buf->vb.width = width; - buf->vb.height = height; - buf->vb.field = field; - buf->tvnorm = cx->std; - s->pixelformat = pixelformat; + /* + * Let's request at least three buffers: two for the + * DMA engine and one for userspace. + */ + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; - /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) - UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ - if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) - s->vb_bytes_per_frame = height * 720 * 3 / 2; - else - s->vb_bytes_per_frame = height * 720 * 2; - cx18_dma_free(q, s, buf); + if (*nplanes) { + if (*nplanes != 1 || sizes[0] < szimage) + return -EINVAL; + return 0; } - if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size)) - return -EINVAL; - - if (buf->vb.field == 0) - buf->vb.field = V4L2_FIELD_INTERLACED; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - buf->vb.width = width; - buf->vb.height = height; - buf->vb.field = field; - buf->tvnorm = cx->std; - s->pixelformat = pixelformat; - - /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) - UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ - if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) - s->vb_bytes_per_frame = height * 720 * 3 / 2; - else - s->vb_bytes_per_frame = height * 720 * 2; - rc = videobuf_iolock(q, &buf->vb, NULL); - if (rc != 0) - goto fail; - } - buf->vb.state = VIDEOBUF_PREPARED; + sizes[0] = szimage; + *nplanes = 1; return 0; - -fail: - cx18_dma_free(q, s, buf); - return rc; - } -/* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576) - 1440 is a single line of 4:2:2 YUV at 720 luma samples wide -*/ -#define VB_MIN_BUFFERS 32 -#define VB_MIN_BUFSIZE 4147200 +static void cx18_buf_queue(struct vb2_buffer *vb) +{ + struct cx18_stream *s = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct cx18_vb2_buffer *buf = + container_of(vbuf, struct cx18_vb2_buffer, vb); + unsigned long flags; + + spin_lock_irqsave(&s->vb_lock, flags); + list_add_tail(&buf->list, &s->vb_capture); + spin_unlock_irqrestore(&s->vb_lock, flags); +} -static int buffer_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) +static int cx18_buf_prepare(struct vb2_buffer *vb) { - struct cx18_stream *s = q->priv_data; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct cx18_stream *s = vb2_get_drv_priv(vb->vb2_queue); struct cx18 *cx = s->cx; + unsigned int size; - *size = 2 * cx->cxhdl.width * cx->cxhdl.height; - if (*count == 0) - *count = VB_MIN_BUFFERS; - - while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE) - (*count)--; - - q->field = V4L2_FIELD_INTERLACED; - q->last = V4L2_FIELD_INTERLACED; + /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) + UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ + if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) + size = cx->cxhdl.height * 720 * 3 / 2; + else + size = cx->cxhdl.height * 720 * 2; + if (vb2_plane_size(vb, 0) < size) + return -EINVAL; + vb2_set_plane_payload(vb, 0, size); + vbuf->field = V4L2_FIELD_INTERLACED; return 0; } -static int buffer_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field) +void cx18_clear_queue(struct cx18_stream *s, enum vb2_buffer_state state) { - struct cx18_videobuf_buffer *buf = - container_of(vb, struct cx18_videobuf_buffer, vb); - struct cx18_stream *s = q->priv_data; - struct cx18 *cx = s->cx; + while (!list_empty(&s->vb_capture)) { + struct cx18_vb2_buffer *buf; - return cx18_prepare_buffer(q, s, buf, s->pixelformat, - cx->cxhdl.width, cx->cxhdl.height, field); + buf = list_first_entry(&s->vb_capture, + struct cx18_vb2_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, state); + } } -static void buffer_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static int cx18_start_streaming(struct vb2_queue *vq, unsigned int count) { - struct cx18_videobuf_buffer *buf = - container_of(vb, struct cx18_videobuf_buffer, vb); - struct cx18_stream *s = q->priv_data; + struct v4l2_fh *owner = vq->owner; + struct cx18_stream *s = vb2_get_drv_priv(vq); + unsigned long flags; + int rc; + + if (WARN_ON(!owner)) { + rc = -EIO; + goto clear_queue; + } + + s->sequence = 0; + rc = cx18_start_capture(fh2id(owner)); + if (!rc) { + /* Establish a buffer timeout */ + mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies); + return 0; + } - cx18_dma_free(q, s, buf); +clear_queue: + spin_lock_irqsave(&s->vb_lock, flags); + cx18_clear_queue(s, VB2_BUF_STATE_QUEUED); + spin_unlock_irqrestore(&s->vb_lock, flags); + return rc; } -static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) +static void cx18_stop_streaming(struct vb2_queue *vq) { - struct cx18_videobuf_buffer *buf = - container_of(vb, struct cx18_videobuf_buffer, vb); - struct cx18_stream *s = q->priv_data; - - buf->vb.state = VIDEOBUF_QUEUED; - - list_add_tail(&buf->vb.queue, &s->vb_capture); + struct cx18_stream *s = vb2_get_drv_priv(vq); + unsigned long flags; + + cx18_stop_capture(s, 0); + timer_delete_sync(&s->vb_timeout); + spin_lock_irqsave(&s->vb_lock, flags); + cx18_clear_queue(s, VB2_BUF_STATE_ERROR); + spin_unlock_irqrestore(&s->vb_lock, flags); } -static const struct videobuf_queue_ops cx18_videobuf_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, +static const struct vb2_ops cx18_vb2_qops = { + .queue_setup = cx18_queue_setup, + .buf_queue = cx18_buf_queue, + .buf_prepare = cx18_buf_prepare, + .start_streaming = cx18_start_streaming, + .stop_streaming = cx18_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; -static void cx18_stream_init(struct cx18 *cx, int type) +static int cx18_stream_init(struct cx18 *cx, int type) { struct cx18_stream *s = &cx->streams[type]; + int err = 0; memset(s, 0, sizeof(*s)); @@ -275,22 +267,33 @@ static void cx18_stream_init(struct cx18 *cx, int type) INIT_LIST_HEAD(&s->vb_capture); timer_setup(&s->vb_timeout, cx18_vb_timeout, 0); spin_lock_init(&s->vb_lock); - if (type == CX18_ENC_STREAM_TYPE_YUV) { - spin_lock_init(&s->vbuf_q_lock); + if (type == CX18_ENC_STREAM_TYPE_YUV) { s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops, - &cx->pci_dev->dev, &s->vbuf_q_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx18_videobuf_buffer), - s, &cx->serialize_lock); /* Assume the previous pixel default */ s->pixelformat = V4L2_PIX_FMT_NV12_16L16; s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2; s->vb_bytes_per_line = 720; + + s->vidq.io_modes = VB2_READ | VB2_MMAP | VB2_DMABUF; + s->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + s->vidq.drv_priv = s; + s->vidq.buf_struct_size = sizeof(struct cx18_vb2_buffer); + s->vidq.ops = &cx18_vb2_qops; + s->vidq.mem_ops = &vb2_vmalloc_memops; + s->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + s->vidq.min_buffers_needed = 2; + s->vidq.gfp_flags = GFP_DMA32; + s->vidq.dev = &cx->pci_dev->dev; + s->vidq.lock = &cx->serialize_lock; + + err = vb2_queue_init(&s->vidq); + if (err) + v4l2_err(&cx->v4l2_dev, "cannot init vb2 queue\n"); + s->video_dev.queue = &s->vidq; } + return err; } static int cx18_prep_dev(struct cx18 *cx, int type) @@ -299,6 +302,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) u32 cap = cx->v4l2_cap; int num_offset = cx18_stream_info[type].num_offset; int num = cx->instance + cx18_first_minor + num_offset; + int err; /* * These five fields are always initialized. @@ -330,7 +334,9 @@ static int cx18_prep_dev(struct cx18 *cx, int type) return 0; } - cx18_stream_init(cx, type); + err = cx18_stream_init(cx, type); + if (err) + return err; /* Allocate the cx18_dvb struct only for the TS on cards with DTV */ if (type == CX18_ENC_STREAM_TYPE_TS) { @@ -356,7 +362,10 @@ static int cx18_prep_dev(struct cx18 *cx, int type) s->video_dev.num = num; s->video_dev.v4l2_dev = &cx->v4l2_dev; - s->video_dev.fops = &cx18_v4l2_enc_fops; + if (type == CX18_ENC_STREAM_TYPE_YUV) + s->video_dev.fops = &cx18_v4l2_enc_yuv_fops; + else + s->video_dev.fops = &cx18_v4l2_enc_fops; s->video_dev.release = video_device_release_empty; if (cx->card->video_inputs->video_type == CX18_CARD_INPUT_VID_TUNER) s->video_dev.tvnorms = cx->tuner_std; @@ -525,12 +534,12 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) if (vdev->v4l2_dev == NULL) continue; - if (type == CX18_ENC_STREAM_TYPE_YUV) - videobuf_mmap_free(&cx->streams[type].vbuf_q); - cx18_stream_free(&cx->streams[type]); - video_unregister_device(vdev); + if (type == CX18_ENC_STREAM_TYPE_YUV) + vb2_video_unregister_device(vdev); + else + video_unregister_device(vdev); } } From patchwork Wed Feb 1 16:11:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 650765 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC779C05027 for ; Wed, 1 Feb 2023 16:12:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232110AbjBAQMG (ORCPT ); Wed, 1 Feb 2023 11:12:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47996 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232177AbjBAQMC (ORCPT ); Wed, 1 Feb 2023 11:12:02 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7AEE376405 for ; Wed, 1 Feb 2023 08:12:01 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 185166172E for ; Wed, 1 Feb 2023 16:12:01 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BF4B6C433D2; Wed, 1 Feb 2023 16:11:59 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Andy Walls , Hans Verkuil Subject: [PATCH 4/8] cx18: fix incorrect input counting Date: Wed, 1 Feb 2023 17:11:49 +0100 Message-Id: <20230201161153.883376-5-hverkuil-cisco@xs4all.nl> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> References: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil Counting the number of video and audio inputs was wrong if the number of inputs equalled CX18_CARD_MAX_VIDEO_INPUTS or CX18_CARD_MAX_AUDIO_INPUTS. This was a copy-and-paste from the ivtv driver. That driver has been fixed quite a long time ago, but we missed that this driver had the same bug. Signed-off-by: Hans Verkuil --- drivers/media/pci/cx18/cx18-driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 84260972c343..743fcc961374 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -771,11 +771,11 @@ static void cx18_init_struct2(struct cx18 *cx) { int i; - for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS - 1; i++) + for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++) if (cx->card->video_inputs[i].video_type == 0) break; cx->nof_inputs = i; - for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS - 1; i++) + for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++) if (cx->card->audio_inputs[i].audio_type == 0) break; cx->nof_audio_inputs = i; From patchwork Wed Feb 1 16:11:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 649506 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55E79C63797 for ; Wed, 1 Feb 2023 16:12:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232598AbjBAQMH (ORCPT ); Wed, 1 Feb 2023 11:12:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48136 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232297AbjBAQMD (ORCPT ); Wed, 1 Feb 2023 11:12:03 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9A874751AD for ; Wed, 1 Feb 2023 08:12:02 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 407B861706 for ; Wed, 1 Feb 2023 16:12:02 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E794CC4339C; Wed, 1 Feb 2023 16:12:00 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Andy Walls , Hans Verkuil Subject: [PATCH 5/8] cx18: properly report pixelformats Date: Wed, 1 Feb 2023 17:11:50 +0100 Message-Id: <20230201161153.883376-6-hverkuil-cisco@xs4all.nl> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> References: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil The MPEG device reported non-MPEG pixelformats, and the YUV device reported the MPEG pixelformat as well. Separate the two: either report MPEG or HM12/UYUV, not all three. Signed-off-by: Hans Verkuil --- drivers/media/pci/cx18/cx18-ioctl.c | 61 ++++++++++++++++++----------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index af6e72ffe4b7..549aa5e3c898 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -27,6 +27,28 @@ #include #include +static const struct v4l2_fmtdesc cx18_formats_yuv[] = { + { + .index = 0, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .pixelformat = V4L2_PIX_FMT_NV12_16L16, + }, + { + .index = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .pixelformat = V4L2_PIX_FMT_UYVY, + }, +}; + +static const struct v4l2_fmtdesc cx18_formats_mpeg[] = { + { + .index = 0, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .flags = V4L2_FMT_FLAG_COMPRESSED, + .pixelformat = V4L2_PIX_FMT_MPEG, + }, +}; + u16 cx18_service2vbi(int type) { switch (type) { @@ -210,11 +232,18 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, w = min(w, 720); w = max(w, 2); + if (id->type == CX18_ENC_STREAM_TYPE_YUV) { + if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12_16L16 && + fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) + fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV height must be a multiple of 32 */ h &= ~0x1f; min_h = 32; + } else { + fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; } + h = min(h, cx->is_50hz ? 576 : 480); h = max(h, min_h); @@ -463,31 +492,17 @@ static int cx18_g_selection(struct file *file, void *fh, static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) { - static const struct v4l2_fmtdesc formats[] = { - { - .index = 0, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "HM12 (YUV 4:1:1)", - .pixelformat = V4L2_PIX_FMT_NV12_16L16, - }, - { - .index = 1, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .flags = V4L2_FMT_FLAG_COMPRESSED, - .description = "MPEG", - .pixelformat = V4L2_PIX_FMT_MPEG, - }, - { - .index = 2, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "UYVY 4:2:2", - .pixelformat = V4L2_PIX_FMT_UYVY, - }, - }; + struct cx18_open_id *id = fh2id(fh); - if (fmt->index > ARRAY_SIZE(formats) - 1) + if (id->type == CX18_ENC_STREAM_TYPE_YUV) { + if (fmt->index >= ARRAY_SIZE(cx18_formats_yuv)) + return -EINVAL; + *fmt = cx18_formats_yuv[fmt->index]; + return 0; + } + if (fmt->index) return -EINVAL; - *fmt = formats[fmt->index]; + *fmt = cx18_formats_mpeg[0]; return 0; } From patchwork Wed Feb 1 16:11:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 650764 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 73843C6379F for ; Wed, 1 Feb 2023 16:12:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232792AbjBAQMI (ORCPT ); Wed, 1 Feb 2023 11:12:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232614AbjBAQME (ORCPT ); Wed, 1 Feb 2023 11:12:04 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CF8C469511 for ; Wed, 1 Feb 2023 08:12:03 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 68A166172E for ; Wed, 1 Feb 2023 16:12:03 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1C671C433D2; Wed, 1 Feb 2023 16:12:01 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Andy Walls , Hans Verkuil Subject: [PATCH 6/8] cx18: missing CAP_AUDIO for vbi stream Date: Wed, 1 Feb 2023 17:11:51 +0100 Message-Id: <20230201161153.883376-7-hverkuil-cisco@xs4all.nl> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> References: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil The v4l2-compliance test complained about this. You can change the input connector for the vbi stream, but that means that you can have to be able to do the same for the audio input. Signed-off-by: Hans Verkuil --- drivers/media/pci/cx18/cx18-streams.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c index 240d58d36d4b..4acde457f85d 100644 --- a/drivers/media/pci/cx18/cx18-streams.c +++ b/drivers/media/pci/cx18/cx18-streams.c @@ -80,7 +80,7 @@ static struct { VFL_TYPE_VBI, 0, DMA_FROM_DEVICE, V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_TUNER + V4L2_CAP_READWRITE | V4L2_CAP_AUDIO | V4L2_CAP_TUNER }, { /* CX18_ENC_STREAM_TYPE_PCM */ "encoder PCM audio", From patchwork Wed Feb 1 16:11:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 650763 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF876C64EC5 for ; Wed, 1 Feb 2023 16:12:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232466AbjBAQMJ (ORCPT ); Wed, 1 Feb 2023 11:12:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48136 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230200AbjBAQMG (ORCPT ); Wed, 1 Feb 2023 11:12:06 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0ED107642D for ; Wed, 1 Feb 2023 08:12:05 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 9129A61706 for ; Wed, 1 Feb 2023 16:12:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 44917C4339C; Wed, 1 Feb 2023 16:12:03 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Andy Walls , Hans Verkuil Subject: [PATCH 7/8] cx18: reorder fmt_vid_cap functions in cx18-ioctl.c Date: Wed, 1 Feb 2023 17:11:52 +0100 Message-Id: <20230201161153.883376-8-hverkuil-cisco@xs4all.nl> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> References: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil No actual code changed, this just reorders functions so that the g/try/s_fmt_vid_cap functions are all together rather than mixed in with the vbi format functions. Signed-off-by: Hans Verkuil --- drivers/media/pci/cx18/cx18-ioctl.c | 195 ++++++++++++++-------------- 1 file changed, 98 insertions(+), 97 deletions(-) diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index 549aa5e3c898..7403980e4ce1 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -49,6 +49,104 @@ static const struct v4l2_fmtdesc cx18_formats_mpeg[] = { }, }; +static int cx18_g_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_format *fmt) +{ + struct cx18_open_id *id = fh2id(fh); + struct cx18 *cx = id->cx; + struct cx18_stream *s = &cx->streams[id->type]; + struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; + + pixfmt->width = cx->cxhdl.width; + pixfmt->height = cx->cxhdl.height; + pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + pixfmt->field = V4L2_FIELD_INTERLACED; + if (id->type == CX18_ENC_STREAM_TYPE_YUV) { + pixfmt->pixelformat = s->pixelformat; + pixfmt->sizeimage = s->vb_bytes_per_frame; + pixfmt->bytesperline = s->vb_bytes_per_line; + } else { + pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; + pixfmt->sizeimage = 128 * 1024; + pixfmt->bytesperline = 0; + } + return 0; +} + +static int cx18_try_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_format *fmt) +{ + struct cx18_open_id *id = fh2id(fh); + struct cx18 *cx = id->cx; + int w = fmt->fmt.pix.width; + int h = fmt->fmt.pix.height; + int min_h = 2; + + w = min(w, 720); + w = max(w, 2); + + if (id->type == CX18_ENC_STREAM_TYPE_YUV) { + if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12_16L16 && + fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) + fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + /* YUV height must be a multiple of 32 */ + h &= ~0x1f; + min_h = 32; + } else { + fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + } + + h = min(h, cx->is_50hz ? 576 : 480); + h = max(h, min_h); + + fmt->fmt.pix.width = w; + fmt->fmt.pix.height = h; + return 0; +} + +static int cx18_s_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_format *fmt) +{ + struct cx18_open_id *id = fh2id(fh); + struct cx18 *cx = id->cx; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct cx18_stream *s = &cx->streams[id->type]; + int ret; + int w, h; + + ret = cx18_try_fmt_vid_cap(file, fh, fmt); + if (ret) + return ret; + w = fmt->fmt.pix.width; + h = fmt->fmt.pix.height; + + if (cx->cxhdl.width == w && cx->cxhdl.height == h && + s->pixelformat == fmt->fmt.pix.pixelformat) + return 0; + + if (atomic_read(&cx->ana_capturing) > 0) + return -EBUSY; + + s->pixelformat = fmt->fmt.pix.pixelformat; + /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) + UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ + if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) { + s->vb_bytes_per_frame = h * 720 * 3 / 2; + s->vb_bytes_per_line = 720; /* First plane */ + } else { + s->vb_bytes_per_frame = h * 720 * 2; + s->vb_bytes_per_line = 1440; /* Packed */ + } + + format.format.width = cx->cxhdl.width = w; + format.format.height = cx->cxhdl.height = h; + format.format.code = MEDIA_BUS_FMT_FIXED; + v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format); + return cx18_g_fmt_vid_cap(file, fh, fmt); +} + u16 cx18_service2vbi(int type) { switch (type) { @@ -153,29 +251,6 @@ u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) return set; } -static int cx18_g_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_format *fmt) -{ - struct cx18_open_id *id = fh2id(fh); - struct cx18 *cx = id->cx; - struct cx18_stream *s = &cx->streams[id->type]; - struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; - - pixfmt->width = cx->cxhdl.width; - pixfmt->height = cx->cxhdl.height; - pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; - pixfmt->field = V4L2_FIELD_INTERLACED; - if (id->type == CX18_ENC_STREAM_TYPE_YUV) { - pixfmt->pixelformat = s->pixelformat; - pixfmt->sizeimage = s->vb_bytes_per_frame; - pixfmt->bytesperline = s->vb_bytes_per_line; - } else { - pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; - pixfmt->sizeimage = 128 * 1024; - pixfmt->bytesperline = 0; - } - return 0; -} static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) @@ -221,37 +296,6 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, return 0; } -static int cx18_try_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_format *fmt) -{ - struct cx18_open_id *id = fh2id(fh); - struct cx18 *cx = id->cx; - int w = fmt->fmt.pix.width; - int h = fmt->fmt.pix.height; - int min_h = 2; - - w = min(w, 720); - w = max(w, 2); - - if (id->type == CX18_ENC_STREAM_TYPE_YUV) { - if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12_16L16 && - fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) - fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; - /* YUV height must be a multiple of 32 */ - h &= ~0x1f; - min_h = 32; - } else { - fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - } - - h = min(h, cx->is_50hz ? 576 : 480); - h = max(h, min_h); - - fmt->fmt.pix.width = w; - fmt->fmt.pix.height = h; - return 0; -} - static int cx18_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { @@ -277,49 +321,6 @@ static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, return 0; } -static int cx18_s_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_format *fmt) -{ - struct cx18_open_id *id = fh2id(fh); - struct cx18 *cx = id->cx; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct cx18_stream *s = &cx->streams[id->type]; - int ret; - int w, h; - - ret = cx18_try_fmt_vid_cap(file, fh, fmt); - if (ret) - return ret; - w = fmt->fmt.pix.width; - h = fmt->fmt.pix.height; - - if (cx->cxhdl.width == w && cx->cxhdl.height == h && - s->pixelformat == fmt->fmt.pix.pixelformat) - return 0; - - if (atomic_read(&cx->ana_capturing) > 0) - return -EBUSY; - - s->pixelformat = fmt->fmt.pix.pixelformat; - /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) - UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ - if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) { - s->vb_bytes_per_frame = h * 720 * 3 / 2; - s->vb_bytes_per_line = 720; /* First plane */ - } else { - s->vb_bytes_per_frame = h * 720 * 2; - s->vb_bytes_per_line = 1440; /* Packed */ - } - - format.format.width = cx->cxhdl.width = w; - format.format.height = cx->cxhdl.height = h; - format.format.code = MEDIA_BUS_FMT_FIXED; - v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format); - return cx18_g_fmt_vid_cap(file, fh, fmt); -} - static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { From patchwork Wed Feb 1 16:11:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 649504 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4161C05027 for ; Wed, 1 Feb 2023 16:12:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233002AbjBAQMS (ORCPT ); Wed, 1 Feb 2023 11:12:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47994 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232394AbjBAQMJ (ORCPT ); Wed, 1 Feb 2023 11:12:09 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCD60761C8 for ; Wed, 1 Feb 2023 08:12:07 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 8B64EB8217E for ; Wed, 1 Feb 2023 16:12:06 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6D00EC433D2; Wed, 1 Feb 2023 16:12:04 +0000 (UTC) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Andy Walls , Hans Verkuil Subject: [PATCH 8/8] cx18: fix format compliance issues Date: Wed, 1 Feb 2023 17:11:53 +0100 Message-Id: <20230201161153.883376-9-hverkuil-cisco@xs4all.nl> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> References: <20230201161153.883376-1-hverkuil-cisco@xs4all.nl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil This properly fills in all the format fields and calculates the width and height correctly. Esp. the minimum width and height was wrong. When changing the standard the width and height also have to be reset to the corresponding default width/height for the chosen standard. Signed-off-by: Hans Verkuil --- drivers/media/pci/cx18/cx18-ioctl.c | 65 ++++++++++++++++++----------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index 7403980e4ce1..95db1a03c466 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -78,29 +78,41 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, { struct cx18_open_id *id = fh2id(fh); struct cx18 *cx = id->cx; - int w = fmt->fmt.pix.width; - int h = fmt->fmt.pix.height; - int min_h = 2; + struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; + int w = pixfmt->width; + int h = pixfmt->height; w = min(w, 720); - w = max(w, 2); + w = max(w, 720 / 16); + + h = min(h, cx->is_50hz ? 576 : 480); + h = max(h, (cx->is_50hz ? 576 : 480) / 8); if (id->type == CX18_ENC_STREAM_TYPE_YUV) { - if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_NV12_16L16 && - fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) - fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + if (pixfmt->pixelformat != V4L2_PIX_FMT_NV12_16L16 && + pixfmt->pixelformat != V4L2_PIX_FMT_UYVY) + pixfmt->pixelformat = V4L2_PIX_FMT_UYVY; /* YUV height must be a multiple of 32 */ - h &= ~0x1f; - min_h = 32; + h = round_up(h, 32); + /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) + UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ + if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12_16L16) { + pixfmt->sizeimage = h * 720 * 3 / 2; + pixfmt->bytesperline = 720; /* First plane */ + } else { + pixfmt->sizeimage = h * 720 * 2; + pixfmt->bytesperline = 1440; /* Packed */ + } } else { - fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; + pixfmt->sizeimage = 128 * 1024; + pixfmt->bytesperline = 0; } - h = min(h, cx->is_50hz ? 576 : 480); - h = max(h, min_h); - - fmt->fmt.pix.width = w; - fmt->fmt.pix.height = h; + pixfmt->width = w; + pixfmt->height = h; + pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + pixfmt->field = V4L2_FIELD_INTERLACED; return 0; } @@ -130,15 +142,8 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, return -EBUSY; s->pixelformat = fmt->fmt.pix.pixelformat; - /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) - UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ - if (s->pixelformat == V4L2_PIX_FMT_NV12_16L16) { - s->vb_bytes_per_frame = h * 720 * 3 / 2; - s->vb_bytes_per_line = 720; /* First plane */ - } else { - s->vb_bytes_per_frame = h * 720 * 2; - s->vb_bytes_per_line = 1440; /* Packed */ - } + s->vb_bytes_per_frame = fmt->fmt.pix.sizeimage; + s->vb_bytes_per_line = fmt->fmt.pix.bytesperline; format.format.width = cx->cxhdl.width = w; format.format.height = cx->cxhdl.height = h; @@ -251,7 +256,6 @@ u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) return set; } - static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { @@ -612,6 +616,17 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id std) cx2341x_handler_set_50hz(&cx->cxhdl, cx->is_50hz); cx->cxhdl.width = 720; cx->cxhdl.height = cx->is_50hz ? 576 : 480; + /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) + UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */ + if (cx->streams[CX18_ENC_STREAM_TYPE_YUV].pixelformat == V4L2_PIX_FMT_NV12_16L16) { + cx->streams[CX18_ENC_STREAM_TYPE_YUV].vb_bytes_per_frame = + cx->cxhdl.height * 720 * 3 / 2; + cx->streams[CX18_ENC_STREAM_TYPE_YUV].vb_bytes_per_line = 720; + } else { + cx->streams[CX18_ENC_STREAM_TYPE_YUV].vb_bytes_per_frame = + cx->cxhdl.height * 720 * 2; + cx->streams[CX18_ENC_STREAM_TYPE_YUV].vb_bytes_per_line = 1440; + } cx->vbi.count = cx->is_50hz ? 18 : 12; cx->vbi.start[0] = cx->is_50hz ? 6 : 10; cx->vbi.start[1] = cx->is_50hz ? 318 : 273;