Hi Tomasz, Just a few more stylistic issues... On Tue October 2 2012 16:27:13 Tomasz Stanislawski wrote: > This patch adds description and usage examples for importing > DMABUF file descriptor in V4L2. > > Signed-off-by: Tomasz Stanislawski <t.stanislaws@xxxxxxxxxxx> > Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> > CC: linux-doc@xxxxxxxxxxxxxxx > --- > Documentation/DocBook/media/v4l/compat.xml | 4 + > Documentation/DocBook/media/v4l/io.xml | 180 +++++++++++++++++++- > .../DocBook/media/v4l/vidioc-create-bufs.xml | 16 +- > Documentation/DocBook/media/v4l/vidioc-qbuf.xml | 17 ++ > Documentation/DocBook/media/v4l/vidioc-reqbufs.xml | 47 ++--- > 5 files changed, 234 insertions(+), 30 deletions(-) > > diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml > index faa0fd1..a46f95b 100644 > --- a/Documentation/DocBook/media/v4l/compat.xml > +++ b/Documentation/DocBook/media/v4l/compat.xml > @@ -2621,6 +2621,10 @@ ioctls.</para> > <listitem> > <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para> > </listitem> > + <listitem> > + <para>Importing DMABUF file descriptors as a new IO method described > + in <xref linkend="dmabuf" />.</para> > + </listitem> > </itemizedlist> > </section> > > diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml > index 1885cc0..5b58657 100644 > --- a/Documentation/DocBook/media/v4l/io.xml > +++ b/Documentation/DocBook/media/v4l/io.xml > @@ -331,7 +331,7 @@ application until one or more buffers can be dequeued. By default > outgoing queue. When the <constant>O_NONBLOCK</constant> flag was > given to the &func-open; function, <constant>VIDIOC_DQBUF</constant> > returns immediately with an &EAGAIN; when no buffer is available. The > -&func-select; or &func-poll; function are always available.</para> > +&func-select; or &func-poll; functions are always available.</para> > > <para>To start and stop capturing or output applications call the > &VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctl. Note > @@ -472,6 +472,161 @@ rest should be evident.</para> > </footnote></para> > </section> > > + <section id="dmabuf"> > + <title>Streaming I/O (DMA buffer importing)</title> > + > + <note> > + <title>Experimental</title> > + <para>This is an <link linkend="experimental"> experimental </link> > + interface and may change in the future.</para> > + </note> > + > +<para>The DMABUF framework provides a generic method for sharing buffers > +between multiple devices. Device drivers that support DMABUF can export a DMA > +buffer to userspace as a file descriptor (known as the exporter role), import a > +DMA buffer from userspace using a file descriptor previously exported for a > +different or the same device (known as the importer role), or both. This > +section describes the DMABUF importer role API in V4L2.</para> > + > +<para>Input and output devices support the streaming I/O method when the > +<constant>V4L2_CAP_STREAMING</constant> flag in the > +<structfield>capabilities</structfield> field of &v4l2-capability; returned by > +the &VIDIOC-QUERYCAP; ioctl is set. Whether importing DMA buffers through > +DMABUF file descriptors is supported is determined by calling the > +&VIDIOC-REQBUFS; ioctl with the memory type set to > +<constant>V4L2_MEMORY_DMABUF</constant>.</para> > + > + <para>This I/O method is dedicated for sharing DMA buffers between V4L and > +other APIs. It's more accurate to say something along the lines of: "...is dedicated to sharing DMA buffers between different devices, which may be V4L devices or other video-related devices (e.g. DRM)." One of the uses of this API is to share buffers between different V4L devices, so that's a bit more generic than the original sentence suggests. > Buffers (planes) are allocated by a driver on behalf of an > +application. Next, these buffers are exported to the application as file > +descriptors using an API which is specific for an allocator driver. Only such > +file descriptor are exchanged. The descriptors and meta-information are passed > +in &v4l2-buffer; (or in &v4l2-plane; in the multi-planar API case). The driver > +must be switched into DMABUF I/O mode by calling the &VIDIOC-REQBUFS; with the > +desired buffer type.</para> > + > + <example> > + <title>Initiating streaming I/O with DMABUF file descriptors</title> > + > + <programlisting> > +&v4l2-requestbuffers; reqbuf; > + > +memset (&reqbuf, 0, sizeof (reqbuf)); no space after memset > +reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > +reqbuf.memory = V4L2_MEMORY_DMABUF; > +reqbuf.count = 1; > + > +if (ioctl (fd, &VIDIOC-REQBUFS;, &reqbuf) == -1) { no space after ioctl > + if (errno == EINVAL) > + printf("Video capturing or DMABUF streaming is not supported\n"); > + else > + perror("VIDIOC_REQBUFS"); > + > + exit(EXIT_FAILURE); > +} > + </programlisting> > + </example> > + > + <para>The buffer (plane) file descriptor is passed on the fly with the > +&VIDIOC-QBUF; ioctl. In case of multiplanar buffers, every plane can be > +associated with a different DMABUF descriptor. Although buffers are commonly > +cycled, applications can pass a different DMABUF descriptor at each > +<constant>VIDIOC_QBUF</constant> call.</para> > + > + <example> > + <title>Queueing DMABUF using single plane API</title> > + > + <programlisting> > +int buffer_queue(int v4lfd, int index, int dmafd) > +{ > + &v4l2-buffer; buf; > + > + memset(&buf, 0, sizeof buf); > + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > + buf.memory = V4L2_MEMORY_DMABUF; > + buf.index = index; > + buf.m.fd = dmafd; > + > + if (ioctl(v4lfd, &VIDIOC-QBUF;, &buf) == -1) { > + perror("VIDIOC_QBUF"); > + return -1; > + } > + > + return 0; > +} > + </programlisting> > + </example> > + > + <example> > + <title>Queueing DMABUF using multi plane API</title> > + > + <programlisting> > +int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes) > +{ > + &v4l2-buffer; buf; > + &v4l2-plane; planes[VIDEO_MAX_PLANES]; > + int i; > + > + memset(&buf, 0, sizeof buf); > + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; > + buf.memory = V4L2_MEMORY_DMABUF; > + buf.index = index; > + buf.m.planes = planes; > + buf.length = n_planes; > + > + memset(&planes, 0, sizeof planes); > + > + for (i = 0; i < n_planes; ++i) > + buf.m.planes[i].m.fd = dmafd[i]; > + > + if (ioctl(v4lfd, &VIDIOC-QBUF;, &buf) == -1) { > + perror("VIDIOC_QBUF"); > + return -1; > + } > + > + return 0; > +} > + </programlisting> > + </example> > + > + <para>Filled or displayed buffers are dequeued with the Filled -> Captured > +&VIDIOC-DQBUF; ioctl. The driver can unlock the buffer at any > +time between the completion of the DMA and this ioctl. The memory is > +also unlocked when &VIDIOC-STREAMOFF; is called, &VIDIOC-REQBUFS;, or > +when the device is closed.</para> > + > + <para>For capturing applications it is customary to enqueue a > +number of empty buffers, to start capturing and enter the read loop. > +Here the application waits until a filled buffer can be dequeued, and > +re-enqueues the buffer when the data is no longer needed. Output > +applications fill and enqueue buffers, when enough buffers are stacked > +up output is started. In the write loop, when the application > +runs out of free buffers it must wait until an empty buffer can be > +dequeued and reused. Two methods exist to suspend execution of the > +application until one or more buffers can be dequeued. By default > +<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the > +outgoing queue. When the <constant>O_NONBLOCK</constant> flag was > +given to the &func-open; function, <constant>VIDIOC_DQBUF</constant> > +returns immediately with an &EAGAIN; when no buffer is available. The > +&func-select; or &func-poll; function are always available.</para> or -> and function -> functions > + > + <para>To start and stop capturing or output applications call the output -> displaying > +&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctls. Note that > +<constant>VIDIOC_STREAMOFF</constant> removes all buffers from both queues and > +unlocks all buffers as a side effect. Since there is no notion of doing > +anything "now" on a multitasking system, if an application needs to synchronize > +with another event it should examine the &v4l2-buffer; > +<structfield>timestamp</structfield> of captured buffers, or set the field > +before enqueuing buffers for output.</para> > + > + <para>Drivers implementing DMABUF importing I/O must support the > +<constant>VIDIOC_REQBUFS</constant>, <constant>VIDIOC_QBUF</constant>, > +<constant>VIDIOC_DQBUF</constant>, <constant>VIDIOC_STREAMON</constant> and > +<constant>VIDIOC_STREAMOFF</constant> ioctls, and the > +<function>select()</function> and <function>poll()</function> functions.</para> > + > + </section> > + > <section id="async"> > <title>Asynchronous I/O</title> > > @@ -673,6 +828,14 @@ memory, set by the application. See <xref linkend="userp" /> for details. > <structname>v4l2_buffer</structname> structure.</entry> > </row> > <row> > + <entry></entry> > + <entry>int</entry> > + <entry><structfield>fd</structfield></entry> > + <entry>For the single-plane API and when > +<structfield>memory</structfield> is <constant>V4L2_MEMORY_DMABUF</constant> this > +is the file descriptor associated with a DMABUF buffer.</entry> > + </row> > + <row> > <entry>__u32</entry> > <entry><structfield>length</structfield></entry> > <entry></entry> > @@ -746,6 +909,15 @@ should set this to 0.</entry> > </entry> > </row> > <row> > + <entry></entry> > + <entry>int</entry> > + <entry><structfield>fd</structfield></entry> > + <entry>When the memory type in the containing &v4l2-buffer; is > + <constant>V4L2_MEMORY_DMABUF</constant>, this is a file > + descriptor associated with a DMABUF buffer, similar to the > + <structfield>fd</structfield> field in &v4l2-buffer;.</entry> > + </row> > + <row> > <entry>__u32</entry> > <entry><structfield>data_offset</structfield></entry> > <entry></entry> > @@ -973,6 +1145,12 @@ pointer</link> I/O.</entry> > <entry>3</entry> > <entry>[to do]</entry> > </row> > + <row> > + <entry><constant>V4L2_MEMORY_DMABUF</constant></entry> > + <entry>4</entry> > + <entry>The buffer is used for <link linkend="dmabuf">DMA shared > +buffer</link> I/O.</entry> > + </row> > </tbody> > </tgroup> > </table> > diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml > index a8cda1a..cd99436 100644 > --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml > +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml > @@ -6,7 +6,8 @@ > > <refnamediv> > <refname>VIDIOC_CREATE_BUFS</refname> > - <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose> > + <refpurpose>Create buffers for Memory Mapped or User Pointer or DMA Buffer > + I/O</refpurpose> > </refnamediv> > > <refsynopsisdiv> > @@ -55,11 +56,11 @@ > </note> > > <para>This ioctl is used to create buffers for <link linkend="mmap">memory > -mapped</link> or <link linkend="userp">user pointer</link> > -I/O. It can be used as an alternative or in addition to the > -<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers > -is required. This ioctl can be called multiple times to create buffers of > -different sizes.</para> > +mapped</link> or <link linkend="userp">user pointer</link> or <link > +linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in > +addition to the <constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter > +control over buffers is required. This ioctl can be called multiple times to > +create buffers of different sizes.</para> > > <para>To allocate device buffers applications initialize relevant fields of > the <structname>v4l2_create_buffers</structname> structure. They set the > @@ -109,7 +110,8 @@ information.</para> > <entry>__u32</entry> > <entry><structfield>memory</structfield></entry> > <entry>Applications set this field to > -<constant>V4L2_MEMORY_MMAP</constant> or > +<constant>V4L2_MEMORY_MMAP</constant>, > +<constant>V4L2_MEMORY_DMABUF</constant> or > <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory" > /></entry> > </row> > diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml > index 77ff5be..f40dfa0 100644 > --- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml > +++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml > @@ -109,6 +109,23 @@ they cannot be swapped out to disk. Buffers remain locked until > dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is > called, or until the device is closed.</para> > > + <para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications > +set the <structfield>memory</structfield> field to > +<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield> > +field to a file descriptor associated with a DMABUF buffer. When the > +multi-planar API is used the <structfield>m.fd</structfield> fields of the > +passed array of &v4l2-plane; have to be used instead. When > +<constant>VIDIOC_QBUF</constant> is called with a pointer to this structure the > +driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the > +<constant>V4L2_BUF_FLAG_MAPPED</constant> and > +<constant>V4L2_BUF_FLAG_DONE</constant> flags in the > +<structfield>flags</structfield> field, or it returns an error code. This > +ioctl locks the buffer. Locking a buffer means passing it to a driver for an > +access by hardware. "an access by hardware" -> "hardware access (usually DMA)" > If an application accesses (reads/writes) a locked buffer > +then the result is undefined. Buffers remain locked until dequeued, until the > +&VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or until the device is > +closed.</para> > + > <para>Applications call the <constant>VIDIOC_DQBUF</constant> > ioctl to dequeue a filled (capturing) or displayed (output) buffer > from the driver's outgoing queue. They just set the > diff --git a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml > index d7c9505..20f4323 100644 > --- a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml > +++ b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml > @@ -48,28 +48,30 @@ > <refsect1> > <title>Description</title> > > - <para>This ioctl is used to initiate <link linkend="mmap">memory > -mapped</link> or <link linkend="userp">user pointer</link> > -I/O. Memory mapped buffers are located in device memory and must be > -allocated with this ioctl before they can be mapped into the > -application's address space. User buffers are allocated by > -applications themselves, and this ioctl is merely used to switch the > -driver into user pointer I/O mode and to setup some internal structures.</para> > +<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>, > +<link linkend="userp">user pointer</link> or <link > +linkend="dmabuf">DMABUF</link> based I/O. Memory mapped buffers are located in > +device memory and must be allocated with this ioctl before they can be mapped > +into the application's address space. User buffers are allocated by > +applications themselves, and this ioctl is merely used to switch the driver > +into user pointer I/O mode and to setup some internal structures. > +Similarly, DMABUF buffers are allocated by applications through a device > +driver, and this ioctl only configures the driver into DMABUF I/O mode without > +performing any direct allocation.</para> > > - <para>To allocate device buffers applications initialize all > -fields of the <structname>v4l2_requestbuffers</structname> structure. > -They set the <structfield>type</structfield> field to the respective > -stream or buffer type, the <structfield>count</structfield> field to > -the desired number of buffers, <structfield>memory</structfield> > -must be set to the requested I/O method and the <structfield>reserved</structfield> array > -must be zeroed. When the ioctl > -is called with a pointer to this structure the driver will attempt to allocate > -the requested number of buffers and it stores the actual number > -allocated in the <structfield>count</structfield> field. It can be > -smaller than the number requested, even zero, when the driver runs out > -of free memory. A larger number is also possible when the driver requires > -more buffers to function correctly. For example video output requires at least two buffers, > -one displayed and one filled by the application.</para> > + <para>To allocate device buffers applications initialize all fields of the > +<structname>v4l2_requestbuffers</structname> structure. They set the > +<structfield>type</structfield> field to the respective stream or buffer type, > +the <structfield>count</structfield> field to the desired number of buffers, > +<structfield>memory</structfield> must be set to the requested I/O method and > +the <structfield>reserved</structfield> array must be zeroed. When the ioctl is > +called with a pointer to this structure the driver will attempt to allocate the > +requested number of buffers and it stores the actual number allocated in the > +<structfield>count</structfield> field. It can be smaller than the number > +requested, even zero, when the driver runs out of free memory. A larger number > +is also possible when the driver requires more buffers to function correctly. > +For example video output requires at least two buffers, one displayed and one > +filled by the application.</para> > <para>When the I/O method is not supported the ioctl > returns an &EINVAL;.</para> > > @@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref > <entry>__u32</entry> > <entry><structfield>memory</structfield></entry> > <entry>Applications set this field to > -<constant>V4L2_MEMORY_MMAP</constant> or > +<constant>V4L2_MEMORY_MMAP</constant>, > +<constant>V4L2_MEMORY_DMABUF</constant> or > <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory" > />.</entry> > </row> > Regards, Hans -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html