From bedbef8ad3e75a304af6361af235302bcc61d06b Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 14 May 2024 06:39:01 +0000
Subject: [PATCH] 修改内核路径
---
kernel/drivers/usb/gadget/function/uvc_queue.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 101 insertions(+), 15 deletions(-)
diff --git a/kernel/drivers/usb/gadget/function/uvc_queue.c b/kernel/drivers/usb/gadget/function/uvc_queue.c
index a404108..d6383ac 100644
--- a/kernel/drivers/usb/gadget/function/uvc_queue.c
+++ b/kernel/drivers/usb/gadget/function/uvc_queue.c
@@ -20,6 +20,7 @@
#include <media/videobuf2-vmalloc.h>
#include "uvc.h"
+#include "u_uvc.h"
/* ------------------------------------------------------------------------
* Video buffers queue management.
@@ -43,6 +44,12 @@
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
struct uvc_video *video = container_of(queue, struct uvc_video, queue);
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
+ struct uvc_device *uvc = container_of(video, struct uvc_device, video);
+ struct f_uvc_opts *opts = fi_to_f_uvc_opts(uvc->func.fi);
+#endif
+ unsigned int req_size;
+ unsigned int nreq;
if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
*nbuffers = UVC_MAX_VIDEO_BUFFERS;
@@ -51,8 +58,92 @@
sizes[0] = video->imagesize;
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
+ if (opts && opts->uvc_num_request > 0) {
+ video->uvc_num_requests = opts->uvc_num_request;
+ return 0;
+ }
+#endif
+
+ req_size = video->ep->maxpacket
+ * max_t(unsigned int, video->ep->maxburst, 1)
+ * (video->ep->mult);
+
+ /* We divide by two, to increase the chance to run
+ * into fewer requests for smaller framesizes.
+ */
+ nreq = DIV_ROUND_UP(DIV_ROUND_UP(sizes[0], 2), req_size);
+ nreq = clamp(nreq, 4U, 64U);
+ video->uvc_num_requests = nreq;
+
return 0;
}
+
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
+/*
+ * uvc_dma_buf_phys_to_virt - Get the physical address of the dma_buf and
+ * translate it to virtual address.
+ *
+ * @dbuf: the dma_buf of vb2_plane
+ * @dev: the device to the actual usb controller
+ *
+ * This function is used for dma buf allocated by Contiguous Memory Allocator.
+ *
+ * Returns:
+ * The virtual addresses of the dma_buf.
+ */
+static void *uvc_dma_buf_phys_to_virt(struct uvc_device *uvc,
+ struct dma_buf *dbuf)
+{
+ struct usb_gadget *gadget = uvc->func.config->cdev->gadget;
+ struct dma_buf_attachment *attachment;
+ struct sg_table *table;
+ struct scatterlist *sgl;
+ dma_addr_t phys = 0;
+ int i;
+
+ attachment = dma_buf_attach(dbuf, gadget->dev.parent);
+ if (IS_ERR(attachment))
+ return ERR_PTR(-ENOMEM);
+
+ table = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
+ if (IS_ERR(table)) {
+ dma_buf_detach(dbuf, attachment);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ for_each_sgtable_sg(table, sgl, i)
+ phys = sg_phys(sgl);
+
+ dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL);
+ dma_buf_detach(dbuf, attachment);
+
+ if (i > 1) {
+ uvcg_err(&uvc->func, "Not support mult sgl for uvc zero copy\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return phys_to_virt(phys);
+}
+
+static void *uvc_buffer_mem_prepare(struct vb2_buffer *vb,
+ struct uvc_video_queue *queue)
+{
+ struct uvc_video *video = container_of(queue, struct uvc_video, queue);
+ struct uvc_device *uvc = container_of(video, struct uvc_device, video);
+ struct f_uvc_opts *opts = fi_to_f_uvc_opts(uvc->func.fi);
+ void *mem;
+
+ if (!opts->uvc_zero_copy || video->fcc == V4L2_PIX_FMT_YUYV)
+ return (vb2_plane_vaddr(vb, 0) + vb2_plane_data_offset(vb, 0));
+
+ mem = uvc_dma_buf_phys_to_virt(uvc, vb->planes[0].dbuf);
+ if (IS_ERR(mem))
+ return ERR_PTR(-ENOMEM);
+
+ return (mem + vb2_plane_data_offset(vb, 0));
+}
+#endif
static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
@@ -70,7 +161,13 @@
return -ENODEV;
buf->state = UVC_BUF_STATE_QUEUED;
+#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI)
+ buf->mem = uvc_buffer_mem_prepare(vb, queue);
+ if (IS_ERR(buf->mem))
+ return -ENOMEM;
+#else
buf->mem = vb2_plane_vaddr(vb, 0);
+#endif
buf->length = vb2_plane_size(vb, 0);
if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->bytesused = 0;
@@ -102,7 +199,7 @@
spin_unlock_irqrestore(&queue->irqlock, flags);
}
-static struct vb2_ops uvc_queue_qops = {
+static const struct vb2_ops uvc_queue_qops = {
.queue_setup = uvc_queue_setup,
.buf_prepare = uvc_buffer_prepare,
.buf_queue = uvc_buffer_queue,
@@ -171,18 +268,7 @@
int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
{
- unsigned long flags;
- int ret;
-
- ret = vb2_qbuf(&queue->queue, buf);
- if (ret < 0)
- return ret;
-
- spin_lock_irqsave(&queue->irqlock, flags);
- ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
- queue->flags &= ~UVC_QUEUE_PAUSED;
- spin_unlock_irqrestore(&queue->irqlock, flags);
- return ret;
+ return vb2_qbuf(&queue->queue, NULL, buf);
}
/*
@@ -250,6 +336,8 @@
buf->state = UVC_BUF_STATE_ERROR;
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
}
+ queue->buf_used = 0;
+
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
@@ -348,8 +436,6 @@
if (!list_empty(&queue->irqqueue))
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
- else
- queue->flags |= UVC_QUEUE_PAUSED;
return buf;
}
--
Gitblit v1.6.2