From c4c0a78d459f2e4fcc7c4f3621a34e71ec7970d0 Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Wed, 12 Jan 2011 05:57:26 -0300 Subject: [media] Fix mmap() example in the V4L2 API DocBook Correct ioctl return value handling and fix coding style issues. [mchehab@redhat.com: return -1 is OK, according with ioctl manpages. Reverting ioctl changes] Signed-off-by: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/io.xml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/io.xml b/Documentation/DocBook/v4l/io.xml index d424886beda..a9750437000 100644 --- a/Documentation/DocBook/v4l/io.xml +++ b/Documentation/DocBook/v4l/io.xml @@ -141,63 +141,63 @@ struct { } *buffers; unsigned int i; -memset (&reqbuf, 0, sizeof (reqbuf)); +memset(&reqbuf, 0, sizeof(reqbuf)); reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = V4L2_MEMORY_MMAP; reqbuf.count = 20; if (-1 == ioctl (fd, &VIDIOC-REQBUFS;, &reqbuf)) { if (errno == EINVAL) - printf ("Video capturing or mmap-streaming is not supported\n"); + printf("Video capturing or mmap-streaming is not supported\n"); else - perror ("VIDIOC_REQBUFS"); + perror("VIDIOC_REQBUFS"); - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } /* We want at least five buffers. */ if (reqbuf.count < 5) { /* You may need to free the buffers here. */ - printf ("Not enough buffer memory\n"); - exit (EXIT_FAILURE); + printf("Not enough buffer memory\n"); + exit(EXIT_FAILURE); } -buffers = calloc (reqbuf.count, sizeof (*buffers)); -assert (buffers != NULL); +buffers = calloc(reqbuf.count, sizeof(*buffers)); +assert(buffers != NULL); for (i = 0; i < reqbuf.count; i++) { &v4l2-buffer; buffer; - memset (&buffer, 0, sizeof (buffer)); + memset(&buffer, 0, sizeof(buffer)); buffer.type = reqbuf.type; buffer.memory = V4L2_MEMORY_MMAP; buffer.index = i; if (-1 == ioctl (fd, &VIDIOC-QUERYBUF;, &buffer)) { - perror ("VIDIOC_QUERYBUF"); - exit (EXIT_FAILURE); + perror("VIDIOC_QUERYBUF"); + exit(EXIT_FAILURE); } buffers[i].length = buffer.length; /* remember for munmap() */ - buffers[i].start = mmap (NULL, buffer.length, - PROT_READ | PROT_WRITE, /* recommended */ - MAP_SHARED, /* recommended */ - fd, buffer.m.offset); + buffers[i].start = mmap(NULL, buffer.length, + PROT_READ | PROT_WRITE, /* recommended */ + MAP_SHARED, /* recommended */ + fd, buffer.m.offset); if (MAP_FAILED == buffers[i].start) { /* If you do not exit here you should unmap() and free() the buffers mapped so far. */ - perror ("mmap"); - exit (EXIT_FAILURE); + perror("mmap"); + exit(EXIT_FAILURE); } } /* Cleanup. */ for (i = 0; i < reqbuf.count; i++) - munmap (buffers[i].start, buffers[i].length); + munmap(buffers[i].start, buffers[i].length); -- cgit v1.2.3-70-g09d2 From 53b5d5749b6fcca37c7ad60cd40feafadd390b70 Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Fri, 7 Jan 2011 01:41:33 -0300 Subject: [media] Add multi-planar API documentation Add DocBook documentation for the new multi-planar API extensions to the Video for Linux 2 API DocBook. Signed-off-by: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 4 + Documentation/DocBook/v4l/common.xml | 2 + Documentation/DocBook/v4l/compat.xml | 11 ++ Documentation/DocBook/v4l/dev-capture.xml | 13 +- Documentation/DocBook/v4l/dev-output.xml | 13 +- Documentation/DocBook/v4l/func-mmap.xml | 10 +- Documentation/DocBook/v4l/func-munmap.xml | 3 +- Documentation/DocBook/v4l/io.xml | 247 ++++++++++++++++++++++---- Documentation/DocBook/v4l/pixfmt.xml | 116 +++++++++++- Documentation/DocBook/v4l/planar-apis.xml | 81 +++++++++ Documentation/DocBook/v4l/v4l2.xml | 21 ++- Documentation/DocBook/v4l/vidioc-enum-fmt.xml | 2 + Documentation/DocBook/v4l/vidioc-g-fmt.xml | 15 +- Documentation/DocBook/v4l/vidioc-qbuf.xml | 24 ++- Documentation/DocBook/v4l/vidioc-querybuf.xml | 14 +- Documentation/DocBook/v4l/vidioc-querycap.xml | 24 ++- 16 files changed, 530 insertions(+), 70 deletions(-) create mode 100644 Documentation/DocBook/v4l/planar-apis.xml (limited to 'Documentation') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index be34dcbe0d9..74923d74553 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -129,6 +129,7 @@ v4l2_audioout"> v4l2_bt_timings"> v4l2_buffer"> +v4l2_plane"> v4l2_capability"> v4l2_captureparm"> v4l2_clip"> @@ -167,6 +168,8 @@ v4l2_output"> v4l2_outputparm"> v4l2_pix_format"> +v4l2_pix_format_mplane"> +v4l2_plane_pix_format"> v4l2_queryctrl"> v4l2_querymenu"> v4l2_rect"> @@ -202,6 +205,7 @@ + diff --git a/Documentation/DocBook/v4l/common.xml b/Documentation/DocBook/v4l/common.xml index cea23e1c4fc..dbab79c215c 100644 --- a/Documentation/DocBook/v4l/common.xml +++ b/Documentation/DocBook/v4l/common.xml @@ -846,6 +846,8 @@ conversion routine or library for integration into applications. + &sub-planar-apis; +
Image Cropping, Insertion and Scaling diff --git a/Documentation/DocBook/v4l/compat.xml b/Documentation/DocBook/v4l/compat.xml index c9ce61d981f..223c24c536b 100644 --- a/Documentation/DocBook/v4l/compat.xml +++ b/Documentation/DocBook/v4l/compat.xml @@ -2353,6 +2353,17 @@ that used it. It was originally scheduled for removal in 2.6.35.
+
+ V4L2 in Linux 2.6.38 + + + Multi-planar API added. Does not affect the compatibility of + current drivers and applications. See + multi-planar API + for details. + + +
Relation of V4L2 to other Linux multimedia APIs diff --git a/Documentation/DocBook/v4l/dev-capture.xml b/Documentation/DocBook/v4l/dev-capture.xml index 32807e43f17..2237c661f26 100644 --- a/Documentation/DocBook/v4l/dev-capture.xml +++ b/Documentation/DocBook/v4l/dev-capture.xml @@ -18,7 +18,8 @@ files are used for video output devices. Querying Capabilities Devices supporting the video capture interface set the -V4L2_CAP_VIDEO_CAPTURE flag in the +V4L2_CAP_VIDEO_CAPTURE or +V4L2_CAP_VIDEO_CAPTURE_MPLANE flag in the capabilities field of &v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl. As secondary device functions they may also support the video overlay @@ -64,9 +65,11 @@ linkend="crop" />. To query the current image format applications set the type field of a &v4l2-format; to -V4L2_BUF_TYPE_VIDEO_CAPTURE and call the +V4L2_BUF_TYPE_VIDEO_CAPTURE or +V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE and call the &VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill -the &v4l2-pix-format; pix member of the +the &v4l2-pix-format; pix or the +&v4l2-pix-format-mplane; pix_mp member of the fmt union. To request different parameters applications set the @@ -84,8 +87,8 @@ adjust the parameters and finally return the actual parameters as without disabling I/O or possibly time consuming hardware preparations. - The contents of &v4l2-pix-format; are discussed in . See also the specification of the + The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane; +are discussed in . See also the specification of the VIDIOC_G_FMT, VIDIOC_S_FMT and VIDIOC_TRY_FMT ioctls for details. Video capture devices must implement both the diff --git a/Documentation/DocBook/v4l/dev-output.xml b/Documentation/DocBook/v4l/dev-output.xml index 63c3c20e5a7..919e22c5385 100644 --- a/Documentation/DocBook/v4l/dev-output.xml +++ b/Documentation/DocBook/v4l/dev-output.xml @@ -17,7 +17,8 @@ files are used for video capture devices. Querying Capabilities Devices supporting the video output interface set the -V4L2_CAP_VIDEO_OUTPUT flag in the +V4L2_CAP_VIDEO_OUTPUT or +V4L2_CAP_VIDEO_OUTPUT_MPLANE flag in the capabilities field of &v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl. As secondary device functions they may also support the raw VBI @@ -60,9 +61,11 @@ linkend="crop" />. To query the current image format applications set the type field of a &v4l2-format; to -V4L2_BUF_TYPE_VIDEO_OUTPUT and call the +V4L2_BUF_TYPE_VIDEO_OUTPUT or +V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE and call the &VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill -the &v4l2-pix-format; pix member of the +the &v4l2-pix-format; pix or the +&v4l2-pix-format-mplane; pix_mp member of the fmt union. To request different parameters applications set the @@ -80,8 +83,8 @@ adjust the parameters and finally return the actual parameters as without disabling I/O or possibly time consuming hardware preparations. - The contents of &v4l2-pix-format; are discussed in . See also the specification of the + The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane; +are discussed in . See also the specification of the VIDIOC_G_FMT, VIDIOC_S_FMT and VIDIOC_TRY_FMT ioctls for details. Video output devices must implement both the diff --git a/Documentation/DocBook/v4l/func-mmap.xml b/Documentation/DocBook/v4l/func-mmap.xml index 2e2fc3933ae..786732b64bb 100644 --- a/Documentation/DocBook/v4l/func-mmap.xml +++ b/Documentation/DocBook/v4l/func-mmap.xml @@ -45,7 +45,10 @@ just specify a NULL pointer here. Length of the memory area to map. This must be the same value as returned by the driver in the &v4l2-buffer; -length field. +length field for the +single-planar API, and the same value as returned by the driver +in the &v4l2-plane; length field for the +multi-planar API. @@ -106,7 +109,10 @@ flag. Offset of the buffer in device memory. This must be the same value as returned by the driver in the &v4l2-buffer; -m union offset field. +m union offset field for +the single-planar API, and the same value as returned by the driver +in the &v4l2-plane; m union +mem_offset field for the multi-planar API. diff --git a/Documentation/DocBook/v4l/func-munmap.xml b/Documentation/DocBook/v4l/func-munmap.xml index 502ed49323b..e2c4190f9bb 100644 --- a/Documentation/DocBook/v4l/func-munmap.xml +++ b/Documentation/DocBook/v4l/func-munmap.xml @@ -37,7 +37,8 @@ Length of the mapped buffer. This must be the same value as given to mmap() and returned by the driver in the &v4l2-buffer; length -field. +field for the single-planar API and in the &v4l2-plane; +length field for the multi-planar API. diff --git a/Documentation/DocBook/v4l/io.xml b/Documentation/DocBook/v4l/io.xml index a9750437000..227e7ac45a0 100644 --- a/Documentation/DocBook/v4l/io.xml +++ b/Documentation/DocBook/v4l/io.xml @@ -121,18 +121,22 @@ mapped. Before applications can access the buffers they must map them into their address space with the &func-mmap; function. The location of the buffers in device memory can be determined with the -&VIDIOC-QUERYBUF; ioctl. The m.offset and -length returned in a &v4l2-buffer; are -passed as sixth and second parameter to the -mmap() function. The offset and length values -must not be modified. Remember the buffers are allocated in physical -memory, as opposed to virtual memory which can be swapped out to disk. -Applications should free the buffers as soon as possible with the -&func-munmap; function. +&VIDIOC-QUERYBUF; ioctl. In the single-planar API case, the +m.offset and length +returned in a &v4l2-buffer; are passed as sixth and second parameter to the +mmap() function. When using the multi-planar API, +struct &v4l2-buffer; contains an array of &v4l2-plane; structures, each +containing its own m.offset and +length. When using the multi-planar API, every +plane of every buffer has to be mapped separately, so the number of +calls to &func-mmap; should be equal to number of buffers times number of +planes in each buffer. The offset and length values must not be modified. +Remember, the buffers are allocated in physical memory, as opposed to virtual +memory, which can be swapped out to disk. Applications should free the buffers +as soon as possible with the &func-munmap; function. - Mapping buffers - + Mapping buffers in the single-planar API &v4l2-requestbuffers; reqbuf; struct { @@ -201,6 +205,88 @@ for (i = 0; i < reqbuf.count; i++) + + Mapping buffers in the multi-planar API + +&v4l2-requestbuffers; reqbuf; +/* Our current format uses 3 planes per buffer */ +#define FMT_NUM_PLANES = 3; + +struct { + void *start[FMT_NUM_PLANES]; + size_t length[FMT_NUM_PLANES]; +} *buffers; +unsigned int i, j; + +memset(&reqbuf, 0, sizeof(reqbuf)); +reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; +reqbuf.memory = V4L2_MEMORY_MMAP; +reqbuf.count = 20; + +if (ioctl(fd, &VIDIOC-REQBUFS;, &reqbuf) < 0) { + if (errno == EINVAL) + printf("Video capturing or mmap-streaming is not supported\n"); + else + perror("VIDIOC_REQBUFS"); + + exit(EXIT_FAILURE); +} + +/* We want at least five buffers. */ + +if (reqbuf.count < 5) { + /* You may need to free the buffers here. */ + printf("Not enough buffer memory\n"); + exit(EXIT_FAILURE); +} + +buffers = calloc(reqbuf.count, sizeof(*buffers)); +assert(buffers != NULL); + +for (i = 0; i < reqbuf.count; i++) { + &v4l2-buffer; buffer; + &v4l2-plane; planes[FMT_NUM_PLANES]; + + memset(&buffer, 0, sizeof(buffer)); + buffer.type = reqbuf.type; + buffer.memory = V4L2_MEMORY_MMAP; + buffer.index = i; + /* length in struct v4l2_buffer in multi-planar API stores the size + * of planes array. */ + buffer.length = FMT_NUM_PLANES; + buffer.m.planes = planes; + + if (ioctl(fd, &VIDIOC-QUERYBUF;, &buffer) < 0) { + perror("VIDIOC_QUERYBUF"); + exit(EXIT_FAILURE); + } + + /* Every plane has to be mapped separately */ + for (j = 0; j < FMT_NUM_PLANES; j++) { + buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */ + + buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length, + PROT_READ | PROT_WRITE, /* recommended */ + MAP_SHARED, /* recommended */ + fd, buffer.m.planes[j].m.offset); + + if (MAP_FAILED == buffers[i].start[j]) { + /* If you do not exit here you should unmap() and free() + the buffers and planes mapped so far. */ + perror("mmap"); + exit(EXIT_FAILURE); + } + } +} + +/* Cleanup. */ + +for (i = 0; i < reqbuf.count; i++) + for (j = 0; j < FMT_NUM_PLANES; j++) + munmap(buffers[i].start[j], buffers[i].length[j]); + + + Conceptually streaming drivers maintain two buffer queues, an incoming and an outgoing queue. They separate the synchronous capture or output operation locked to a video clock from the application which is @@ -286,13 +372,13 @@ pointer method (not only memory mapping) is supported must be determined by calling the &VIDIOC-REQBUFS; ioctl. This I/O method combines advantages of the read/write and -memory mapping methods. Buffers are allocated by the application +memory mapping methods. Buffers (planes) are allocated by the application itself, and can reside for example in virtual or shared memory. Only pointers to data are exchanged, these pointers and meta-information -are passed in &v4l2-buffer;. The driver must be switched -into user pointer I/O mode by calling the &VIDIOC-REQBUFS; with the -desired buffer type. No buffers are allocated beforehands, -consequently they are not indexed and cannot be queried like mapped +are passed in &v4l2-buffer; (or in &v4l2-plane; in the multi-planar API case). +The driver must be switched into user pointer I/O mode by calling the +&VIDIOC-REQBUFS; with the desired buffer type. No buffers (planes) are allocated +beforehand, consequently they are not indexed and cannot be queried like mapped buffers with the VIDIOC_QUERYBUF ioctl. @@ -316,7 +402,7 @@ if (ioctl (fd, &VIDIOC-REQBUFS;, &reqbuf) == -1) { - Buffer addresses and sizes are passed on the fly with the + Buffer (plane) addresses and sizes are passed on the fly with the &VIDIOC-QBUF; ioctl. Although buffers are commonly cycled, applications can pass different addresses and sizes at each VIDIOC_QBUF call. If required by the hardware the @@ -396,11 +482,18 @@ rest should be evident. Buffers A buffer contains data exchanged by application and -driver using one of the Streaming I/O methods. Only pointers to -buffers are exchanged, the data itself is not copied. These pointers, -together with meta-information like timestamps or field parity, are -stored in a struct v4l2_buffer, argument to -the &VIDIOC-QUERYBUF;, &VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl. +driver using one of the Streaming I/O methods. In the multi-planar API, the +data is held in planes, while the buffer structure acts as a container +for the planes. Only pointers to buffers (planes) are exchanged, the data +itself is not copied. These pointers, together with meta-information like +timestamps or field parity, are stored in a struct +v4l2_buffer, argument to +the &VIDIOC-QUERYBUF;, &VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl. +In the multi-planar API, some plane-specific members of struct +v4l2_buffer, such as pointers and sizes for each +plane, are stored in struct v4l2_plane instead. +In that case, struct v4l2_buffer contains an array of +plane structures. Nominally timestamps refer to the first data byte transmitted. In practice however the wide range of hardware covered by the V4L2 API @@ -551,26 +644,40 @@ in accordance with the selected I/O method. __u32 offset - When memory is -V4L2_MEMORY_MMAP this is the offset of the buffer -from the start of the device memory. The value is returned by the -driver and apart of serving as parameter to the &func-mmap; function -not useful for applications. See for details. + For the single-planar API and when +memory is V4L2_MEMORY_MMAP this +is the offset of the buffer from the start of the device memory. The value is +returned by the driver and apart of serving as parameter to the &func-mmap; +function not useful for applications. See for details + unsigned long userptr - When memory is -V4L2_MEMORY_USERPTR this is a pointer to the -buffer (casted to unsigned long type) in virtual memory, set by the -application. See for details. + For the single-planar API and when +memory is V4L2_MEMORY_USERPTR +this is a pointer to the buffer (casted to unsigned long type) in virtual +memory, set by the application. See for details. + + + + + struct v4l2_plane + *planes + When using the multi-planar API, contains a userspace pointer + to an array of &v4l2-plane;. The size of the array should be put + in the length field of this + v4l2_buffer structure. __u32 length - Size of the buffer (not the payload) in bytes. + Size of the buffer (not the payload) in bytes for the + single-planar API. For the multi-planar API should contain the + number of elements in the planes array. + __u32 @@ -596,6 +703,66 @@ should set this to 0. + + struct <structname>v4l2_plane</structname> + + &cs-ustr; + + + __u32 + bytesused + + The number of bytes occupied by data in the plane + (its payload). + + + __u32 + length + + Size in bytes of the plane (not its payload). + + + union + m + + + + + + __u32 + mem_offset + When the memory type in the containing &v4l2-buffer; is + V4L2_MEMORY_MMAP, this is the value that + should be passed to &func-mmap;, similar to the + offset field in &v4l2-buffer;. + + + + __unsigned long + userptr + When the memory type in the containing &v4l2-buffer; is + V4L2_MEMORY_USERPTR, this is a userspace + pointer to the memory allocated for this plane by an application. + + + + __u32 + data_offset + + Offset in bytes to video data in the plane, if applicable. + + + + __u32 + reserved[11] + + Reserved for future use. Should be zeroed by an + application. + + + +
+ enum v4l2_buf_type @@ -604,13 +771,27 @@ should set this to 0. V4L2_BUF_TYPE_VIDEO_CAPTURE 1 - Buffer of a video capture stream, see Buffer of a single-planar video capture stream, see . + + + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + + 9 + Buffer of a multi-planar video capture stream, see . V4L2_BUF_TYPE_VIDEO_OUTPUT 2 - Buffer of a video output stream, see Buffer of a single-planar video output stream, see . + + + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE + + 10 + Buffer of a multi-planar video output stream, see . diff --git a/Documentation/DocBook/v4l/pixfmt.xml b/Documentation/DocBook/v4l/pixfmt.xml index cfffc88d738..28f9c700f75 100644 --- a/Documentation/DocBook/v4l/pixfmt.xml +++ b/Documentation/DocBook/v4l/pixfmt.xml @@ -2,12 +2,16 @@ The V4L2 API was primarily designed for devices exchanging image data with applications. The -v4l2_pix_format structure defines the format -and layout of an image in memory. Image formats are negotiated with -the &VIDIOC-S-FMT; ioctl. (The explanations here focus on video +v4l2_pix_format and v4l2_pix_format_mplane + structures define the format and layout of an image in memory. +The former is used with the single-planar API, while the latter is used with the +multi-planar version (see ). Image formats are +negotiated with the &VIDIOC-S-FMT; ioctl. (The explanations here focus on video capturing and output, for overlay frame buffer formats see also &VIDIOC-G-FBUF;.) +
+ Single-planar format structure
struct <structname>v4l2_pix_format</structname> @@ -106,6 +110,98 @@ set this field to zero.
+
+ +
+ Multi-planar format structures + The v4l2_plane_pix_format structures define + size and layout for each of the planes in a multi-planar format. + The v4l2_pix_format_mplane structure contains + information common to all planes (such as image width and height) and + an array of v4l2_plane_pix_format structures, + describing all planes of that format. + + struct <structname>vl42_plane_pix_format</structname> + + &cs-str; + + + __u32 + sizeimage + Maximum size in bytes required for image data in this plane. + + + + __u16 + bytesperline + Distance in bytes between the leftmost pixels in two adjacent + lines. + + + __u16 + reserved[7] + Reserved for future extensions. Should be zeroed by the + application. + + + +
+ + struct <structname>v4l2_pix_format_mplane</structname> + + &cs-str; + + + __u32 + width + Image width in pixels. + + + __u32 + height + Image height in pixels. + + + __u32 + pixelformat + The pixel format. Both single- and multi-planar four character +codes can be used. + + + &v4l2-field; + field + See &v4l2-pix-format;. + + + &v4l2-colorspace; + colorspace + See &v4l2-pix-format;. + + + &v4l2-plane-pix-format; + plane_fmt[VIDEO_MAX_PLANES] + An array of structures describing format of each plane this + pixel format consists of. The number of valid entries in this array + has to be put in the num_planes + field. + + + __u8 + num_planes + Number of planes (i.e. separate memory buffers) for this format + and the number of valid entries in the + plane_fmt array. + + + __u8 + reserved[11] + Reserved for future extensions. Should be zeroed by the + application. + + + +
+
Standard Image Formats @@ -142,11 +238,19 @@ leftmost pixel of the second row from the top, and so on. The last row has just as many pad bytes after it as the other rows. In V4L2 each format has an identifier which looks like -PIX_FMT_XXX, defined in the videodev2.h -header file. These identifiers -represent four character codes +PIX_FMT_XXX, defined in the videodev.h header file. These identifiers +represent four character (FourCC) codes which are also listed below, however they are not the same as those used in the Windows world. + + For some formats, data is stored in separate, discontiguous +memory buffers. Those formats are identified by a separate set of FourCC codes +and are referred to as "multi-planar formats". For example, a YUV422 frame is +normally stored in one memory buffer, but it can also be placed in two or three +separate buffers, with Y component in one buffer and CbCr components in another +in the 2-planar version or with each component in its own buffer in the +3-planar case. Those sub-buffers are referred to as "planes".
diff --git a/Documentation/DocBook/v4l/planar-apis.xml b/Documentation/DocBook/v4l/planar-apis.xml new file mode 100644 index 00000000000..8be7552b37d --- /dev/null +++ b/Documentation/DocBook/v4l/planar-apis.xml @@ -0,0 +1,81 @@ +
+ Single- and multi-planar APIs + + Some devices require data for each input or output video frame + to be placed in discontiguous memory buffers. In such cases one + video frame has to be addressed using more than one memory address, i.e. one + pointer per "plane". A plane is a sub-buffer of current frame. For examples + of such formats see . + + Initially, V4L2 API did not support multi-planar buffers and a set of + extensions has been introduced to handle them. Those extensions constitute + what is being referred to as the "multi-planar API". + + Some of the V4L2 API calls and structures are interpreted differently, + depending on whether single- or multi-planar API is being used. An application + can choose whether to use one or the other by passing a corresponding buffer + type to its ioctl calls. Multi-planar versions of buffer types are suffixed with + an `_MPLANE' string. For a list of available multi-planar buffer types + see &v4l2-buf-type;. + + +
+ Multi-planar formats + Multi-planar API introduces new multi-planar formats. Those formats + use a separate set of FourCC codes. It is important to distinguish between + the multi-planar API and a multi-planar format. Multi-planar API calls can + handle all single-planar formats as well, while the single-planar API cannot + handle multi-planar formats. Applications do not have to switch between APIs + when handling both single- and multi-planar devices and should use the + multi-planar API version for both single- and multi-planar formats. + Drivers that do not support multi-planar API can still be handled with it, + utilizing a compatibility layer built into standard V4L2 ioctl handling. + +
+ +
+ Single and multi-planar API compatibility layer + In most casesThe compatibility layer does not cover + drivers that do not use video_ioctl2() call., applications + can use the multi-planar API with older drivers that support + only its single-planar version and vice versa. Appropriate conversion is + done seamlessly for both applications and drivers in the V4L2 core. The + general rule of thumb is: as long as an application uses formats that + a driver supports, it can use either API (although use of multi-planar + formats is only possible with the multi-planar API). The list of formats + supported by a driver can be obtained using the &VIDIOC-ENUM-FMT; call. + It is possible, but discouraged, for a driver or an application to support + and use both versions of the API. +
+ +
+ Calls that distinguish between single and multi-planar APIs + + + &VIDIOC-QUERYCAP; + Two additional multi-planar capabilities are added. They can + be set together with non-multi-planar ones for devices that handle + both single- and multi-planar formats. + + + &VIDIOC-G-FMT;, &VIDIOC-S-FMT;, &VIDIOC-TRY-FMT; + New structures for describing multi-planar formats are added: + &v4l2-pix-format-mplane; and &v4l2-plane-pix-format;. Drivers may + define new multi-planar formats, which have distinct FourCC codes from + the existing single-planar ones. + + + + &VIDIOC-QBUF;, &VIDIOC-DQBUF;, &VIDIOC-QUERYBUF; + A new &v4l2-plane; structure for describing planes is added. + Arrays of this structure are passed in the new + m.planes field of &v4l2-buffer;. + + + + &VIDIOC-REQBUFS; + Will allocate multi-planar buffers as requested. + + +
+
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 9288af96de3..9c7a1751ba1 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -85,6 +85,17 @@ Remote Controller chapter. + + + Pawel + Osciak + Designed and documented the multi-planar API. + +
+ pawel AT osciak.com +
+
+
@@ -102,7 +113,8 @@ Remote Controller chapter. 2010 2011 Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin -Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab +Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab, + Pawel Osciak Except when explicitly stated as GPL, programming examples within @@ -115,6 +127,13 @@ structs, ioctls) must be noted in more detail in the history chapter (compat.xml), along with the possible impact on existing drivers and applications. --> + + 2.6.38 + po + Added the multi-planar API. + + + 2.6.37 2010-08-06 diff --git a/Documentation/DocBook/v4l/vidioc-enum-fmt.xml b/Documentation/DocBook/v4l/vidioc-enum-fmt.xml index 960d44615ca..71d373b6d36 100644 --- a/Documentation/DocBook/v4l/vidioc-enum-fmt.xml +++ b/Documentation/DocBook/v4l/vidioc-enum-fmt.xml @@ -76,7 +76,9 @@ pixelformat field. Type of the data stream, set by the application. Only these types are valid here: V4L2_BUF_TYPE_VIDEO_CAPTURE, +V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_BUF_TYPE_VIDEO_OUTPUT, +V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_BUF_TYPE_VIDEO_OVERLAY, and custom (driver defined) types with code V4L2_BUF_TYPE_PRIVATE and higher. diff --git a/Documentation/DocBook/v4l/vidioc-g-fmt.xml b/Documentation/DocBook/v4l/vidioc-g-fmt.xml index 7c7d1b72c40..a4ae59b664e 100644 --- a/Documentation/DocBook/v4l/vidioc-g-fmt.xml +++ b/Documentation/DocBook/v4l/vidioc-g-fmt.xml @@ -60,11 +60,13 @@ application. type field of a struct v4l2_format to the respective buffer (stream) type. For example video capture devices use -V4L2_BUF_TYPE_VIDEO_CAPTURE. When the application +V4L2_BUF_TYPE_VIDEO_CAPTURE or +V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE. When the application calls the VIDIOC_G_FMT ioctl with a pointer to this structure the driver fills the respective member of the fmt union. In case of video capture devices -that is the &v4l2-pix-format; pix member. +that is either the &v4l2-pix-format; pix or +the &v4l2-pix-format-mplane; pix_mp member. When the requested buffer type is not supported drivers return an &EINVAL;. @@ -131,6 +133,15 @@ this ioctl. Definition of an image format, see , used by video capture and output devices. + + + + &v4l2-pix-format-mplane; + pix_mp + Definition of an image format, see , used by video capture and output +devices that support the multi-planar +version of the API. diff --git a/Documentation/DocBook/v4l/vidioc-qbuf.xml b/Documentation/DocBook/v4l/vidioc-qbuf.xml index ab691ebf3b9..f2b11f8a403 100644 --- a/Documentation/DocBook/v4l/vidioc-qbuf.xml +++ b/Documentation/DocBook/v4l/vidioc-qbuf.xml @@ -64,7 +64,8 @@ zero to the number of buffers allocated with &VIDIOC-REQBUFS; contents of the struct v4l2_buffer returned by a &VIDIOC-QUERYBUF; ioctl will do as well. When the buffer is intended for output (type is -V4L2_BUF_TYPE_VIDEO_OUTPUT or +V4L2_BUF_TYPE_VIDEO_OUTPUT, +V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, or V4L2_BUF_TYPE_VBI_OUTPUT) applications must also initialize the bytesused, field and @@ -75,7 +76,11 @@ supports capturing from specific video inputs and you want to specify a video input, then flags should be set to V4L2_BUF_FLAG_INPUT and the field input must be initialized to the desired input. -The reserved field must be set to 0. +The reserved field must be set to 0. When using +the multi-planar API, the +m.planes field must contain a userspace pointer +to a filled-in array of &v4l2-plane; and the length +field must be set to the number of elements in that array. To enqueue a memory mapped @@ -93,10 +98,13 @@ structure the driver sets the buffer applications set the memory field to V4L2_MEMORY_USERPTR, the m.userptr field to the address of the -buffer and length to its size. -When VIDIOC_QBUF is called with a pointer to this -structure the driver sets the V4L2_BUF_FLAG_QUEUED -flag and clears the V4L2_BUF_FLAG_MAPPED and +buffer and length to its size. When the multi-planar +API is used, m.userptr and +length members of the passed array of &v4l2-plane; +have to be used instead. When VIDIOC_QBUF is called with +a pointer to this structure the driver sets the +V4L2_BUF_FLAG_QUEUED flag and clears the +V4L2_BUF_FLAG_MAPPED and V4L2_BUF_FLAG_DONE flags in the flags field, or it returns an error code. This ioctl locks the memory pages of the buffer in physical memory, @@ -115,7 +123,9 @@ remaining fields or returns an error code. The driver may also set V4L2_BUF_FLAG_ERROR in the flags field. It indicates a non-critical (recoverable) streaming error. In such case the application may continue as normal, but should be aware that data in the -dequeued buffer might be corrupted. +dequeued buffer might be corrupted. When using the multi-planar API, the +planes array does not have to be passed; the m.planes +member must be set to NULL in that case. By default VIDIOC_DQBUF blocks when no buffer is in the outgoing queue. When the diff --git a/Documentation/DocBook/v4l/vidioc-querybuf.xml b/Documentation/DocBook/v4l/vidioc-querybuf.xml index e649805a490..5c104d42d31 100644 --- a/Documentation/DocBook/v4l/vidioc-querybuf.xml +++ b/Documentation/DocBook/v4l/vidioc-querybuf.xml @@ -61,6 +61,10 @@ buffer at any time after buffers have been allocated with the to the number of buffers allocated with &VIDIOC-REQBUFS; (&v4l2-requestbuffers; count) minus one. The reserved field should to set to 0. +When using the multi-planar API, the +m.planes field must contain a userspace pointer to an +array of &v4l2-plane; and the length field has +to be set to the number of elements in that array. After calling VIDIOC_QUERYBUF with a pointer to this structure drivers return an error code or fill the rest of the structure. @@ -70,11 +74,13 @@ the structure. V4L2_BUF_FLAG_QUEUED and V4L2_BUF_FLAG_DONE flags will be valid. The memory field will be set to the current -I/O method, the m.offset +I/O method. For the single-planar API, the m.offset contains the offset of the buffer from the start of the device memory, -the length field its size. The driver may -or may not set the remaining fields and flags, they are meaningless in -this context. +the length field its size. For the multi-planar API, +fields m.mem_offset and +length in the m.planes +array elements will be used instead. The driver may or may not set the remaining +fields and flags, they are meaningless in this context. The v4l2_buffer structure is specified in . diff --git a/Documentation/DocBook/v4l/vidioc-querycap.xml b/Documentation/DocBook/v4l/vidioc-querycap.xml index d499da93a45..93699769cd0 100644 --- a/Documentation/DocBook/v4l/vidioc-querycap.xml +++ b/Documentation/DocBook/v4l/vidioc-querycap.xml @@ -142,14 +142,30 @@ this array to zero. V4L2_CAP_VIDEO_CAPTURE 0x00000001 - The device supports the Video Capture interface. + The device supports single-planar formats through the Video Capture interface. An application can use either +the single or the multi-planar API. + + + V4L2_CAP_VIDEO_CAPTURE_MPLANE + 0x00001000 + The device supports multi-planar formats through the Video Capture interface. An application has to use the +multi-planar API. V4L2_CAP_VIDEO_OUTPUT 0x00000002 - The device supports the Video Output interface. + The device supports single-planar formats through the Video Output interface. An application can use either +the single or the multi-planar API. + + + V4L2_CAP_VIDEO_OUTPUT_MPLANE + 0x00002000 + The device supports multi-planar formats through the Video Output interface. An application has to use the +multi-planar API. V4L2_CAP_VIDEO_OVERLAY -- cgit v1.2.3-70-g09d2 From 269da4027c9a3466150308a9fe5f2a3a58336cd8 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 9 Jan 2011 09:01:10 -0300 Subject: [media] v4l: Add DocBook documentation for YU12M, NV12M image formats Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 4 + Documentation/DocBook/v4l/pixfmt-nv12m.xml | 154 +++++++++++++++++++++++++ Documentation/DocBook/v4l/pixfmt-yuv420m.xml | 162 +++++++++++++++++++++++++++ Documentation/DocBook/v4l/pixfmt.xml | 2 + 4 files changed, 322 insertions(+) create mode 100644 Documentation/DocBook/v4l/pixfmt-nv12m.xml create mode 100644 Documentation/DocBook/v4l/pixfmt-yuv420m.xml (limited to 'Documentation') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index 74923d74553..d2f99e5a3a2 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -237,6 +237,7 @@ + @@ -251,6 +252,7 @@ + @@ -337,6 +339,7 @@ + @@ -351,6 +354,7 @@ + diff --git a/Documentation/DocBook/v4l/pixfmt-nv12m.xml b/Documentation/DocBook/v4l/pixfmt-nv12m.xml new file mode 100644 index 00000000000..c9e166d9ded --- /dev/null +++ b/Documentation/DocBook/v4l/pixfmt-nv12m.xml @@ -0,0 +1,154 @@ + + + V4L2_PIX_FMT_NV12M ('NV12M') + &manvol; + + + V4L2_PIX_FMT_NV12M + Variation of V4L2_PIX_FMT_NV12 with planes + non contiguous in memory. + + + Description + + This is a multi-planar, two-plane version of the YUV 4:2:0 format. +The three components are separated into two sub-images or planes. +V4L2_PIX_FMT_NV12M differs from V4L2_PIX_FMT_NV12 + in that the two planes are non-contiguous in memory, i.e. the chroma +plane do not necessarily immediately follows the luma plane. +The luminance data occupies the first plane. The Y plane has one byte per pixel. +In the second plane there is a chrominance data with alternating chroma samples. +The CbCr plane is the same width, in bytes, as the Y plane (and of the image), +but is half as tall in pixels. Each CbCr pair belongs to four pixels. For example, +Cb0/Cr0 belongs to +Y'00, Y'01, +Y'10, Y'11. + + V4L2_PIX_FMT_NV12M is intended to be +used only in drivers and applications that support the multi-planar API, +described in . + + If the Y plane has pad bytes after each row, then the +CbCr plane has as many pad bytes after its rows. + + + <constant>V4L2_PIX_FMT_NV12M</constant> 4 × 4 pixel image + + + Byte Order. + Each cell is one byte. + + + + + + start0 + 0: + Y'00 + Y'01 + Y'02 + Y'03 + + + start0 + 4: + Y'10 + Y'11 + Y'12 + Y'13 + + + start0 + 8: + Y'20 + Y'21 + Y'22 + Y'23 + + + start0 + 12: + Y'30 + Y'31 + Y'32 + Y'33 + + + + + + start1 + 0: + Cb00 + Cr00 + Cb01 + Cr01 + + + start1 + 4: + Cb10 + Cr10 + Cb11 + Cr11 + + + + + + + + + Color Sample Location. + + + + + + + 01 + 23 + + + 0 + YY + YY + + + + C + C + + + 1 + YY + YY + + + + + + 2 + YY + YY + + + + C + C + + + 3 + YY + YY + + + + + + + + + + + diff --git a/Documentation/DocBook/v4l/pixfmt-yuv420m.xml b/Documentation/DocBook/v4l/pixfmt-yuv420m.xml new file mode 100644 index 00000000000..f5d8f57495c --- /dev/null +++ b/Documentation/DocBook/v4l/pixfmt-yuv420m.xml @@ -0,0 +1,162 @@ + + + V4L2_PIX_FMT_YUV420M ('YU12M') + &manvol; + + + V4L2_PIX_FMT_YUV420M + Variation of V4L2_PIX_FMT_YUV420 + with planes non contiguous in memory. + + + + Description + + This is a multi-planar format, as opposed to a packed format. +The three components are separated into three sub- images or planes. + +The Y plane is first. The Y plane has one byte per pixel. The Cb data +constitutes the second plane which is half the width and half +the height of the Y plane (and of the image). Each Cb belongs to four +pixels, a two-by-two square of the image. For example, +Cb0 belongs to Y'00, +Y'01, Y'10, and +Y'11. The Cr data, just like the Cb plane, is +in the third plane. + + If the Y plane has pad bytes after each row, then the Cb +and Cr planes have half as many pad bytes after their rows. In other +words, two Cx rows (including padding) is exactly as long as one Y row +(including padding). + + V4L2_PIX_FMT_NV12M is intended to be +used only in drivers and applications that support the multi-planar API, +described in . + + + <constant>V4L2_PIX_FMT_YVU420M</constant> 4 × 4 +pixel image + + + Byte Order. + Each cell is one byte. + + + + + + start0 + 0: + Y'00 + Y'01 + Y'02 + Y'03 + + + start0 + 4: + Y'10 + Y'11 + Y'12 + Y'13 + + + start0 + 8: + Y'20 + Y'21 + Y'22 + Y'23 + + + start0 + 12: + Y'30 + Y'31 + Y'32 + Y'33 + + + + start1 + 0: + Cb00 + Cb01 + + + start1 + 2: + Cb10 + Cb11 + + + + start2 + 0: + Cr00 + Cr01 + + + start2 + 2: + Cr10 + Cr11 + + + + + + + + + Color Sample Location. + + + + + + + 01 + 23 + + + 0 + YY + YY + + + + C + C + + + 1 + YY + YY + + + + + + 2 + YY + YY + + + + C + C + + + 3 + YY + YY + + + + + + + + + + + diff --git a/Documentation/DocBook/v4l/pixfmt.xml b/Documentation/DocBook/v4l/pixfmt.xml index 28f9c700f75..f8436dcb741 100644 --- a/Documentation/DocBook/v4l/pixfmt.xml +++ b/Documentation/DocBook/v4l/pixfmt.xml @@ -703,10 +703,12 @@ information. &sub-vyuy; &sub-y41p; &sub-yuv420; + &sub-yuv420m; &sub-yuv410; &sub-yuv422p; &sub-yuv411p; &sub-nv12; + &sub-nv12m; &sub-nv16;
-- cgit v1.2.3-70-g09d2 From f33de4aa24646b445f4dd52ebd57e322730644b2 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Mon, 10 Jan 2011 06:36:19 -0300 Subject: [media] get_dvb_firmware: ngene_18.fw added Add download link for ngene firmware rev 18. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- Documentation/dvb/get_dvb_firmware | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index 59690de8ebf..3348d313fbe 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -556,6 +556,9 @@ sub ngene { my $hash1 = "d798d5a757121174f0dbc5f2833c0c85"; my $file2 = "ngene_17.fw"; my $hash2 = "26b687136e127b8ac24b81e0eeafc20b"; + my $url2 = "http://l4m-daten.de/downloads/firmware/dvb-s2/linux/all/"; + my $file3 = "ngene_18.fw"; + my $hash3 = "ebce3ea769a53e3e0b0197c3b3f127e3"; checkstandard(); @@ -565,7 +568,10 @@ sub ngene { wgetfile($file2, $url . $file2); verify($file2, $hash2); - "$file1, $file2"; + wgetfile($file3, $url2 . $file3); + verify($file3, $hash3); + + "$file1, $file2, $file3"; } sub az6027{ -- cgit v1.2.3-70-g09d2 From db4d56835e07ec793f143431170ba2fc17bf0191 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 16 Jan 2011 17:21:02 -0300 Subject: [media] DocBook/v4l: fix validation errors Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/planar-apis.xml | 14 +++++++------- Documentation/DocBook/v4l/v4l2.xml | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/planar-apis.xml b/Documentation/DocBook/v4l/planar-apis.xml index 8be7552b37d..7f3f5527057 100644 --- a/Documentation/DocBook/v4l/planar-apis.xml +++ b/Documentation/DocBook/v4l/planar-apis.xml @@ -53,28 +53,28 @@ &VIDIOC-QUERYCAP; - Two additional multi-planar capabilities are added. They can + Two additional multi-planar capabilities are added. They can be set together with non-multi-planar ones for devices that handle - both single- and multi-planar formats. + both single- and multi-planar formats. &VIDIOC-G-FMT;, &VIDIOC-S-FMT;, &VIDIOC-TRY-FMT; - New structures for describing multi-planar formats are added: + New structures for describing multi-planar formats are added: &v4l2-pix-format-mplane; and &v4l2-plane-pix-format;. Drivers may define new multi-planar formats, which have distinct FourCC codes from - the existing single-planar ones. + the existing single-planar ones. &VIDIOC-QBUF;, &VIDIOC-DQBUF;, &VIDIOC-QUERYBUF; - A new &v4l2-plane; structure for describing planes is added. + A new &v4l2-plane; structure for describing planes is added. Arrays of this structure are passed in the new - m.planes field of &v4l2-buffer;. + m.planes field of &v4l2-buffer;. &VIDIOC-REQBUFS; - Will allocate multi-planar buffers as requested. + Will allocate multi-planar buffers as requested. diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 9c7a1751ba1..c3d699173c1 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -129,6 +129,7 @@ applications. --> 2.6.38 + 2011-01-16 po Added the multi-planar API. -- cgit v1.2.3-70-g09d2 From d39155d91d034e2b2c9154892e29c8a8eb193b7f Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Sun, 16 Jan 2011 13:53:31 -0300 Subject: [media] Remove compatibility layer from multi-planar API documentation This feature will probably be moved to libv4l2. Signed-off-by: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/planar-apis.xml | 35 ++++++--------------------- Documentation/DocBook/v4l/vidioc-querycap.xml | 22 ++++++++--------- 2 files changed, 18 insertions(+), 39 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/planar-apis.xml b/Documentation/DocBook/v4l/planar-apis.xml index 7f3f5527057..878ce204048 100644 --- a/Documentation/DocBook/v4l/planar-apis.xml +++ b/Documentation/DocBook/v4l/planar-apis.xml @@ -2,10 +2,10 @@ Single- and multi-planar APIs Some devices require data for each input or output video frame - to be placed in discontiguous memory buffers. In such cases one + to be placed in discontiguous memory buffers. In such cases, one video frame has to be addressed using more than one memory address, i.e. one - pointer per "plane". A plane is a sub-buffer of current frame. For examples - of such formats see . + pointer per "plane". A plane is a sub-buffer of the current frame. For + examples of such formats see . Initially, V4L2 API did not support multi-planar buffers and a set of extensions has been introduced to handle them. Those extensions constitute @@ -14,8 +14,8 @@ Some of the V4L2 API calls and structures are interpreted differently, depending on whether single- or multi-planar API is being used. An application can choose whether to use one or the other by passing a corresponding buffer - type to its ioctl calls. Multi-planar versions of buffer types are suffixed with - an `_MPLANE' string. For a list of available multi-planar buffer types + type to its ioctl calls. Multi-planar versions of buffer types are suffixed + with an `_MPLANE' string. For a list of available multi-planar buffer types see &v4l2-buf-type;. @@ -24,28 +24,9 @@ Multi-planar API introduces new multi-planar formats. Those formats use a separate set of FourCC codes. It is important to distinguish between the multi-planar API and a multi-planar format. Multi-planar API calls can - handle all single-planar formats as well, while the single-planar API cannot - handle multi-planar formats. Applications do not have to switch between APIs - when handling both single- and multi-planar devices and should use the - multi-planar API version for both single- and multi-planar formats. - Drivers that do not support multi-planar API can still be handled with it, - utilizing a compatibility layer built into standard V4L2 ioctl handling. - - - -
- Single and multi-planar API compatibility layer - In most casesThe compatibility layer does not cover - drivers that do not use video_ioctl2() call., applications - can use the multi-planar API with older drivers that support - only its single-planar version and vice versa. Appropriate conversion is - done seamlessly for both applications and drivers in the V4L2 core. The - general rule of thumb is: as long as an application uses formats that - a driver supports, it can use either API (although use of multi-planar - formats is only possible with the multi-planar API). The list of formats - supported by a driver can be obtained using the &VIDIOC-ENUM-FMT; call. - It is possible, but discouraged, for a driver or an application to support - and use both versions of the API. + handle all single-planar formats as well (as long as they are passed in + multi-planar API structures), while the single-planar API cannot + handle multi-planar formats.
diff --git a/Documentation/DocBook/v4l/vidioc-querycap.xml b/Documentation/DocBook/v4l/vidioc-querycap.xml index 93699769cd0..f29f1b86213 100644 --- a/Documentation/DocBook/v4l/vidioc-querycap.xml +++ b/Documentation/DocBook/v4l/vidioc-querycap.xml @@ -142,30 +142,28 @@ this array to zero. V4L2_CAP_VIDEO_CAPTURE 0x00000001 - The device supports single-planar formats through the Video Capture interface. An application can use either -the single or the multi-planar API. + The device supports the single-planar API through the Video Capture interface. V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000 - The device supports multi-planar formats through the Video Capture interface. An application has to use the -multi-planar API. + The device supports the + multi-planar API through the + Video Capture interface. V4L2_CAP_VIDEO_OUTPUT 0x00000002 - The device supports single-planar formats through the Video Output interface. An application can use either -the single or the multi-planar API. + The device supports the single-planar API through the Video Output interface. V4L2_CAP_VIDEO_OUTPUT_MPLANE 0x00002000 - The device supports multi-planar formats through the Video Output interface. An application has to use the -multi-planar API. + The device supports the + multi-planar API through the + Video Output interface. V4L2_CAP_VIDEO_OVERLAY -- cgit v1.2.3-70-g09d2 From 458efe2d558b51fff38026e8ede9374899340e60 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Thu, 10 Feb 2011 10:11:04 -0300 Subject: [media] gspca - ov534: Add the webcam 06f8:3002 and sensor ov767x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/ov534.c | 518 +++++++++++++++++++++++++++++++----- 2 files changed, 459 insertions(+), 60 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 261776e0c5e..dc72fff2eb1 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -199,6 +199,7 @@ spca500 06bd:0404 Agfa CL20 spca500 06be:0800 Optimedia sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom spca506 06e1:a190 ADS Instant VCD +ov534 06f8:3002 Hercules Blog Webcam ov534_9 06f8:3003 Hercules Dualpix HD Weblog sonixj 06f8:3004 Hercules Classic Silver sonixj 06f8:3008 Hercules Deluxe Optical Glass diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index ee6c1df7602..8dada2b745b 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1,5 +1,5 @@ /* - * ov534-ov772x gspca driver + * ov534-ov7xxx gspca driver * * Copyright (C) 2008 Antonio Ospite * Copyright (C) 2008 Jim Paris @@ -75,6 +75,12 @@ struct sd { u16 last_fid; u8 frame_rate; + u8 sensor; +}; +enum sensors { + SENSOR_OV767x, + SENSOR_OV772x, + NSENSORS }; /* V4L2 controls supported by the driver */ @@ -239,6 +245,16 @@ static const struct v4l2_pix_format ov772x_mode[] = { .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0}, }; +static const struct v4l2_pix_format ov767x_mode[] = { + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG}, + {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG}, +}; static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30}; static const u8 vga_rates[] = {60, 50, 40, 30, 15}; @@ -254,7 +270,288 @@ static const struct framerates ov772x_framerates[] = { }, }; -static const u8 bridge_init[][2] = { +struct reg_array { + const u8 (*val)[2]; + int len; +}; + +static const u8 bridge_init_767x[][2] = { +/* comments from the ms-win file apollo7670.set */ +/* str1 */ + {0xf1, 0x42}, + {0x88, 0xf8}, + {0x89, 0xff}, + {0x76, 0x03}, + {0x92, 0x03}, + {0x95, 0x10}, + {0xe2, 0x00}, + {0xe7, 0x3e}, + {0x8d, 0x1c}, + {0x8e, 0x00}, + {0x8f, 0x00}, + {0x1f, 0x00}, + {0xc3, 0xf9}, + {0x89, 0xff}, + {0x88, 0xf8}, + {0x76, 0x03}, + {0x92, 0x01}, + {0x93, 0x18}, + {0x1c, 0x00}, + {0x1d, 0x48}, + {0x1d, 0x00}, + {0x1d, 0xff}, + {0x1d, 0x02}, + {0x1d, 0x58}, + {0x1d, 0x00}, + {0x1c, 0x0a}, + {0x1d, 0x0a}, + {0x1d, 0x0e}, + {0xc0, 0x50}, /* HSize 640 */ + {0xc1, 0x3c}, /* VSize 480 */ + {0x34, 0x05}, /* enable Audio Suspend mode */ + {0xc2, 0x0c}, /* Input YUV */ + {0xc3, 0xf9}, /* enable PRE */ + {0x34, 0x05}, /* enable Audio Suspend mode */ + {0xe7, 0x2e}, /* this solves failure of "SuspendResumeTest" */ + {0x31, 0xf9}, /* enable 1.8V Suspend */ + {0x35, 0x02}, /* turn on JPEG */ + {0xd9, 0x10}, + {0x25, 0x42}, /* GPIO[8]:Input */ + {0x94, 0x11}, /* If the default setting is loaded when + * system boots up, this flag is closed here */ +}; +static const u8 sensor_init_767x[][2] = { + {0x12, 0x80}, + {0x11, 0x03}, + {0x3a, 0x04}, + {0x12, 0x00}, + {0x17, 0x13}, + {0x18, 0x01}, + {0x32, 0xb6}, + {0x19, 0x02}, + {0x1a, 0x7a}, + {0x03, 0x0a}, + {0x0c, 0x00}, + {0x3e, 0x00}, + {0x70, 0x3a}, + {0x71, 0x35}, + {0x72, 0x11}, + {0x73, 0xf0}, + {0xa2, 0x02}, + {0x7a, 0x2a}, /* set Gamma=1.6 below */ + {0x7b, 0x12}, + {0x7c, 0x1d}, + {0x7d, 0x2d}, + {0x7e, 0x45}, + {0x7f, 0x50}, + {0x80, 0x59}, + {0x81, 0x62}, + {0x82, 0x6b}, + {0x83, 0x73}, + {0x84, 0x7b}, + {0x85, 0x8a}, + {0x86, 0x98}, + {0x87, 0xb2}, + {0x88, 0xca}, + {0x89, 0xe0}, + {0x13, 0xe0}, + {0x00, 0x00}, + {0x10, 0x00}, + {0x0d, 0x40}, + {0x14, 0x38}, /* gain max 16x */ + {0xa5, 0x05}, + {0xab, 0x07}, + {0x24, 0x95}, + {0x25, 0x33}, + {0x26, 0xe3}, + {0x9f, 0x78}, + {0xa0, 0x68}, + {0xa1, 0x03}, + {0xa6, 0xd8}, + {0xa7, 0xd8}, + {0xa8, 0xf0}, + {0xa9, 0x90}, + {0xaa, 0x94}, + {0x13, 0xe5}, + {0x0e, 0x61}, + {0x0f, 0x4b}, + {0x16, 0x02}, + {0x21, 0x02}, + {0x22, 0x91}, + {0x29, 0x07}, + {0x33, 0x0b}, + {0x35, 0x0b}, + {0x37, 0x1d}, + {0x38, 0x71}, + {0x39, 0x2a}, + {0x3c, 0x78}, + {0x4d, 0x40}, + {0x4e, 0x20}, + {0x69, 0x00}, + {0x6b, 0x4a}, + {0x74, 0x10}, + {0x8d, 0x4f}, + {0x8e, 0x00}, + {0x8f, 0x00}, + {0x90, 0x00}, + {0x91, 0x00}, + {0x96, 0x00}, + {0x9a, 0x80}, + {0xb0, 0x84}, + {0xb1, 0x0c}, + {0xb2, 0x0e}, + {0xb3, 0x82}, + {0xb8, 0x0a}, + {0x43, 0x0a}, + {0x44, 0xf0}, + {0x45, 0x34}, + {0x46, 0x58}, + {0x47, 0x28}, + {0x48, 0x3a}, + {0x59, 0x88}, + {0x5a, 0x88}, + {0x5b, 0x44}, + {0x5c, 0x67}, + {0x5d, 0x49}, + {0x5e, 0x0e}, + {0x6c, 0x0a}, + {0x6d, 0x55}, + {0x6e, 0x11}, + {0x6f, 0x9f}, + {0x6a, 0x40}, + {0x01, 0x40}, + {0x02, 0x40}, + {0x13, 0xe7}, + {0x4f, 0x80}, + {0x50, 0x80}, + {0x51, 0x00}, + {0x52, 0x22}, + {0x53, 0x5e}, + {0x54, 0x80}, + {0x58, 0x9e}, + {0x41, 0x08}, + {0x3f, 0x00}, + {0x75, 0x04}, + {0x76, 0xe1}, + {0x4c, 0x00}, + {0x77, 0x01}, + {0x3d, 0xc2}, + {0x4b, 0x09}, + {0xc9, 0x60}, + {0x41, 0x38}, /* jfm: auto sharpness + auto de-noise */ + {0x56, 0x40}, + {0x34, 0x11}, + {0x3b, 0xc2}, + {0xa4, 0x8a}, /* Night mode trigger point */ + {0x96, 0x00}, + {0x97, 0x30}, + {0x98, 0x20}, + {0x99, 0x20}, + {0x9a, 0x84}, + {0x9b, 0x29}, + {0x9c, 0x03}, + {0x9d, 0x4c}, + {0x9e, 0x3f}, + {0x78, 0x04}, + {0x79, 0x01}, + {0xc8, 0xf0}, + {0x79, 0x0f}, + {0xc8, 0x00}, + {0x79, 0x10}, + {0xc8, 0x7e}, + {0x79, 0x0a}, + {0xc8, 0x80}, + {0x79, 0x0b}, + {0xc8, 0x01}, + {0x79, 0x0c}, + {0xc8, 0x0f}, + {0x79, 0x0d}, + {0xc8, 0x20}, + {0x79, 0x09}, + {0xc8, 0x80}, + {0x79, 0x02}, + {0xc8, 0xc0}, + {0x79, 0x03}, + {0xc8, 0x20}, + {0x79, 0x26}, +}; +static const u8 bridge_start_vga_767x[][2] = { +/* str59 JPG */ + {0x94, 0xaa}, + {0xf1, 0x42}, + {0xe5, 0x04}, + {0xc0, 0x50}, + {0xc1, 0x3c}, + {0xc2, 0x0c}, + {0x35, 0x02}, /* turn on JPEG */ + {0xd9, 0x10}, + {0xda, 0x00}, /* for higher clock rate(30fps) */ + {0x34, 0x05}, /* enable Audio Suspend mode */ + {0xc3, 0xf9}, /* enable PRE */ + {0x8c, 0x00}, /* CIF VSize LSB[2:0] */ + {0x8d, 0x1c}, /* output YUV */ +/* {0x34, 0x05}, * enable Audio Suspend mode (?) */ + {0x50, 0x00}, /* H/V divider=0 */ + {0x51, 0xa0}, /* input H=640/4 */ + {0x52, 0x3c}, /* input V=480/4 */ + {0x53, 0x00}, /* offset X=0 */ + {0x54, 0x00}, /* offset Y=0 */ + {0x55, 0x00}, /* H/V size[8]=0 */ + {0x57, 0x00}, /* H-size[9]=0 */ + {0x5c, 0x00}, /* output size[9:8]=0 */ + {0x5a, 0xa0}, /* output H=640/4 */ + {0x5b, 0x78}, /* output V=480/4 */ + {0x1c, 0x0a}, + {0x1d, 0x0a}, + {0x94, 0x11}, +}; +static const u8 sensor_start_vga_767x[][2] = { + {0x11, 0x01}, + {0x1e, 0x04}, + {0x19, 0x02}, + {0x1a, 0x7a}, +}; +static const u8 bridge_start_qvga_767x[][2] = { +/* str86 JPG */ + {0x94, 0xaa}, + {0xf1, 0x42}, + {0xe5, 0x04}, + {0xc0, 0x80}, + {0xc1, 0x60}, + {0xc2, 0x0c}, + {0x35, 0x02}, /* turn on JPEG */ + {0xd9, 0x10}, + {0xc0, 0x50}, /* CIF HSize 640 */ + {0xc1, 0x3c}, /* CIF VSize 480 */ + {0x8c, 0x00}, /* CIF VSize LSB[2:0] */ + {0x8d, 0x1c}, /* output YUV */ + {0x34, 0x05}, /* enable Audio Suspend mode */ + {0xc2, 0x4c}, /* output YUV and Enable DCW */ + {0xc3, 0xf9}, /* enable PRE */ + {0x1c, 0x00}, /* indirect addressing */ + {0x1d, 0x48}, /* output YUV422 */ + {0x50, 0x89}, /* H/V divider=/2; plus DCW AVG */ + {0x51, 0xa0}, /* DCW input H=640/4 */ + {0x52, 0x78}, /* DCW input V=480/4 */ + {0x53, 0x00}, /* offset X=0 */ + {0x54, 0x00}, /* offset Y=0 */ + {0x55, 0x00}, /* H/V size[8]=0 */ + {0x57, 0x00}, /* H-size[9]=0 */ + {0x5c, 0x00}, /* DCW output size[9:8]=0 */ + {0x5a, 0x50}, /* DCW output H=320/4 */ + {0x5b, 0x3c}, /* DCW output V=240/4 */ + {0x1c, 0x0a}, + {0x1d, 0x0a}, + {0x94, 0x11}, +}; +static const u8 sensor_start_qvga_767x[][2] = { + {0x11, 0x01}, + {0x1e, 0x04}, + {0x19, 0x02}, + {0x1a, 0x7a}, +}; + +static const u8 bridge_init_772x[][2] = { { 0xc2, 0x0c }, { 0x88, 0xf8 }, { 0xc3, 0x69 }, @@ -312,7 +609,7 @@ static const u8 bridge_init[][2] = { { 0xc1, 0x3c }, { 0xc2, 0x0c }, }; -static const u8 sensor_init[][2] = { +static const u8 sensor_init_772x[][2] = { { 0x12, 0x80 }, { 0x11, 0x01 }, /*fixme: better have a delay?*/ @@ -405,7 +702,7 @@ static const u8 sensor_init[][2] = { { 0x8e, 0x00 }, /* De-noise threshold */ { 0x0c, 0xd0 } }; -static const u8 bridge_start_vga[][2] = { +static const u8 bridge_start_vga_772x[][2] = { {0x1c, 0x00}, {0x1d, 0x40}, {0x1d, 0x02}, @@ -416,7 +713,7 @@ static const u8 bridge_start_vga[][2] = { {0xc0, 0x50}, {0xc1, 0x3c}, }; -static const u8 sensor_start_vga[][2] = { +static const u8 sensor_start_vga_772x[][2] = { {0x12, 0x00}, {0x17, 0x26}, {0x18, 0xa0}, @@ -426,7 +723,7 @@ static const u8 sensor_start_vga[][2] = { {0x2c, 0xf0}, {0x65, 0x20}, }; -static const u8 bridge_start_qvga[][2] = { +static const u8 bridge_start_qvga_772x[][2] = { {0x1c, 0x00}, {0x1d, 0x40}, {0x1d, 0x02}, @@ -437,7 +734,7 @@ static const u8 bridge_start_qvga[][2] = { {0xc0, 0x28}, {0xc1, 0x1e}, }; -static const u8 sensor_start_qvga[][2] = { +static const u8 sensor_start_qvga_772x[][2] = { {0x12, 0x40}, {0x17, 0x3f}, {0x18, 0x50}, @@ -620,6 +917,8 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) {30, 0x04, 0x41, 0x04}, }; + if (sd->sensor != SENSOR_OV772x) + return; if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) { r = rate_0; i = ARRAY_SIZE(rate_0); @@ -643,15 +942,28 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int val; - sccb_reg_write(gspca_dev, 0x9b, sd->ctrls[BRIGHTNESS].val); + val = sd->ctrls[BRIGHTNESS].val; + if (sd->sensor == SENSOR_OV767x) { + if (val < 0) + val = 0x80 - val; + sccb_reg_write(gspca_dev, 0x55, val); /* bright */ + } else { + sccb_reg_write(gspca_dev, 0x9b, val); + } } static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + u8 val; - sccb_reg_write(gspca_dev, 0x9c, sd->ctrls[CONTRAST].val); + val = sd->ctrls[CONTRAST].val; + if (sd->sensor == SENSOR_OV767x) + sccb_reg_write(gspca_dev, 0x56, val); /* contras */ + else + sccb_reg_write(gspca_dev, 0x9c, val); } static void setgain(struct gspca_dev *gspca_dev) @@ -692,15 +1004,22 @@ static void setexposure(struct gspca_dev *gspca_dev) if (sd->ctrls[AEC].val) return; - /* 'val' is one byte and represents half of the exposure value we are - * going to set into registers, a two bytes value: - * - * MSB: ((u16) val << 1) >> 8 == val >> 7 - * LSB: ((u16) val << 1) & 0xff == val << 1 - */ val = sd->ctrls[EXPOSURE].val; - sccb_reg_write(gspca_dev, 0x08, val >> 7); - sccb_reg_write(gspca_dev, 0x10, val << 1); + if (sd->sensor == SENSOR_OV767x) { + + /* set only aec[9:2] */ + sccb_reg_write(gspca_dev, 0x10, val); /* aech */ + } else { + + /* 'val' is one byte and represents half of the exposure value + * we are going to set into registers, a two bytes value: + * + * MSB: ((u16) val << 1) >> 8 == val >> 7 + * LSB: ((u16) val << 1) & 0xff == val << 1 + */ + sccb_reg_write(gspca_dev, 0x08, val >> 7); + sccb_reg_write(gspca_dev, 0x10, val << 1); + } } static void setagc(struct gspca_dev *gspca_dev) @@ -729,12 +1048,14 @@ static void setawb(struct gspca_dev *gspca_dev) if (sd->ctrls[AWB].val) { sccb_reg_write(gspca_dev, 0x13, sccb_reg_read(gspca_dev, 0x13) | 0x02); - sccb_reg_write(gspca_dev, 0x63, + if (sd->sensor == SENSOR_OV772x) + sccb_reg_write(gspca_dev, 0x63, sccb_reg_read(gspca_dev, 0x63) | 0xc0); } else { sccb_reg_write(gspca_dev, 0x13, sccb_reg_read(gspca_dev, 0x13) & ~0x02); - sccb_reg_write(gspca_dev, 0x63, + if (sd->sensor == SENSOR_OV772x) + sccb_reg_write(gspca_dev, 0x63, sccb_reg_read(gspca_dev, 0x63) & ~0xc0); } } @@ -742,14 +1063,22 @@ static void setawb(struct gspca_dev *gspca_dev) static void setaec(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + u8 data; + data = sd->sensor == SENSOR_OV767x ? + 0x05 : /* agc + aec */ + 0x01; /* agc */ if (sd->ctrls[AEC].val) sccb_reg_write(gspca_dev, 0x13, - sccb_reg_read(gspca_dev, 0x13) | 0x01); + sccb_reg_read(gspca_dev, 0x13) | data); else { sccb_reg_write(gspca_dev, 0x13, - sccb_reg_read(gspca_dev, 0x13) & ~0x01); - setexposure(gspca_dev); + sccb_reg_read(gspca_dev, 0x13) & ~data); + if (sd->sensor == SENSOR_OV767x) + sd->ctrls[EXPOSURE].val = + sccb_reg_read(gspca_dev, 10); /* aech */ + else + setexposure(gspca_dev); } } @@ -768,23 +1097,37 @@ static void sethvflip(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; u8 val; - val = sccb_reg_read(gspca_dev, 0x0c); - val &= ~0xc0; - if (sd->ctrls[HFLIP].val == 0) - val |= 0x40; - if (sd->ctrls[VFLIP].val == 0) - val |= 0x80; - sccb_reg_write(gspca_dev, 0x0c, val); + if (sd->sensor == SENSOR_OV767x) { + val = sccb_reg_read(gspca_dev, 0x1e); /* mvfp */ + val &= ~0x30; + if (sd->ctrls[HFLIP].val) + val |= 0x20; + if (sd->ctrls[VFLIP].val) + val |= 0x10; + sccb_reg_write(gspca_dev, 0x1e, val); + } else { + val = sccb_reg_read(gspca_dev, 0x0c); + val &= ~0xc0; + if (sd->ctrls[HFLIP].val == 0) + val |= 0x40; + if (sd->ctrls[VFLIP].val == 0) + val |= 0x80; + sccb_reg_write(gspca_dev, 0x0c, val); + } } static void setlightfreq(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + u8 val; - if (sd->ctrls[LIGHTFREQ].val == 0) - sccb_reg_write(gspca_dev, 0x2b, 0x00); - else - sccb_reg_write(gspca_dev, 0x2b, 0x9e); + val = sd->ctrls[LIGHTFREQ].val ? 0x9e : 0x00; + if (sd->sensor == SENSOR_OV767x) { + sccb_reg_write(gspca_dev, 0x2a, 0x00); + if (val) + val = 0x9d; /* insert dummy to 25fps for 50Hz */ + } + sccb_reg_write(gspca_dev, 0x2b, val); } @@ -805,11 +1148,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = ov772x_mode; cam->nmodes = ARRAY_SIZE(ov772x_mode); - cam->mode_framerates = ov772x_framerates; - - cam->bulk = 1; - cam->bulk_size = 16384; - cam->bulk_nurbs = 2; sd->frame_rate = 30; @@ -819,7 +1157,16 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; u16 sensor_id; + static const struct reg_array bridge_init[NSENSORS] = { + [SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)}, + [SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)}, + }; + static const struct reg_array sensor_init[NSENSORS] = { + [SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)}, + [SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)}, + }; /* reset bridge */ ov534_reg_write(gspca_dev, 0xe7, 0x3a); @@ -840,35 +1187,82 @@ static int sd_init(struct gspca_dev *gspca_dev) sensor_id |= sccb_reg_read(gspca_dev, 0x0b); PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); + if ((sensor_id & 0xfff0) == 0x7670) { + sd->sensor = SENSOR_OV767x; + gspca_dev->ctrl_dis = (1 << GAIN) | + (1 << AGC) | + (1 << SHARPNESS); /* auto */ + sd->ctrls[BRIGHTNESS].min = -127; + sd->ctrls[BRIGHTNESS].max = 127; + sd->ctrls[BRIGHTNESS].def = 0; + sd->ctrls[CONTRAST].max = 0x80; + sd->ctrls[CONTRAST].def = 0x40; + sd->ctrls[EXPOSURE].min = 0x08; + sd->ctrls[EXPOSURE].max = 0x60; + sd->ctrls[EXPOSURE].def = 0x13; + sd->ctrls[SHARPNESS].max = 9; + sd->ctrls[SHARPNESS].def = 4; + sd->ctrls[HFLIP].def = 1; + gspca_dev->cam.cam_mode = ov767x_mode; + gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode); + } else { + sd->sensor = SENSOR_OV772x; + gspca_dev->cam.bulk = 1; + gspca_dev->cam.bulk_size = 16384; + gspca_dev->cam.bulk_nurbs = 2; + gspca_dev->cam.mode_framerates = ov772x_framerates; + } + /* initialize */ - reg_w_array(gspca_dev, bridge_init, - ARRAY_SIZE(bridge_init)); + reg_w_array(gspca_dev, bridge_init[sd->sensor].val, + bridge_init[sd->sensor].len); ov534_set_led(gspca_dev, 1); - sccb_w_array(gspca_dev, sensor_init, - ARRAY_SIZE(sensor_init)); - ov534_reg_write(gspca_dev, 0xe0, 0x09); - ov534_set_led(gspca_dev, 0); - set_frame_rate(gspca_dev); + sccb_w_array(gspca_dev, sensor_init[sd->sensor].val, + sensor_init[sd->sensor].len); + if (sd->sensor == SENSOR_OV767x) + sd_start(gspca_dev); + sd_stopN(gspca_dev); +/* set_frame_rate(gspca_dev); */ return gspca_dev->usb_err; } static int sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int mode; + static const struct reg_array bridge_start[NSENSORS][2] = { + [SENSOR_OV767x] = {{bridge_start_qvga_767x, + ARRAY_SIZE(bridge_start_qvga_767x)}, + {bridge_start_vga_767x, + ARRAY_SIZE(bridge_start_vga_767x)}}, + [SENSOR_OV772x] = {{bridge_start_qvga_772x, + ARRAY_SIZE(bridge_start_qvga_772x)}, + {bridge_start_vga_772x, + ARRAY_SIZE(bridge_start_vga_772x)}}, + }; + static const struct reg_array sensor_start[NSENSORS][2] = { + [SENSOR_OV767x] = {{sensor_start_qvga_767x, + ARRAY_SIZE(sensor_start_qvga_767x)}, + {sensor_start_vga_767x, + ARRAY_SIZE(sensor_start_vga_767x)}}, + [SENSOR_OV772x] = {{sensor_start_qvga_772x, + ARRAY_SIZE(sensor_start_qvga_772x)}, + {sensor_start_vga_772x, + ARRAY_SIZE(sensor_start_vga_772x)}}, + }; + + /* (from ms-win trace) */ + if (sd->sensor == SENSOR_OV767x) + sccb_reg_write(gspca_dev, 0x1e, 0x04); + /* black sun enable ? */ + + mode = gspca_dev->curr_mode; /* 0: 320x240, 1: 640x480 */ + reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val, + bridge_start[sd->sensor][mode].len); + sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val, + sensor_start[sd->sensor][mode].len); - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - if (mode != 0) { /* 320x240 */ - reg_w_array(gspca_dev, bridge_start_qvga, - ARRAY_SIZE(bridge_start_qvga)); - sccb_w_array(gspca_dev, sensor_start_qvga, - ARRAY_SIZE(sensor_start_qvga)); - } else { /* 640x480 */ - reg_w_array(gspca_dev, bridge_start_vga, - ARRAY_SIZE(bridge_start_vga)); - sccb_w_array(gspca_dev, sensor_start_vga, - ARRAY_SIZE(sensor_start_vga)); - } set_frame_rate(gspca_dev); if (!(gspca_dev->ctrl_dis & (1 << AGC))) @@ -913,9 +1307,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u32 this_pts; u16 this_fid; int remaining_len = len; + int payload_len; + payload_len = gspca_dev->cam.bulk ? 2048 : 2040; do { - len = min(remaining_len, 2048); + len = min(remaining_len, payload_len); /* Payloads are prefixed with a UVC-style header. We consider a frame to start when the FID toggles, or the PTS @@ -955,8 +1351,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* If this packet is marked as EOF, end the frame */ } else if (data[1] & UVC_STREAM_EOF) { sd->last_pts = 0; - if (gspca_dev->image_len + len - 12 != - gspca_dev->width * gspca_dev->height * 2) { + if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV + && gspca_dev->image_len + len - 12 != + gspca_dev->width * gspca_dev->height * 2) { PDEBUG(D_PACK, "wrong sized frame"); goto discard; } @@ -1073,6 +1470,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x1415, 0x2000)}, + {USB_DEVICE(0x06f8, 0x3002)}, {} }; -- cgit v1.2.3-70-g09d2 From b287db119edb92548b53f63f05fd593c43cba200 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 5 Feb 2011 09:25:02 -0300 Subject: [media] se401: remove last V4L1 driver This driver is for obsolete hardware that the old maintainer didn't care (or not have the hardware anymore), and that no other developer could find any hardware to buy. The V4L1 API is no longer supported, and since nobody stepped in to convert them to V4L2 the decision was made to remove them. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/feature-removal-schedule.txt | 15 - drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/se401/Kconfig | 13 - drivers/staging/se401/Makefile | 1 - drivers/staging/se401/TODO | 5 - drivers/staging/se401/se401.c | 1492 ---------------------------- drivers/staging/se401/se401.h | 236 ----- drivers/staging/se401/videodev.h | 318 ------ 9 files changed, 2083 deletions(-) delete mode 100644 drivers/staging/se401/Kconfig delete mode 100644 drivers/staging/se401/Makefile delete mode 100644 drivers/staging/se401/TODO delete mode 100644 drivers/staging/se401/se401.c delete mode 100644 drivers/staging/se401/se401.h delete mode 100644 drivers/staging/se401/videodev.h (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index b3f35e5f9c9..08e0df12df3 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -97,21 +97,6 @@ Who: Pavel Machek --------------------------- -What: Video4Linux obsolete drivers using V4L1 API -When: kernel 2.6.39 -Files: drivers/staging/se401/* drivers/staging/usbvideo/* -Check: drivers/staging/se401/se401.c drivers/staging/usbvideo/usbvideo.c -Why: There are some drivers still using V4L1 API, despite all efforts we've done - to migrate. Those drivers are for obsolete hardware that the old maintainer - didn't care (or not have the hardware anymore), and that no other developer - could find any hardware to buy. They probably have no practical usage today, - and people with such old hardware could probably keep using an older version - of the kernel. Those drivers will be moved to staging on 2.6.38 and, if nobody - cares enough to port and test them with V4L2 API, they'll be removed on 2.6.39. -Who: Mauro Carvalho Chehab - ---------------------------- - What: Video4Linux: Remove obsolete ioctl's When: kernel 2.6.39 Files: include/media/videodev2.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index a3f340bb6b5..fa5c007e74c 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -55,8 +55,6 @@ source "drivers/staging/cxd2099/Kconfig" source "drivers/staging/dabusb/Kconfig" -source "drivers/staging/se401/Kconfig" - source "drivers/staging/usbip/Kconfig" source "drivers/staging/winbond/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 532331ceb12..2bdd703ed20 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ obj-$(CONFIG_DVB_CXD2099) += cxd2099/ obj-$(CONFIG_USB_DABUSB) += dabusb/ -obj-$(CONFIG_USB_SE401) += se401/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_USB_IP_COMMON) += usbip/ obj-$(CONFIG_W35UND) += winbond/ diff --git a/drivers/staging/se401/Kconfig b/drivers/staging/se401/Kconfig deleted file mode 100644 index b7f8222ad21..00000000000 --- a/drivers/staging/se401/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -config USB_SE401 - tristate "USB SE401 Camera support (DEPRECATED)" - depends on VIDEO_DEV && VIDEO_V4L2_COMMON && USB - ---help--- - Say Y here if you want to connect this type of camera to your - computer's USB port. See - for more information and for a list of supported cameras. - - This driver uses the deprecated V4L1 API and will be removed in - 2.6.39, unless someone converts it to the V4L2 API. - - To compile this driver as a module, choose M here: the - module will be called se401. diff --git a/drivers/staging/se401/Makefile b/drivers/staging/se401/Makefile deleted file mode 100644 index b465d49783a..00000000000 --- a/drivers/staging/se401/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_USB_SE401) += se401.o diff --git a/drivers/staging/se401/TODO b/drivers/staging/se401/TODO deleted file mode 100644 index 3b2c0383628..00000000000 --- a/drivers/staging/se401/TODO +++ /dev/null @@ -1,5 +0,0 @@ -This is an obsolete driver for some old webcams that still use V4L1 API. -As V4L1 support is being removed from kernel, if nobody take care on it, -the driver will be removed for 2.6.39. - -Please send patches to linux-media@vger.kernel.org diff --git a/drivers/staging/se401/se401.c b/drivers/staging/se401/se401.c deleted file mode 100644 index 41360d7c3e9..00000000000 --- a/drivers/staging/se401/se401.c +++ /dev/null @@ -1,1492 +0,0 @@ -/* - * Endpoints (formerly known as AOX) se401 USB Camera Driver - * - * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) - * - * Still somewhat based on the Linux ov511 driver. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on - * their chipset available and supporting me while writing this driver. - * - Jeroen Vreeken - */ - -static const char version[] = "0.24"; - -#include -#include -#include -#include -#include -#include -#include "se401.h" - -static int flickerless; -static int video_nr = -1; - -static struct usb_device_id device_table[] = { - { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */ - { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */ - { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */ - { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */ - { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */ - { } -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -MODULE_AUTHOR("Jeroen Vreeken "); -MODULE_DESCRIPTION("SE401 USB Camera Driver"); -MODULE_LICENSE("GPL"); -module_param(flickerless, int, 0); -MODULE_PARM_DESC(flickerless, - "Net frequency to adjust exposure time to (0/50/60)"); -module_param(video_nr, int, 0); - -static struct usb_driver se401_driver; - - -/********************************************************************** - * - * Memory management - * - **********************************************************************/ -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - - - -/**************************************************************************** - * - * se401 register read/write functions - * - ***************************************************************************/ - -static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, - unsigned short value, unsigned char *cp, int size) -{ - return usb_control_msg( - se401->dev, - set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), - req, - (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - 0, - cp, - size, - 1000 - ); -} - -static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, - unsigned short param) -{ - /* specs say that the selector (address) should go in the value field - and the param in index, but in the logs of the windows driver they do - this the other way around... - */ - return usb_control_msg( - se401->dev, - usb_sndctrlpipe(se401->dev, 0), - SE401_REQ_SET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - param, - selector, - NULL, - 0, - 1000 - ); -} - -static unsigned short se401_get_feature(struct usb_se401 *se401, - unsigned short selector) -{ - /* For 'set' the selecetor should be in index, not sure if the spec is - wrong here to.... - */ - unsigned char cp[2]; - usb_control_msg( - se401->dev, - usb_rcvctrlpipe(se401->dev, 0), - SE401_REQ_GET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - selector, - cp, - 2, - 1000 - ); - return cp[0]+cp[1]*256; -} - -/**************************************************************************** - * - * Camera control - * - ***************************************************************************/ - - -static int se401_send_pict(struct usb_se401 *se401) -{ - /* integration time low */ - se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l); - /* integration time mid */ - se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m); - /* integration time mid */ - se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h); - /* reset level value */ - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); - /* red color gain */ - se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain); - /* green color gain */ - se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain); - /* blue color gain */ - se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain); - - return 0; -} - -static void se401_set_exposure(struct usb_se401 *se401, int brightness) -{ - int integration = brightness << 5; - - if (flickerless == 50) - integration = integration-integration % 106667; - if (flickerless == 60) - integration = integration-integration % 88889; - se401->brightness = integration >> 5; - se401->expose_h = (integration >> 16) & 0xff; - se401->expose_m = (integration >> 8) & 0xff; - se401->expose_l = integration & 0xff; -} - -static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) -{ - p->brightness = se401->brightness; - if (se401->enhance) - p->whiteness = 32768; - else - p->whiteness = 0; - - p->colour = 65535; - p->contrast = 65535; - p->hue = se401->rgain << 10; - p->palette = se401->palette; - p->depth = 3; /* rgb24 */ - return 0; -} - - -static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) -{ - if (p->palette != VIDEO_PALETTE_RGB24) - return 1; - se401->palette = p->palette; - if (p->hue != se401->hue) { - se401->rgain = p->hue >> 10; - se401->bgain = 0x40-(p->hue >> 10); - se401->hue = p->hue; - } - if (p->brightness != se401->brightness) - se401_set_exposure(se401, p->brightness); - - if (p->whiteness >= 32768) - se401->enhance = 1; - else - se401->enhance = 0; - se401_send_pict(se401); - se401_send_pict(se401); - return 0; -} - -/* - Hyundai have some really nice docs about this and other sensor related - stuff on their homepage: www.hei.co.kr -*/ -static void se401_auto_resetlevel(struct usb_se401 *se401) -{ - unsigned int ahrc, alrc; - int oldreset = se401->resetlevel; - - /* For some reason this normally read-only register doesn't get reset - to zero after reading them just once... - */ - se401_get_feature(se401, HV7131_REG_HIREFNOH); - se401_get_feature(se401, HV7131_REG_HIREFNOL); - se401_get_feature(se401, HV7131_REG_LOREFNOH); - se401_get_feature(se401, HV7131_REG_LOREFNOL); - ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + - se401_get_feature(se401, HV7131_REG_HIREFNOL); - alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + - se401_get_feature(se401, HV7131_REG_LOREFNOL); - - /* Not an exact science, but it seems to work pretty well... */ - if (alrc > 10) { - while (alrc >= 10 && se401->resetlevel < 63) { - se401->resetlevel++; - alrc /= 2; - } - } else if (ahrc > 20) { - while (ahrc >= 20 && se401->resetlevel > 0) { - se401->resetlevel--; - ahrc /= 2; - } - } - if (se401->resetlevel != oldreset) - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); - - return; -} - -/* irq handler for snapshot button */ -static void se401_button_irq(struct urb *urb) -{ - struct usb_se401 *se401 = urb->context; - int status; - - if (!se401->dev) { - dev_info(&urb->dev->dev, "device vapourished\n"); - return; - } - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", - __func__, urb->status); - goto exit; - } - - if (urb->actual_length >= 2) - if (se401->button) - se401->buttonpressed = 1; -exit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) - err("%s - usb_submit_urb failed with result %d", - __func__, status); -} - -static void se401_video_irq(struct urb *urb) -{ - struct usb_se401 *se401 = urb->context; - int length = urb->actual_length; - - /* ohoh... */ - if (!se401->streaming) - return; - - if (!se401->dev) { - dev_info(&urb->dev->dev, "device vapourished\n"); - return; - } - - /* 0 sized packets happen if we are to fast, but sometimes the camera - keeps sending them forever... - */ - if (length && !urb->status) { - se401->nullpackets = 0; - switch (se401->scratch[se401->scratch_next].state) { - case BUFFER_READY: - case BUFFER_BUSY: - se401->dropped++; - break; - case BUFFER_UNUSED: - memcpy(se401->scratch[se401->scratch_next].data, - (unsigned char *)urb->transfer_buffer, length); - se401->scratch[se401->scratch_next].state - = BUFFER_READY; - se401->scratch[se401->scratch_next].offset - = se401->bayeroffset; - se401->scratch[se401->scratch_next].length = length; - if (waitqueue_active(&se401->wq)) - wake_up_interruptible(&se401->wq); - se401->scratch_overflow = 0; - se401->scratch_next++; - if (se401->scratch_next >= SE401_NUMSCRATCH) - se401->scratch_next = 0; - break; - } - se401->bayeroffset += length; - if (se401->bayeroffset >= se401->cheight * se401->cwidth) - se401->bayeroffset = 0; - } else { - se401->nullpackets++; - if (se401->nullpackets > SE401_MAX_NULLPACKETS) - if (waitqueue_active(&se401->wq)) - wake_up_interruptible(&se401->wq); - } - - /* Resubmit urb for new data */ - urb->status = 0; - urb->dev = se401->dev; - if (usb_submit_urb(urb, GFP_KERNEL)) - dev_info(&urb->dev->dev, "urb burned down\n"); - return; -} - -static void se401_send_size(struct usb_se401 *se401, int width, int height) -{ - int i = 0; - int mode = 0x03; /* No compression */ - int sendheight = height; - int sendwidth = width; - - /* JangGu compression can only be used with the camera supported sizes, - but bayer seems to work with any size that fits on the sensor. - We check if we can use compression with the current size with either - 4 or 16 times subcapturing, if not we use uncompressed bayer data - but this will result in cutouts of the maximum size.... - */ - while (i < se401->sizes && !(se401->width[i] == width && - se401->height[i] == height)) - i++; - while (i < se401->sizes) { - if (se401->width[i] == width * 2 && - se401->height[i] == height * 2) { - sendheight = se401->height[i]; - sendwidth = se401->width[i]; - mode = 0x40; - } - if (se401->width[i] == width * 4 && - se401->height[i] == height * 4) { - sendheight = se401->height[i]; - sendwidth = se401->width[i]; - mode = 0x42; - } - i++; - } - - se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); - se401_set_feature(se401, SE401_OPERATINGMODE, mode); - - if (mode == 0x03) - se401->format = FMT_BAYER; - else - se401->format = FMT_JANGGU; -} - -/* - In this function se401_send_pict is called several times, - for some reason (depending on the state of the sensor and the phase of - the moon :) doing this only in either place doesn't always work... -*/ -static int se401_start_stream(struct usb_se401 *se401) -{ - struct urb *urb; - int err = 0, i; - se401->streaming = 1; - - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - - /* Set picture settings */ - /* windowed + pix intg */ - se401_set_feature(se401, HV7131_REG_MODE_B, 0x05); - se401_send_pict(se401); - - se401_send_size(se401, se401->cwidth, se401->cheight); - - se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, - 0, NULL, 0); - - /* Do some memory allocation */ - for (i = 0; i < SE401_NUMFRAMES; i++) { - se401->frame[i].data = se401->fbuf + i * se401->maxframesize; - se401->frame[i].curpix = 0; - } - for (i = 0; i < SE401_NUMSBUF; i++) { - se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); - if (!se401->sbuf[i].data) { - for (i = i - 1; i >= 0; i--) { - kfree(se401->sbuf[i].data); - se401->sbuf[i].data = NULL; - } - return -ENOMEM; - } - } - - se401->bayeroffset = 0; - se401->scratch_next = 0; - se401->scratch_use = 0; - se401->scratch_overflow = 0; - for (i = 0; i < SE401_NUMSCRATCH; i++) { - se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); - if (!se401->scratch[i].data) { - for (i = i - 1; i >= 0; i--) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - goto nomem_sbuf; - } - se401->scratch[i].state = BUFFER_UNUSED; - } - - for (i = 0; i < SE401_NUMSBUF; i++) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - for (i = i - 1; i >= 0; i--) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - } - goto nomem_scratch; - } - - usb_fill_bulk_urb(urb, se401->dev, - usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT), - se401->sbuf[i].data, SE401_PACKETSIZE, - se401_video_irq, - se401); - - se401->urb[i] = urb; - - err = usb_submit_urb(se401->urb[i], GFP_KERNEL); - if (err) - err("urb burned down"); - } - - se401->framecount = 0; - - return 0; - - nomem_scratch: - for (i = 0; i < SE401_NUMSCRATCH; i++) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - nomem_sbuf: - for (i = 0; i < SE401_NUMSBUF; i++) { - kfree(se401->sbuf[i].data); - se401->sbuf[i].data = NULL; - } - return -ENOMEM; -} - -static int se401_stop_stream(struct usb_se401 *se401) -{ - int i; - - if (!se401->streaming || !se401->dev) - return 1; - - se401->streaming = 0; - - se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0); - - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - - for (i = 0; i < SE401_NUMSBUF; i++) - if (se401->urb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - for (i = 0; i < SE401_NUMSCRATCH; i++) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - - return 0; -} - -static int se401_set_size(struct usb_se401 *se401, int width, int height) -{ - int wasstreaming = se401->streaming; - /* Check to see if we need to change */ - if (se401->cwidth == width && se401->cheight == height) - return 0; - - /* Check for a valid mode */ - if (!width || !height) - return 1; - if ((width & 1) || (height & 1)) - return 1; - if (width > se401->width[se401->sizes-1]) - return 1; - if (height > se401->height[se401->sizes-1]) - return 1; - - /* Stop a current stream and start it again at the new size */ - if (wasstreaming) - se401_stop_stream(se401); - se401->cwidth = width; - se401->cheight = height; - if (wasstreaming) - se401_start_stream(se401); - return 0; -} - - -/**************************************************************************** - * - * Video Decoding - * - ***************************************************************************/ - -/* - This shouldn't really be done in a v4l driver.... - But it does make the image look a lot more usable. - Basically it lifts the dark pixels more than the light pixels. -*/ -static inline void enhance_picture(unsigned char *frame, int len) -{ - while (len--) { - *frame = (((*frame^255)*(*frame^255))/255)^255; - frame++; - } -} - -static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) -{ - struct se401_frame *frame = &se401->frame[se401->curframe]; - int linelength = se401->cwidth * 3; - - if (frame->curlinepix >= linelength) { - frame->curlinepix = 0; - frame->curline += linelength; - } - - /* First three are absolute, all others relative. - * Format is rgb from right to left (mirrorred image), - * we flip it to get bgr from left to right. */ - if (frame->curlinepix < 3) - *(frame->curline-frame->curlinepix) = 1 + data * 4; - else - *(frame->curline-frame->curlinepix) = - *(frame->curline-frame->curlinepix + 3) + data * 4; - frame->curlinepix++; -} - -static inline void decode_JangGu_vlc(struct usb_se401 *se401, - unsigned char *data, int bit_exp, int packetlength) -{ - int pos = 0; - int vlc_cod = 0; - int vlc_size = 0; - int vlc_data = 0; - int bit_cur; - int bit; - data += 4; - while (pos < packetlength) { - bit_cur = 8; - while (bit_cur && bit_exp) { - bit = ((*data) >> (bit_cur-1))&1; - if (!vlc_cod) { - if (bit) { - vlc_size++; - } else { - if (!vlc_size) - decode_JangGu_integrate(se401, 0); - else { - vlc_cod = 2; - vlc_data = 0; - } - } - } else { - if (vlc_cod == 2) { - if (!bit) - vlc_data = -(1 << vlc_size) + 1; - vlc_cod--; - } - vlc_size--; - vlc_data += bit << vlc_size; - if (!vlc_size) { - decode_JangGu_integrate(se401, vlc_data); - vlc_cod = 0; - } - } - bit_cur--; - bit_exp--; - } - pos++; - data++; - } -} - -static inline void decode_JangGu(struct usb_se401 *se401, - struct se401_scratch *buffer) -{ - unsigned char *data = buffer->data; - int len = buffer->length; - int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size; - int datapos = 0; - - /* New image? */ - if (!se401->frame[se401->curframe].curpix) { - se401->frame[se401->curframe].curlinepix = 0; - se401->frame[se401->curframe].curline = - se401->frame[se401->curframe].data+ - se401->cwidth * 3 - 1; - if (se401->frame[se401->curframe].grabstate == FRAME_READY) - se401->frame[se401->curframe].grabstate = FRAME_GRABBING; - se401->vlcdatapos = 0; - } - while (datapos < len) { - size = 1024 - se401->vlcdatapos; - if (size+datapos > len) - size = len-datapos; - memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size); - se401->vlcdatapos += size; - packetlength = 0; - if (se401->vlcdatapos >= 4) { - bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8); - pix_exp = se401->vlcdata[1] + - ((se401->vlcdata[0] & 0x3f) << 8); - frameinfo = se401->vlcdata[0] & 0xc0; - packetlength = ((bit_exp + 47) >> 4) << 1; - if (packetlength > 1024) { - se401->vlcdatapos = 0; - datapos = len; - packetlength = 0; - se401->error++; - se401->frame[se401->curframe].curpix = 0; - } - } - if (packetlength && se401->vlcdatapos >= packetlength) { - decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, - packetlength); - se401->frame[se401->curframe].curpix += pix_exp * 3; - datapos += size-(se401->vlcdatapos-packetlength); - se401->vlcdatapos = 0; - if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) { - if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) { - if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) { - se401->frame[se401->curframe].grabstate = FRAME_DONE; - se401->framecount++; - se401->readcount++; - } - if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) - se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1); - } else - se401->error++; - se401->frame[se401->curframe].curpix = 0; - datapos = len; - } - } else - datapos += size; - } -} - -static inline void decode_bayer(struct usb_se401 *se401, - struct se401_scratch *buffer) -{ - unsigned char *data = buffer->data; - int len = buffer->length; - int offset = buffer->offset; - int datasize = se401->cwidth * se401->cheight; - struct se401_frame *frame = &se401->frame[se401->curframe]; - unsigned char *framedata = frame->data, *curline, *nextline; - int width = se401->cwidth; - int blineoffset = 0, bline; - int linelength = width * 3, i; - - - if (frame->curpix == 0) { - if (frame->grabstate == FRAME_READY) - frame->grabstate = FRAME_GRABBING; - - frame->curline = framedata + linelength; - frame->curlinepix = 0; - } - - if (offset != frame->curpix) { - /* Regard frame as lost :( */ - frame->curpix = 0; - se401->error++; - return; - } - - /* Check if we have to much data */ - if (frame->curpix + len > datasize) - len = datasize-frame->curpix; - - if (se401->cheight % 4) - blineoffset = 1; - bline = frame->curpix / se401->cwidth+blineoffset; - - curline = frame->curline; - nextline = curline + linelength; - if (nextline >= framedata+datasize * 3) - nextline = curline; - while (len) { - if (frame->curlinepix >= width) { - frame->curlinepix -= width; - bline = frame->curpix / width + blineoffset; - curline += linelength*2; - nextline += linelength*2; - if (curline >= framedata+datasize * 3) { - frame->curlinepix++; - curline -= 3; - nextline -= 3; - len--; - data++; - frame->curpix++; - } - if (nextline >= framedata+datasize*3) - nextline = curline; - } - if (bline & 1) { - if (frame->curlinepix & 1) { - *(curline + 2) = *data; - *(curline - 1) = *data; - *(nextline + 2) = *data; - *(nextline - 1) = *data; - } else { - *(curline + 1) = - (*(curline + 1) + *data) / 2; - *(curline-2) = - (*(curline - 2) + *data) / 2; - *(nextline + 1) = *data; - *(nextline - 2) = *data; - } - } else { - if (frame->curlinepix & 1) { - *(curline + 1) = - (*(curline + 1) + *data) / 2; - *(curline - 2) = - (*(curline - 2) + *data) / 2; - *(nextline + 1) = *data; - *(nextline - 2) = *data; - } else { - *curline = *data; - *(curline - 3) = *data; - *nextline = *data; - *(nextline - 3) = *data; - } - } - frame->curlinepix++; - curline -= 3; - nextline -= 3; - len--; - data++; - frame->curpix++; - } - frame->curline = curline; - - if (frame->curpix >= datasize) { - /* Fix the top line */ - framedata += linelength; - for (i = 0; i < linelength; i++) { - framedata--; - *framedata = *(framedata + linelength); - } - /* Fix the left side (green is already present) */ - for (i = 0; i < se401->cheight; i++) { - *framedata = *(framedata + 3); - *(framedata + 1) = *(framedata + 4); - *(framedata + 2) = *(framedata + 5); - framedata += linelength; - } - frame->curpix = 0; - frame->grabstate = FRAME_DONE; - se401->framecount++; - se401->readcount++; - if (se401->frame[(se401->curframe + 1) & - (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) { - se401->curframe = (se401->curframe+1) & - (SE401_NUMFRAMES-1); - } - } -} - -static int se401_newframe(struct usb_se401 *se401, int framenr) -{ - DECLARE_WAITQUEUE(wait, current); - int errors = 0; - - while (se401->streaming && - (se401->frame[framenr].grabstate == FRAME_READY || - se401->frame[framenr].grabstate == FRAME_GRABBING)) { - if (!se401->frame[framenr].curpix) - errors++; - - wait_interruptible( - se401->scratch[se401->scratch_use].state != BUFFER_READY, - &se401->wq, &wait); - if (se401->nullpackets > SE401_MAX_NULLPACKETS) { - se401->nullpackets = 0; - dev_info(&se401->dev->dev, - "too many null length packets, restarting capture\n"); - se401_stop_stream(se401); - se401_start_stream(se401); - } else { - if (se401->scratch[se401->scratch_use].state != - BUFFER_READY) { - se401->frame[framenr].grabstate = FRAME_ERROR; - return -EIO; - } - se401->scratch[se401->scratch_use].state = BUFFER_BUSY; - if (se401->format == FMT_JANGGU) - decode_JangGu(se401, - &se401->scratch[se401->scratch_use]); - else - decode_bayer(se401, - &se401->scratch[se401->scratch_use]); - - se401->scratch[se401->scratch_use].state = - BUFFER_UNUSED; - se401->scratch_use++; - if (se401->scratch_use >= SE401_NUMSCRATCH) - se401->scratch_use = 0; - if (errors > SE401_MAX_ERRORS) { - errors = 0; - dev_info(&se401->dev->dev, - "too many errors, restarting capture\n"); - se401_stop_stream(se401); - se401_start_stream(se401); - } - } - } - - if (se401->frame[framenr].grabstate == FRAME_DONE) - if (se401->enhance) - enhance_picture(se401->frame[framenr].data, - se401->cheight * se401->cwidth * 3); - return 0; -} - -static void usb_se401_remove_disconnected(struct usb_se401 *se401) -{ - int i; - - se401->dev = NULL; - - for (i = 0; i < SE401_NUMSBUF; i++) - if (se401->urb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - - for (i = 0; i < SE401_NUMSCRATCH; i++) - kfree(se401->scratch[i].data); - - if (se401->inturb) { - usb_kill_urb(se401->inturb); - usb_free_urb(se401->inturb); - } - dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name); - - /* Free the memory */ - kfree(se401->width); - kfree(se401->height); - kfree(se401); -} - - - -/**************************************************************************** - * - * Video4Linux - * - ***************************************************************************/ - - -static int se401_open(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_se401 *se401 = (struct usb_se401 *)dev; - int err = 0; - - mutex_lock(&se401->lock); - if (se401->user) { - mutex_unlock(&se401->lock); - return -EBUSY; - } - se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); - if (se401->fbuf) - file->private_data = dev; - else - err = -ENOMEM; - se401->user = !err; - mutex_unlock(&se401->lock); - - return err; -} - -static int se401_close(struct file *file) -{ - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - int i; - - rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); - if (se401->removed) { - dev_info(&se401->dev->dev, "device unregistered\n"); - usb_se401_remove_disconnected(se401); - } else { - for (i = 0; i < SE401_NUMFRAMES; i++) - se401->frame[i].grabstate = FRAME_UNUSED; - if (se401->streaming) - se401_stop_stream(se401); - se401->user = 0; - } - file->private_data = NULL; - return 0; -} - -static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct video_device *vdev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)vdev; - - if (!se401->dev) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - strcpy(b->name, se401->camera_name); - b->type = VID_TYPE_CAPTURE; - b->channels = 1; - b->audios = 0; - b->maxwidth = se401->width[se401->sizes-1]; - b->maxheight = se401->height[se401->sizes-1]; - b->minwidth = se401->width[0]; - b->minheight = se401->height[0]; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Camera"); - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - - se401_get_pict(se401, p); - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - - if (se401_set_pict(se401, p)) - return -EINVAL; - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (se401_set_size(se401, vw->width, vw->height)) - return -EINVAL; - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; /* FIXME */ - vw->y = 0; - vw->chromakey = 0; - vw->flags = 0; - vw->clipcount = 0; - vw->width = se401->cwidth; - vw->height = se401->cheight; - return 0; - } - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = SE401_NUMFRAMES * se401->maxframesize; - vm->frames = SE401_NUMFRAMES; - for (i = 0; i < SE401_NUMFRAMES; i++) - vm->offsets[i] = se401->maxframesize * i; - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - - if (vm->format != VIDEO_PALETTE_RGB24) - return -EINVAL; - if (vm->frame >= SE401_NUMFRAMES) - return -EINVAL; - if (se401->frame[vm->frame].grabstate != FRAME_UNUSED) - return -EBUSY; - - /* Is this according to the v4l spec??? */ - if (se401_set_size(se401, vm->width, vm->height)) - return -EINVAL; - se401->frame[vm->frame].grabstate = FRAME_READY; - - if (!se401->streaming) - se401_start_stream(se401); - - /* Set the picture properties */ - if (se401->framecount == 0) - se401_send_pict(se401); - /* Calibrate the reset level after a few frames. */ - if (se401->framecount % 20 == 1) - se401_auto_resetlevel(se401); - - return 0; - } - case VIDIOCSYNC: - { - int *frame = arg; - int ret = 0; - - if (*frame < 0 || *frame >= SE401_NUMFRAMES) - return -EINVAL; - - ret = se401_newframe(se401, *frame); - se401->frame[*frame].grabstate = FRAME_UNUSED; - return ret; - } - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb, 0, sizeof(*vb)); - return 0; - } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - return -EINVAL; - case VIDIOCSFBUF: - return -EINVAL; - case VIDIOCGTUNER: - case VIDIOCSTUNER: - return -EINVAL; - case VIDIOCGFREQ: - case VIDIOCSFREQ: - return -EINVAL; - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } /* end switch */ - - return 0; -} - -static long se401_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(file, cmd, arg, se401_do_ioctl); -} - -static ssize_t se401_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int realcount = count, ret = 0; - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - - - if (se401->dev == NULL) - return -EIO; - if (realcount > se401->cwidth*se401->cheight*3) - realcount = se401->cwidth*se401->cheight*3; - - /* Shouldn't happen: */ - if (se401->frame[0].grabstate == FRAME_GRABBING) - return -EBUSY; - se401->frame[0].grabstate = FRAME_READY; - se401->frame[1].grabstate = FRAME_UNUSED; - se401->curframe = 0; - - if (!se401->streaming) - se401_start_stream(se401); - - /* Set the picture properties */ - if (se401->framecount == 0) - se401_send_pict(se401); - /* Calibrate the reset level after a few frames. */ - if (se401->framecount%20 == 1) - se401_auto_resetlevel(se401); - - ret = se401_newframe(se401, 0); - - se401->frame[0].grabstate = FRAME_UNUSED; - if (ret) - return ret; - if (copy_to_user(buf, se401->frame[0].data, realcount)) - return -EFAULT; - - return realcount; -} - -static int se401_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - mutex_lock(&se401->lock); - - if (se401->dev == NULL) { - mutex_unlock(&se401->lock); - return -EIO; - } - if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) - & ~(PAGE_SIZE - 1))) { - mutex_unlock(&se401->lock); - return -EINVAL; - } - pos = (unsigned long)se401->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - mutex_unlock(&se401->lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - mutex_unlock(&se401->lock); - - return 0; -} - -static const struct v4l2_file_operations se401_fops = { - .owner = THIS_MODULE, - .open = se401_open, - .release = se401_close, - .read = se401_read, - .mmap = se401_mmap, - .ioctl = se401_ioctl, -}; -static struct video_device se401_template = { - .name = "se401 USB camera", - .fops = &se401_fops, - .release = video_device_release_empty, -}; - - - -/***************************/ -static int se401_init(struct usb_se401 *se401, int button) -{ - int i = 0, rc; - unsigned char cp[0x40]; - char temp[200]; - int slen; - - /* led on */ - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - - /* get camera descriptor */ - rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, - cp, sizeof(cp)); - if (cp[1] != 0x41) { - err("Wrong descriptor type"); - return 1; - } - slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]); - - se401->sizes = cp[4] + cp[5] * 256; - se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); - if (!se401->width) - return 1; - se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); - if (!se401->height) { - kfree(se401->width); - return 1; - } - for (i = 0; i < se401->sizes; i++) { - se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256; - se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256; - } - slen += snprintf(temp + slen, 200 - slen, " Sizes:"); - for (i = 0; i < se401->sizes; i++) { - slen += snprintf(temp + slen, 200 - slen, - " %dx%d", se401->width[i], se401->height[i]); - } - dev_info(&se401->dev->dev, "%s\n", temp); - se401->maxframesize = se401->width[se401->sizes-1] * - se401->height[se401->sizes - 1] * 3; - - rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); - se401->cwidth = cp[0]+cp[1]*256; - rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); - se401->cheight = cp[0]+cp[1]*256; - - if (!(cp[2] & SE401_FORMAT_BAYER)) { - err("Bayer format not supported!"); - return 1; - } - /* set output mode (BAYER) */ - se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, - SE401_FORMAT_BAYER, NULL, 0); - - rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); - se401->brightness = cp[0]+cp[1]*256; - /* some default values */ - se401->resetlevel = 0x2d; - se401->rgain = 0x20; - se401->ggain = 0x20; - se401->bgain = 0x20; - se401_set_exposure(se401, 20000); - se401->palette = VIDEO_PALETTE_RGB24; - se401->enhance = 1; - se401->dropped = 0; - se401->error = 0; - se401->framecount = 0; - se401->readcount = 0; - - /* Start interrupt transfers for snapshot button */ - if (button) { - se401->inturb = usb_alloc_urb(0, GFP_KERNEL); - if (!se401->inturb) { - dev_info(&se401->dev->dev, - "Allocation of inturb failed\n"); - return 1; - } - usb_fill_int_urb(se401->inturb, se401->dev, - usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), - &se401->button, sizeof(se401->button), - se401_button_irq, - se401, - 8 - ); - if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { - dev_info(&se401->dev->dev, "int urb burned down\n"); - return 1; - } - } else - se401->inturb = NULL; - - /* Flash the led */ - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - - return 0; -} - -static int se401_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_interface_descriptor *interface; - struct usb_se401 *se401; - char *camera_name = NULL; - int button = 1; - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - interface = &intf->cur_altsetting->desc; - - /* Is it an se401? */ - if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && - le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { - camera_name = "Endpoints/Aox SE401"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && - le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { - camera_name = "Philips PCVC665K"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { - camera_name = "Kensington VideoCAM 67014"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { - camera_name = "Kensington VideoCAM 6701(5/7)"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { - camera_name = "Kensington VideoCAM 67016"; - button = 0; - } else - return -ENODEV; - - /* Checking vendor/product should be enough, but what the hell */ - if (interface->bInterfaceClass != 0x00) - return -ENODEV; - if (interface->bInterfaceSubClass != 0x00) - return -ENODEV; - - /* We found one */ - dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); - - se401 = kzalloc(sizeof(*se401), GFP_KERNEL); - if (se401 == NULL) { - err("couldn't kmalloc se401 struct"); - return -ENOMEM; - } - - se401->dev = dev; - se401->iface = interface->bInterfaceNumber; - se401->camera_name = camera_name; - - dev_info(&intf->dev, "firmware version: %02x\n", - le16_to_cpu(dev->descriptor.bcdDevice) & 255); - - if (se401_init(se401, button)) { - kfree(se401); - return -EIO; - } - - memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); - memcpy(se401->vdev.name, se401->camera_name, - strlen(se401->camera_name)); - init_waitqueue_head(&se401->wq); - mutex_init(&se401->lock); - wmb(); - - if (video_register_device(&se401->vdev, - VFL_TYPE_GRABBER, video_nr) < 0) { - kfree(se401); - err("video_register_device failed"); - return -EIO; - } - dev_info(&intf->dev, "registered new video device: %s\n", - video_device_node_name(&se401->vdev)); - - usb_set_intfdata(intf, se401); - return 0; -} - -static void se401_disconnect(struct usb_interface *intf) -{ - struct usb_se401 *se401 = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (se401) { - video_unregister_device(&se401->vdev); - if (!se401->user) - usb_se401_remove_disconnected(se401); - else { - se401->frame[0].grabstate = FRAME_ERROR; - se401->frame[0].grabstate = FRAME_ERROR; - - se401->streaming = 0; - - wake_up_interruptible(&se401->wq); - se401->removed = 1; - } - } -} - -static struct usb_driver se401_driver = { - .name = "se401", - .id_table = device_table, - .probe = se401_probe, - .disconnect = se401_disconnect, -}; - - - -/**************************************************************************** - * - * Module routines - * - ***************************************************************************/ - -static int __init usb_se401_init(void) -{ - printk(KERN_INFO "SE401 usb camera driver version %s registering\n", - version); - if (flickerless) - if (flickerless != 50 && flickerless != 60) { - printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); - return -1; - } - return usb_register(&se401_driver); -} - -static void __exit usb_se401_exit(void) -{ - usb_deregister(&se401_driver); - printk(KERN_INFO "SE401 driver deregistered\frame"); -} - -module_init(usb_se401_init); -module_exit(usb_se401_exit); diff --git a/drivers/staging/se401/se401.h b/drivers/staging/se401/se401.h deleted file mode 100644 index 2758f4716c3..00000000000 --- a/drivers/staging/se401/se401.h +++ /dev/null @@ -1,236 +0,0 @@ - -#ifndef __LINUX_se401_H -#define __LINUX_se401_H - -#include -#include "videodev.h" -#include -#include -#include - -#define se401_DEBUG /* Turn on debug messages */ - -#ifdef se401_DEBUG -# define PDEBUG(level, fmt, args...) \ -if (debug >= level) \ - info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) -#else -# define PDEBUG(level, fmt, args...) do {} while (0) -#endif - -/* An almost drop-in replacement for sleep_on_interruptible */ -#define wait_interruptible(test, queue, wait) \ -{ \ - add_wait_queue(queue, wait); \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (test) \ - schedule(); \ - remove_wait_queue(queue, wait); \ - set_current_state(TASK_RUNNING); \ - if (signal_pending(current)) \ - break; \ -} - -#define SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06 -#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41 -#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42 -#define SE401_REQ_CAPTURE_FRAME 0x43 -#define SE401_REQ_GET_BRT 0x44 -#define SE401_REQ_SET_BRT 0x45 -#define SE401_REQ_GET_WIDTH 0x4c -#define SE401_REQ_SET_WIDTH 0x4d -#define SE401_REQ_GET_HEIGHT 0x4e -#define SE401_REQ_SET_HEIGHT 0x4f -#define SE401_REQ_GET_OUTPUT_MODE 0x50 -#define SE401_REQ_SET_OUTPUT_MODE 0x51 -#define SE401_REQ_GET_EXT_FEATURE 0x52 -#define SE401_REQ_SET_EXT_FEATURE 0x53 -#define SE401_REQ_CAMERA_POWER 0x56 -#define SE401_REQ_LED_CONTROL 0x57 -#define SE401_REQ_BIOS 0xff - -#define SE401_BIOS_READ 0x07 - -#define SE401_FORMAT_BAYER 0x40 - -/* Hyundai hv7131b registers - 7121 and 7141 should be the same (haven't really checked...) */ -/* Mode registers: */ -#define HV7131_REG_MODE_A 0x00 -#define HV7131_REG_MODE_B 0x01 -#define HV7131_REG_MODE_C 0x02 -/* Frame registers: */ -#define HV7131_REG_FRSU 0x10 -#define HV7131_REG_FRSL 0x11 -#define HV7131_REG_FCSU 0x12 -#define HV7131_REG_FCSL 0x13 -#define HV7131_REG_FWHU 0x14 -#define HV7131_REG_FWHL 0x15 -#define HV7131_REG_FWWU 0x16 -#define HV7131_REG_FWWL 0x17 -/* Timing registers: */ -#define HV7131_REG_THBU 0x20 -#define HV7131_REG_THBL 0x21 -#define HV7131_REG_TVBU 0x22 -#define HV7131_REG_TVBL 0x23 -#define HV7131_REG_TITU 0x25 -#define HV7131_REG_TITM 0x26 -#define HV7131_REG_TITL 0x27 -#define HV7131_REG_TMCD 0x28 -/* Adjust Registers: */ -#define HV7131_REG_ARLV 0x30 -#define HV7131_REG_ARCG 0x31 -#define HV7131_REG_AGCG 0x32 -#define HV7131_REG_ABCG 0x33 -#define HV7131_REG_APBV 0x34 -#define HV7131_REG_ASLP 0x54 -/* Offset Registers: */ -#define HV7131_REG_OFSR 0x50 -#define HV7131_REG_OFSG 0x51 -#define HV7131_REG_OFSB 0x52 -/* REset level statistics registers: */ -#define HV7131_REG_LOREFNOH 0x57 -#define HV7131_REG_LOREFNOL 0x58 -#define HV7131_REG_HIREFNOH 0x59 -#define HV7131_REG_HIREFNOL 0x5a - -/* se401 registers */ -#define SE401_OPERATINGMODE 0x2000 - - -/* size of usb transfers */ -#define SE401_PACKETSIZE 4096 -/* number of queued bulk transfers to use, should be about 8 */ -#define SE401_NUMSBUF 1 -/* read the usb specs for this one :) */ -#define SE401_VIDEO_ENDPOINT 1 -#define SE401_BUTTON_ENDPOINT 2 -/* number of frames supported by the v4l part */ -#define SE401_NUMFRAMES 2 -/* scratch buffers for passing data to the decoders */ -#define SE401_NUMSCRATCH 32 -/* maximum amount of data in a JangGu packet */ -#define SE401_VLCDATALEN 1024 -/* number of nul sized packets to receive before kicking the camera */ -#define SE401_MAX_NULLPACKETS 4000 -/* number of decoding errors before kicking the camera */ -#define SE401_MAX_ERRORS 200 - -struct usb_device; - -struct se401_sbuf { - unsigned char *data; -}; - -enum { - FRAME_UNUSED, /* Unused (no MCAPTURE) */ - FRAME_READY, /* Ready to start grabbing */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_ERROR, /* Something bad happened while processing */ -}; - -enum { - FMT_BAYER, - FMT_JANGGU, -}; - -enum { - BUFFER_UNUSED, - BUFFER_READY, - BUFFER_BUSY, - BUFFER_DONE, -}; - -struct se401_scratch { - unsigned char *data; - volatile int state; - int offset; - int length; -}; - -struct se401_frame { - unsigned char *data; /* Frame buffer */ - - volatile int grabstate; /* State of grabbing */ - - unsigned char *curline; - int curlinepix; - int curpix; -}; - -struct usb_se401 { - struct video_device vdev; - - /* Device structure */ - struct usb_device *dev; - - unsigned char iface; - - char *camera_name; - - int change; - int brightness; - int hue; - int rgain; - int ggain; - int bgain; - int expose_h; - int expose_m; - int expose_l; - int resetlevel; - - int enhance; - - int format; - int sizes; - int *width; - int *height; - int cwidth; /* current width */ - int cheight; /* current height */ - int palette; - int maxframesize; - int cframesize; /* current framesize */ - - struct mutex lock; - int user; /* user count for exclusive use */ - int removed; /* device disconnected */ - - int streaming; /* Are we streaming video? */ - - char *fbuf; /* Videodev buffer area */ - - struct urb *urb[SE401_NUMSBUF]; - struct urb *inturb; - - int button; - int buttonpressed; - - int curframe; /* Current receiving frame */ - struct se401_frame frame[SE401_NUMFRAMES]; - int readcount; - int framecount; - int error; - int dropped; - - int scratch_next; - int scratch_use; - int scratch_overflow; - struct se401_scratch scratch[SE401_NUMSCRATCH]; - - /* Decoder specific data: */ - unsigned char vlcdata[SE401_VLCDATALEN]; - int vlcdatapos; - int bayeroffset; - - struct se401_sbuf sbuf[SE401_NUMSBUF]; - - wait_queue_head_t wq; /* Processes waiting */ - - int nullpackets; -}; - - - -#endif - diff --git a/drivers/staging/se401/videodev.h b/drivers/staging/se401/videodev.h deleted file mode 100644 index f11efbef1c0..00000000000 --- a/drivers/staging/se401/videodev.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Video for Linux version 1 - OBSOLETE - * - * Header file for v4l1 drivers and applications, for - * Linux kernels 2.2.x or 2.4.x. - * - * Provides header for legacy drivers and applications - * - * See http://linuxtv.org for more info - * - */ -#ifndef __LINUX_VIDEODEV_H -#define __LINUX_VIDEODEV_H - -#include -#include -#include - -#define VID_TYPE_CAPTURE 1 /* Can capture */ -#define VID_TYPE_TUNER 2 /* Can tune */ -#define VID_TYPE_TELETEXT 4 /* Does teletext */ -#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ -#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ -#define VID_TYPE_CLIPPING 32 /* Can clip */ -#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ -#define VID_TYPE_SCALES 128 /* Scalable */ -#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ -#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ -#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ -#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ -#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ -#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ - -struct video_capability -{ - char name[32]; - int type; - int channels; /* Num channels */ - int audios; /* Num audio devices */ - int maxwidth; /* Supported width */ - int maxheight; /* And height */ - int minwidth; /* Supported width */ - int minheight; /* And height */ -}; - - -struct video_channel -{ - int channel; - char name[32]; - int tuners; - __u32 flags; -#define VIDEO_VC_TUNER 1 /* Channel has a tuner */ -#define VIDEO_VC_AUDIO 2 /* Channel has audio */ - __u16 type; -#define VIDEO_TYPE_TV 1 -#define VIDEO_TYPE_CAMERA 2 - __u16 norm; /* Norm set by channel */ -}; - -struct video_tuner -{ - int tuner; - char name[32]; - unsigned long rangelow, rangehigh; /* Tuner range */ - __u32 flags; -#define VIDEO_TUNER_PAL 1 -#define VIDEO_TUNER_NTSC 2 -#define VIDEO_TUNER_SECAM 4 -#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */ -#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */ -#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */ -#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */ -#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */ - __u16 mode; /* PAL/NTSC/SECAM/OTHER */ -#define VIDEO_MODE_PAL 0 -#define VIDEO_MODE_NTSC 1 -#define VIDEO_MODE_SECAM 2 -#define VIDEO_MODE_AUTO 3 - __u16 signal; /* Signal strength 16bit scale */ -}; - -struct video_picture -{ - __u16 brightness; - __u16 hue; - __u16 colour; - __u16 contrast; - __u16 whiteness; /* Black and white only */ - __u16 depth; /* Capture depth */ - __u16 palette; /* Palette in use */ -#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ -#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */ -#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ -#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ -#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ -#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ -#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */ -#define VIDEO_PALETTE_YUYV 8 -#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ -#define VIDEO_PALETTE_YUV420 10 -#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ -#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ -#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ -#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ -#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ -#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ -#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ -#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ -}; - -struct video_audio -{ - int audio; /* Audio channel */ - __u16 volume; /* If settable */ - __u16 bass, treble; - __u32 flags; -#define VIDEO_AUDIO_MUTE 1 -#define VIDEO_AUDIO_MUTABLE 2 -#define VIDEO_AUDIO_VOLUME 4 -#define VIDEO_AUDIO_BASS 8 -#define VIDEO_AUDIO_TREBLE 16 -#define VIDEO_AUDIO_BALANCE 32 - char name[16]; -#define VIDEO_SOUND_MONO 1 -#define VIDEO_SOUND_STEREO 2 -#define VIDEO_SOUND_LANG1 4 -#define VIDEO_SOUND_LANG2 8 - __u16 mode; - __u16 balance; /* Stereo balance */ - __u16 step; /* Step actual volume uses */ -}; - -struct video_clip -{ - __s32 x,y; - __s32 width, height; - struct video_clip *next; /* For user use/driver use only */ -}; - -struct video_window -{ - __u32 x,y; /* Position of window */ - __u32 width,height; /* Its size */ - __u32 chromakey; - __u32 flags; - struct video_clip __user *clips; /* Set only */ - int clipcount; -#define VIDEO_WINDOW_INTERLACE 1 -#define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */ -#define VIDEO_CLIP_BITMAP -1 -/* bitmap is 1024x625, a '1' bit represents a clipped pixel */ -#define VIDEO_CLIPMAP_SIZE (128 * 625) -}; - -struct video_capture -{ - __u32 x,y; /* Offsets into image */ - __u32 width, height; /* Area to capture */ - __u16 decimation; /* Decimation divider */ - __u16 flags; /* Flags for capture */ -#define VIDEO_CAPTURE_ODD 0 /* Temporal */ -#define VIDEO_CAPTURE_EVEN 1 -}; - -struct video_buffer -{ - void *base; - int height,width; - int depth; - int bytesperline; -}; - -struct video_mmap -{ - unsigned int frame; /* Frame (0 - n) for double buffer */ - int height,width; - unsigned int format; /* should be VIDEO_PALETTE_* */ -}; - -struct video_key -{ - __u8 key[8]; - __u32 flags; -}; - -struct video_mbuf -{ - int size; /* Total memory to map */ - int frames; /* Frames */ - int offsets[VIDEO_MAX_FRAME]; -}; - -#define VIDEO_NO_UNIT (-1) - -struct video_unit -{ - int video; /* Video minor */ - int vbi; /* VBI minor */ - int radio; /* Radio minor */ - int audio; /* Audio minor */ - int teletext; /* Teletext minor */ -}; - -struct vbi_format { - __u32 sampling_rate; /* in Hz */ - __u32 samples_per_line; - __u32 sample_format; /* VIDEO_PALETTE_RAW only (1 byte) */ - __s32 start[2]; /* starting line for each frame */ - __u32 count[2]; /* count of lines for each frame */ - __u32 flags; -#define VBI_UNSYNC 1 /* can distingues between top/bottom field */ -#define VBI_INTERLACED 2 /* lines are interlaced */ -}; - -/* video_info is biased towards hardware mpeg encode/decode */ -/* but it could apply generically to any hardware compressor/decompressor */ -struct video_info -{ - __u32 frame_count; /* frames output since decode/encode began */ - __u32 h_size; /* current unscaled horizontal size */ - __u32 v_size; /* current unscaled veritcal size */ - __u32 smpte_timecode; /* current SMPTE timecode (for current GOP) */ - __u32 picture_type; /* current picture type */ - __u32 temporal_reference; /* current temporal reference */ - __u8 user_data[256]; /* user data last found in compressed stream */ - /* user_data[0] contains user data flags, user_data[1] has count */ -}; - -/* generic structure for setting playback modes */ -struct video_play_mode -{ - int mode; - int p1; - int p2; -}; - -/* for loading microcode / fpga programming */ -struct video_code -{ - char loadwhat[16]; /* name or tag of file being passed */ - int datasize; - __u8 *data; -}; - -#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ -#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ -#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ -#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */ -#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */ -#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */ -#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */ -#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */ -#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */ -#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ -#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */ -#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */ -#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */ -#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */ -#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */ -#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */ -#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */ -#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */ -#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */ -#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */ -#define VIDIOCGUNIT _IOR('v',21, struct video_unit) /* Get attached units */ -#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get subcapture */ -#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set subcapture */ -#define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */ -#define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */ -#define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */ -#define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */ -#define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */ -#define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */ - - -#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ - -/* VIDIOCSWRITEMODE */ -#define VID_WRITE_MPEG_AUD 0 -#define VID_WRITE_MPEG_VID 1 -#define VID_WRITE_OSD 2 -#define VID_WRITE_TTX 3 -#define VID_WRITE_CC 4 -#define VID_WRITE_MJPEG 5 - -/* VIDIOCSPLAYMODE */ -#define VID_PLAY_VID_OUT_MODE 0 - /* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */ -#define VID_PLAY_GENLOCK 1 - /* p1: 0 = OFF, 1 = ON */ - /* p2: GENLOCK FINE DELAY value */ -#define VID_PLAY_NORMAL 2 -#define VID_PLAY_PAUSE 3 -#define VID_PLAY_SINGLE_FRAME 4 -#define VID_PLAY_FAST_FORWARD 5 -#define VID_PLAY_SLOW_MOTION 6 -#define VID_PLAY_IMMEDIATE_NORMAL 7 -#define VID_PLAY_SWITCH_CHANNELS 8 -#define VID_PLAY_FREEZE_FRAME 9 -#define VID_PLAY_STILL_MODE 10 -#define VID_PLAY_MASTER_MODE 11 - /* p1: see below */ -#define VID_PLAY_MASTER_NONE 1 -#define VID_PLAY_MASTER_VIDEO 2 -#define VID_PLAY_MASTER_AUDIO 3 -#define VID_PLAY_ACTIVE_SCANLINES 12 - /* p1 = first active; p2 = last active */ -#define VID_PLAY_RESET 13 -#define VID_PLAY_END_MARK 14 - -#endif /* __LINUX_VIDEODEV_H */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ -- cgit v1.2.3-70-g09d2 From 7ee40aadabd59b6cab60835f0ef9cdbe385df438 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 5 Feb 2011 10:10:38 -0300 Subject: [media] v4l: removal of old, obsolete ioctls Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong type of R/W arguments. They were fixed, but the old ioctl names are still there, maintained to avoid breaking binary compatibility: There's no sense on preserving those forever, as it is very doubtful that someone would try to use a such old binary with a modern kernel. Removing them will allow us to remove some magic done at the V4L ioctl handler. Note that any application compiled with a videodev2.h from 2.6.7 or later will be using the correct ioctls. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/feature-removal-schedule.txt | 21 ----------------- drivers/media/video/v4l2-common.c | 1 - drivers/media/video/v4l2-compat-ioctl32.c | 15 ------------ drivers/media/video/v4l2-ioctl.c | 38 ------------------------------ drivers/staging/easycap/easycap_ioctl.c | 5 ---- include/linux/videodev2.h | 10 -------- 6 files changed, 90 deletions(-) (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 08e0df12df3..61fb823e5a9 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -97,27 +97,6 @@ Who: Pavel Machek --------------------------- -What: Video4Linux: Remove obsolete ioctl's -When: kernel 2.6.39 -Files: include/media/videodev2.h -Why: Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong - type of R/W arguments. They were fixed, but the old ioctl names are - still there, maintained to avoid breaking binary compatibility: - #define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int) - #define VIDIOC_S_PARM_OLD _IOW('V', 22, struct v4l2_streamparm) - #define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct v4l2_control) - #define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct v4l2_audio) - #define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct v4l2_audioout) - #define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct v4l2_cropcap) - There's no sense on preserving those forever, as it is very doubtful - that someone would try to use a such old binary with a modern kernel. - Removing them will allow us to remove some magic done at the V4L ioctl - handler. - -Who: Mauro Carvalho Chehab - ---------------------------- - What: sys_sysctl When: September 2010 Option: CONFIG_SYSCTL_SYSCALL diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 810eef43c21..940b5db3463 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -59,7 +59,6 @@ #include #include #include -#define __OLD_VIDIOC_ /* To allow fixing old calls*/ #include #include #include diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index c19208a07b4..7c2694738b3 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -14,7 +14,6 @@ */ #include -#define __OLD_VIDIOC_ /* To allow fixing old calls*/ #include #include #include @@ -678,9 +677,6 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32) -#ifdef __OLD_VIDIOC_ -#define VIDIOC_OVERLAY32_OLD _IOWR('V', 14, s32) -#endif #define VIDIOC_STREAMON32 _IOW ('V', 18, s32) #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32) #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32) @@ -720,9 +716,6 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break; case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break; case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; -#ifdef __OLD_VIDIOC_ - case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break; -#endif case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; @@ -856,14 +849,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) return ret; switch (cmd) { -#ifdef __OLD_VIDIOC_ - case VIDIOC_OVERLAY32_OLD: - case VIDIOC_S_PARM_OLD: - case VIDIOC_S_CTRL_OLD: - case VIDIOC_G_AUDIO_OLD: - case VIDIOC_G_AUDOUT_OLD: - case VIDIOC_CROPCAP_OLD: -#endif case VIDIOC_QUERYCAP: case VIDIOC_RESERVED: case VIDIOC_ENUM_FMT: diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 8360ed2d933..7a720745c3f 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -17,7 +17,6 @@ #include #include -#define __OLD_VIDIOC_ /* To allow fixing old calls */ #include #include @@ -297,37 +296,6 @@ EXPORT_SYMBOL(v4l_printk_ioctl); /* * helper function -- handles userspace copying for ioctl arguments - */ - -#ifdef __OLD_VIDIOC_ -static unsigned int -video_fix_command(unsigned int cmd) -{ - switch (cmd) { - case VIDIOC_OVERLAY_OLD: - cmd = VIDIOC_OVERLAY; - break; - case VIDIOC_S_PARM_OLD: - cmd = VIDIOC_S_PARM; - break; - case VIDIOC_S_CTRL_OLD: - cmd = VIDIOC_S_CTRL; - break; - case VIDIOC_G_AUDIO_OLD: - cmd = VIDIOC_G_AUDIO; - break; - case VIDIOC_G_AUDOUT_OLD: - cmd = VIDIOC_G_AUDOUT; - break; - case VIDIOC_CROPCAP_OLD: - cmd = VIDIOC_CROPCAP; - break; - } - return cmd; -} -#endif - -/* * Obsolete usercopy function - Should be removed soon */ long @@ -342,9 +310,6 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, size_t ctrls_size = 0; void __user *user_ptr = NULL; -#ifdef __OLD_VIDIOC_ - cmd = video_fix_command(cmd); -#endif is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS || cmd == VIDIOC_TRY_EXT_CTRLS); @@ -2379,9 +2344,6 @@ long video_ioctl2(struct file *file, void __user *user_ptr = NULL; void **kernel_ptr = NULL; -#ifdef __OLD_VIDIOC_ - cmd = video_fix_command(cmd); -#endif /* Copy arguments into temp kernel buffer */ if (_IOC_DIR(cmd) != _IOC_NONE) { if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c index 447953a4e80..7ac43da4e25 100644 --- a/drivers/staging/easycap/easycap_ioctl.c +++ b/drivers/staging/easycap/easycap_ioctl.c @@ -1399,11 +1399,6 @@ case VIDIOC_G_CTRL: { break; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -#if defined(VIDIOC_S_CTRL_OLD) -case VIDIOC_S_CTRL_OLD: { - JOM(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n"); -} -#endif /*VIDIOC_S_CTRL_OLD*/ case VIDIOC_S_CTRL: { struct v4l2_control v4l2_control; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 5122b265dde..a94c4d5ac34 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1935,16 +1935,6 @@ struct v4l2_dbg_chip_ident { /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ -#ifdef __OLD_VIDIOC_ -/* for compatibility, will go away some day */ -#define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int) -#define VIDIOC_S_PARM_OLD _IOW('V', 22, struct v4l2_streamparm) -#define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct v4l2_control) -#define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct v4l2_audio) -#define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct v4l2_audioout) -#define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct v4l2_cropcap) -#endif - #define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ #endif /* __LINUX_VIDEODEV2_H */ -- cgit v1.2.3-70-g09d2 From e45c2be9704381971d78d711e58dec35b1c4cf6f Mon Sep 17 00:00:00 2001 From: Paul Cassella Date: Tue, 8 Feb 2011 21:07:00 -0300 Subject: [media] Documentation: README.ivtv: Remove note that ivtvfb is not yet in the kernel ivtvfb is now in the kernel, so stop saying it's not. Signed-off-by: Paul Cassella Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/README.ivtv | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/README.ivtv b/Documentation/video4linux/README.ivtv index 42b06686eb7..2579b5b709e 100644 --- a/Documentation/video4linux/README.ivtv +++ b/Documentation/video4linux/README.ivtv @@ -36,8 +36,7 @@ Additional features for the PVR-350 (CX23415 based): * Provides comprehensive OSD (On Screen Display: ie. graphics overlaying the video signal) * Provides a framebuffer (allowing X applications to appear on the video - device) (this framebuffer is not yet part of the kernel. In the meantime it - is available from www.ivtvdriver.org). + device) * Supports raw YUV output. IMPORTANT: In case of problems first read this page: -- cgit v1.2.3-70-g09d2 From f6a373fb0569c98d6a44108f5e879f06abd46df3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 1 Mar 2011 09:48:27 -0300 Subject: [media] videodev2.h.xml: Update to reflect videodev2.h changes A few changes happened at videodev2.h: - Addition of multiplane API; - removal of VIDIOC_*_OLD ioctls; - a few more video standards. Update the file to reflect the latest changes. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/videodev2.h.xml | 141 +++++++++++++++++++++++++++--- 1 file changed, 129 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index 325b23b6964..2b796a2ee98 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml @@ -71,6 +71,7 @@ * Moved from videodev.h */ #define VIDEO_MAX_FRAME 32 +#define VIDEO_MAX_PLANES 8 #ifndef __KERNEL__ @@ -158,9 +159,23 @@ enum v4l2_buf_type { /* Experimental */ V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, #endif + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10, V4L2_BUF_TYPE_PRIVATE = 0x80, }; +#define V4L2_TYPE_IS_MULTIPLANAR(type) \ + ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + +#define V4L2_TYPE_IS_OUTPUT(type) \ + ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE \ + || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY \ + || (type) == V4L2_BUF_TYPE_VBI_OUTPUT \ + || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) + enum v4l2_tuner_type { V4L2_TUNER_RADIO = 1, V4L2_TUNER_ANALOG_TV = 2, @@ -246,6 +261,11 @@ struct v4l2_capability { #define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek */ #define V4L2_CAP_RDS_OUTPUT 0x00000800 /* Is an RDS encoder */ +/* Is a video capture device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000 +/* Is a video output device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_OUTPUT_MPLANE 0x00002000 + #define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ #define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ #define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ @@ -320,6 +340,13 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */ #define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */ +/* two non contiguous planes - one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ + +/* three non contiguous planes - Y, Cb, Cr */ +#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */ + /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ @@ -518,6 +545,62 @@ struct v4l2_requestbuffers { __u32 reserved[2]; }; +/** + * struct v4l2_plane - plane info for multi-planar buffers + * @bytesused: number of bytes occupied by data in the plane (payload) + * @length: size of this plane (NOT the payload) in bytes + * @mem_offset: when memory in the associated struct v4l2_buffer is + * V4L2_MEMORY_MMAP, equals the offset from the start of + * the device memory for this plane (or is a "cookie" that + * should be passed to mmap() called on the video node) + * @userptr: when memory is V4L2_MEMORY_USERPTR, a userspace pointer + * pointing to this plane + * @data_offset: offset in the plane to the start of data; usually 0, + * unless there is a header in front of the data + * + * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer + * with two planes can have one plane for Y, and another for interleaved CbCr + * components. Each plane can reside in a separate memory buffer, or even in + * a completely separate memory node (e.g. in embedded devices). + */ +struct v4l2_plane { + __u32 bytesused; + __u32 length; + union { + __u32 mem_offset; + unsigned long userptr; + } m; + __u32 data_offset; + __u32 reserved[11]; +}; + +/** + * struct v4l2_buffer - video buffer info + * @index: id number of the buffer + * @type: buffer type (type == *_MPLANE for multiplanar buffers) + * @bytesused: number of bytes occupied by data in the buffer (payload); + * unused (set to 0) for multiplanar buffers + * @flags: buffer informational flags + * @field: field order of the image in the buffer + * @timestamp: frame timestamp + * @timecode: frame timecode + * @sequence: sequence count of this frame + * @memory: the method, in which the actual video data is passed + * @offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP; + * offset from the start of the device memory for this plane, + * (or a "cookie" that should be passed to mmap() as offset) + * @userptr: for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR; + * a userspace pointer pointing to this buffer + * @planes: for multiplanar buffers; userspace pointer to the array of plane + * info structs for this buffer + * @length: size in bytes of the buffer (NOT its payload) for single-plane + * buffers (when type != *_MPLANE); number of elements in the + * planes array for multi-plane buffers + * @input: input number from which the video data has has been captured + * + * Contains data exchanged by application and driver using one of the Streaming + * I/O methods. + */ struct v4l2_buffer { __u32 index; enum v4l2_buf_type type; @@ -533,6 +616,7 @@ struct v4l2_buffer { union { __u32 offset; unsigned long userptr; + struct v4l2_plane *planes; } m; __u32 length; __u32 input; @@ -1623,12 +1707,56 @@ struct v4l2_mpeg_vbi_fmt_ivtv { * A G G R E G A T E S T R U C T U R E S */ -/* Stream data format +/** + * struct v4l2_plane_pix_format - additional, per-plane format definition + * @sizeimage: maximum size in bytes required for data, for which + * this plane will be used + * @bytesperline: distance in bytes between the leftmost pixels in two + * adjacent lines + */ +struct v4l2_plane_pix_format { + __u32 sizeimage; + __u16 bytesperline; + __u16 reserved[7]; +} __attribute__ ((packed)); + +/** + * struct v4l2_pix_format_mplane - multiplanar format definition + * @width: image width in pixels + * @height: image height in pixels + * @pixelformat: little endian four character code (fourcc) + * @field: field order (for interlaced video) + * @colorspace: supplemental to pixelformat + * @plane_fmt: per-plane information + * @num_planes: number of planes for this format + */ +struct v4l2_pix_format_mplane { + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + enum v4l2_colorspace colorspace; + + struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES]; + __u8 num_planes; + __u8 reserved[11]; +} __attribute__ ((packed)); + +/** + * struct v4l2_format - stream data format + * @type: type of the data stream + * @pix: definition of an image format + * @pix_mp: definition of a multiplanar image format + * @win: definition of an overlaid image + * @vbi: raw VBI capture or output parameters + * @sliced: sliced VBI capture or output parameters + * @raw_data: placeholder for future extensions and custom formats */ struct v4l2_format { enum v4l2_buf_type type; union { struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ + struct v4l2_pix_format_mplane pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */ struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ @@ -1636,7 +1764,6 @@ struct v4l2_format { } fmt; }; - /* Stream type-dependent parameters */ struct v4l2_streamparm { @@ -1809,16 +1936,6 @@ struct v4l2_dbg_chip_ident { /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ -#ifdef __OLD_VIDIOC_ -/* for compatibility, will go away some day */ -#define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int) -#define VIDIOC_S_PARM_OLD _IOW('V', 22, struct v4l2_streamparm) -#define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct v4l2_control) -#define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct v4l2_audio) -#define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct v4l2_audioout) -#define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct v4l2_cropcap) -#endif - #define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ #endif /* __LINUX_VIDEODEV2_H */ -- cgit v1.2.3-70-g09d2 From a602d520acd331ba8bbc02aacccb5e9a0f561f25 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 1 Mar 2011 10:12:36 -0300 Subject: [media] DocBook: Document the removal of the old VIDIOC_*_OLD ioctls Those ioctls passed away. Properly documented it. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/compat.xml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/compat.xml b/Documentation/DocBook/v4l/compat.xml index 223c24c536b..4d74bf24e11 100644 --- a/Documentation/DocBook/v4l/compat.xml +++ b/Documentation/DocBook/v4l/compat.xml @@ -1711,8 +1711,8 @@ ioctl would enumerate the available audio inputs. An ioctl to determine the current audio input, if more than one combines with the current video input, did not exist. So VIDIOC_G_AUDIO was renamed to -VIDIOC_G_AUDIO_OLD, this ioctl will be removed in -the future. The &VIDIOC-ENUMAUDIO; ioctl was added to enumerate +VIDIOC_G_AUDIO_OLD, this ioctl was removed on +Kernel 2.6.39. The &VIDIOC-ENUMAUDIO; ioctl was added to enumerate audio inputs, while &VIDIOC-G-AUDIO; now reports the current audio input. The same changes were made to &VIDIOC-G-AUDOUT; and @@ -1726,7 +1726,7 @@ must be updated to successfully compile again. The &VIDIOC-OVERLAY; ioctl was incorrectly defined with write-read parameter. It was changed to write-only, while the write-read version was renamed to VIDIOC_OVERLAY_OLD. The old -ioctl will be removed in the future. Until further the "videodev" +ioctl was removed on Kernel 2.6.39. Until further the "videodev" kernel module will automatically translate to the new version, so drivers must be recompiled, but not applications. @@ -1744,7 +1744,7 @@ surface can be seen. defined with write-only parameter, inconsistent with other ioctls modifying their argument. They were changed to write-read, while a _OLD suffix was added to the write-only versions. -The old ioctls will be removed in the future. Drivers and +The old ioctls were removed on Kernel 2.6.39. Drivers and applications assuming a constant parameter need an update. @@ -1815,8 +1815,8 @@ yet to be addressed, for details see The &VIDIOC-CROPCAP; ioctl was incorrectly defined with read-only parameter. It is now defined as write-read ioctl, while the read-only version was renamed to -VIDIOC_CROPCAP_OLD. The old ioctl will be removed -in the future. +VIDIOC_CROPCAP_OLD. The old ioctl was removed +on Kernel 2.6.39.
@@ -2364,6 +2364,14 @@ that used it. It was originally scheduled for removal in 2.6.35. +
+ V4L2 in Linux 2.6.39 + + + The old VIDIOC_*_OLD symbols and V4L1 support were removed. + + +
Relation of V4L2 to other Linux multimedia APIs -- cgit v1.2.3-70-g09d2 From 3822f18d8f1c2cf13ade623b2bba6d4a7a1a3f53 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 1 Mar 2011 16:03:11 -0300 Subject: [media] DocBook/v4l2.xml: Update version of the spec Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/v4l2.xml | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index c3d699173c1..7859d7d9da3 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -127,6 +127,14 @@ structs, ioctls) must be noted in more detail in the history chapter (compat.xml), along with the possible impact on existing drivers and applications. --> + + 2.6.39 + 2011-03-01 + mcc + Removed VIDIOC_*_OLD from videodev2.h header and update it to reflect latest changes. + + + 2.6.38 2011-01-16 -- cgit v1.2.3-70-g09d2 From 2096a5dcf9704f5a86ecba37169eb813aaf0431c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:38:49 -0300 Subject: [media] v4l: subdev: Add device node support Create a device node named subdevX for every registered subdev. As the device node is registered before the subdev core::s_config function is called, return -EGAIN on open until initialization completes. Signed-off-by: Laurent Pinchart Signed-off-by: Vimarsh Zutshi Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 16 ++++++++ drivers/media/video/Makefile | 2 +- drivers/media/video/v4l2-dev.c | 27 +++++-------- drivers/media/video/v4l2-device.c | 37 +++++++++++++++++ drivers/media/video/v4l2-subdev.c | 60 ++++++++++++++++++++++++++++ include/media/v4l2-dev.h | 18 +++++++-- include/media/v4l2-device.h | 6 +++ include/media/v4l2-subdev.h | 14 ++++++- 8 files changed, 158 insertions(+), 22 deletions(-) create mode 100644 drivers/media/video/v4l2-subdev.c (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index f22f35c271f..8b358710b2f 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -319,6 +319,22 @@ controlled through GPIO pins. This distinction is only relevant when setting up the device, but once the subdev is registered it is completely transparent. +V4L2 sub-device userspace API +----------------------------- + +Beside exposing a kernel API through the v4l2_subdev_ops structure, V4L2 +sub-devices can also be controlled directly by userspace applications. + +Device nodes named v4l-subdevX can be created in /dev to access sub-devices +directly. If a sub-device supports direct userspace configuration it must set +the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered. + +After registering sub-devices, the v4l2_device driver can create device nodes +for all registered sub-devices marked with V4L2_SUBDEV_FL_HAS_DEVNODE by calling +v4l2_device_register_subdev_nodes(). Those device nodes will be automatically +removed when sub-devices are unregistered. + + I2C sub-device drivers ---------------------- diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index ac54652396e..7ea65163090 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -11,7 +11,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ - v4l2-event.o v4l2-ctrls.o + v4l2-event.o v4l2-ctrls.o v4l2-subdev.o # V4L2 core modules diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 341764a3a99..abe04ef3806 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -408,13 +408,14 @@ static int get_index(struct video_device *vdev) } /** - * video_register_device - register video4linux devices + * __video_register_device - register video4linux devices * @vdev: video device structure we want to register * @type: type of device to register * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ... * -1 == first free) * @warn_if_nr_in_use: warn if the desired device node number * was already in use and another number was chosen instead. + * @owner: module that owns the video device node * * The registration code assigns minor numbers and device node numbers * based on the requested type and registers the new device node with @@ -435,9 +436,11 @@ static int get_index(struct video_device *vdev) * %VFL_TYPE_VBI - Vertical blank data (undecoded) * * %VFL_TYPE_RADIO - A radio card + * + * %VFL_TYPE_SUBDEV - A subdevice */ -static int __video_register_device(struct video_device *vdev, int type, int nr, - int warn_if_nr_in_use) +int __video_register_device(struct video_device *vdev, int type, int nr, + int warn_if_nr_in_use, struct module *owner) { int i = 0; int ret; @@ -469,6 +472,9 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, case VFL_TYPE_RADIO: name_base = "radio"; break; + case VFL_TYPE_SUBDEV: + name_base = "v4l-subdev"; + break; default: printk(KERN_ERR "%s called with unknown type: %d\n", __func__, type); @@ -552,7 +558,7 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, goto cleanup; } vdev->cdev->ops = &v4l2_fops; - vdev->cdev->owner = vdev->fops->owner; + vdev->cdev->owner = owner; ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); if (ret < 0) { printk(KERN_ERR "%s: cdev_add failed\n", __func__); @@ -597,18 +603,7 @@ cleanup: vdev->minor = -1; return ret; } - -int video_register_device(struct video_device *vdev, int type, int nr) -{ - return __video_register_device(vdev, type, nr, 1); -} -EXPORT_SYMBOL(video_register_device); - -int video_register_device_no_warn(struct video_device *vdev, int type, int nr) -{ - return __video_register_device(vdev, type, nr, 0); -} -EXPORT_SYMBOL(video_register_device_no_warn); +EXPORT_SYMBOL(__video_register_device); /** * video_unregister_device - unregister a video4linux device diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index ce64fe16bc6..8c0ad8b372d 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -124,16 +124,20 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, /* Check for valid input */ if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) return -EINVAL; + /* Warn if we apparently re-register a subdev */ WARN_ON(sd->v4l2_dev != NULL); + if (!try_module_get(sd->owner)) return -ENODEV; + sd->v4l2_dev = v4l2_dev; if (sd->internal_ops && sd->internal_ops->registered) { err = sd->internal_ops->registered(sd); if (err) return err; } + /* This just returns 0 if either of the two args is NULL */ err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler); if (err) { @@ -141,24 +145,57 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, sd->internal_ops->unregistered(sd); return err; } + spin_lock(&v4l2_dev->lock); list_add_tail(&sd->list, &v4l2_dev->subdevs); spin_unlock(&v4l2_dev->lock); + return 0; } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); +int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) +{ + struct video_device *vdev; + struct v4l2_subdev *sd; + int err; + + /* Register a device node for every subdev marked with the + * V4L2_SUBDEV_FL_HAS_DEVNODE flag. + */ + list_for_each_entry(sd, &v4l2_dev->subdevs, list) { + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) + continue; + + vdev = &sd->devnode; + strlcpy(vdev->name, sd->name, sizeof(vdev->name)); + vdev->v4l2_dev = v4l2_dev; + vdev->fops = &v4l2_subdev_fops; + vdev->release = video_device_release_empty; + err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1, + sd->owner); + if (err < 0) + return err; + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes); + void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) { /* return if it isn't registered */ if (sd == NULL || sd->v4l2_dev == NULL) return; + spin_lock(&sd->v4l2_dev->lock); list_del(&sd->list); spin_unlock(&sd->v4l2_dev->lock); if (sd->internal_ops && sd->internal_ops->unregistered) sd->internal_ops->unregistered(sd); sd->v4l2_dev = NULL; + + video_unregister_device(&sd->devnode); module_put(sd->owner); } EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev); diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c new file mode 100644 index 00000000000..037aa28a5ed --- /dev/null +++ b/drivers/media/video/v4l2-subdev.c @@ -0,0 +1,60 @@ +/* + * V4L2 subdevice support. + * + * Copyright (C) 2010 Nokia Corporation + * + * Contact: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include + +static int subdev_open(struct file *file) +{ + return 0; +} + +static int subdev_close(struct file *file) +{ + return 0; +} + +static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) +{ + switch (cmd) { + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static long subdev_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return video_usercopy(file, cmd, arg, subdev_do_ioctl); +} + +const struct v4l2_file_operations v4l2_subdev_fops = { + .owner = THIS_MODULE, + .open = subdev_open, + .unlocked_ioctl = subdev_ioctl, + .release = subdev_close, +}; diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 15802a067a1..4fe6831b185 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -21,7 +21,8 @@ #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 -#define VFL_TYPE_MAX 3 +#define VFL_TYPE_SUBDEV 3 +#define VFL_TYPE_MAX 4 struct v4l2_ioctl_callbacks; struct video_device; @@ -102,15 +103,26 @@ struct video_device /* dev to video-device */ #define to_video_device(cd) container_of(cd, struct video_device, dev) +int __must_check __video_register_device(struct video_device *vdev, int type, + int nr, int warn_if_nr_in_use, struct module *owner); + /* Register video devices. Note that if video_register_device fails, the release() callback of the video_device structure is *not* called, so the caller is responsible for freeing any data. Usually that means that you call video_device_release() on failure. */ -int __must_check video_register_device(struct video_device *vdev, int type, int nr); +static inline int __must_check video_register_device(struct video_device *vdev, + int type, int nr) +{ + return __video_register_device(vdev, type, nr, 1, vdev->fops->owner); +} /* Same as video_register_device, but no warning is issued if the desired device node number was already in use. */ -int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr); +static inline int __must_check video_register_device_no_warn( + struct video_device *vdev, int type, int nr) +{ + return __video_register_device(vdev, type, nr, 0, vdev->fops->owner); +} /* Unregister video devices. Will do nothing if vdev == NULL or video_is_registered() returns false. */ diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index b16f307d471..78b11e5a6db 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -96,6 +96,12 @@ int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, wasn't registered. In that case it will do nothing. */ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); +/* Register device nodes for all subdev of the v4l2 device that are marked with + * the V4L2_SUBDEV_FL_HAS_DEVNODE flag. + */ +int __must_check +v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev); + /* Iterate over all subdevs. */ #define v4l2_device_for_each_subdev(sd, v4l2_dev) \ list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index da16d2f4a00..474ef009fd3 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -22,6 +22,7 @@ #define _V4L2_SUBDEV_H #include +#include #include /* generic v4l2_device notify callback notification values */ @@ -431,9 +432,11 @@ struct v4l2_subdev_internal_ops { #define V4L2_SUBDEV_NAME_SIZE 32 /* Set this flag if this subdev is a i2c device. */ -#define V4L2_SUBDEV_FL_IS_I2C (1U << 0) +#define V4L2_SUBDEV_FL_IS_I2C (1U << 0) /* Set this flag if this subdev is a spi device. */ -#define V4L2_SUBDEV_FL_IS_SPI (1U << 1) +#define V4L2_SUBDEV_FL_IS_SPI (1U << 1) +/* Set this flag if this subdev needs a device node. */ +#define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2) /* Each instance of a subdev driver should create this struct, either stand-alone or embedded in a larger struct. @@ -455,8 +458,15 @@ struct v4l2_subdev { /* pointer to private data */ void *dev_priv; void *host_priv; + /* subdev device node */ + struct video_device devnode; }; +#define vdev_to_v4l2_subdev(vdev) \ + container_of(vdev, struct v4l2_subdev, devnode) + +extern const struct v4l2_file_operations v4l2_subdev_fops; + static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p) { sd->dev_priv = p; -- cgit v1.2.3-70-g09d2 From ea8aa4349e11c62242a8908fc172de27d7a151d7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:39:54 -0300 Subject: [media] v4l: subdev: Control ioctls support Pass the control-related ioctls to the subdev driver through the control framework. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 16 ++++++++++++++++ drivers/media/video/v4l2-subdev.c | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 8b358710b2f..1feecfc59c3 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -334,6 +334,22 @@ for all registered sub-devices marked with V4L2_SUBDEV_FL_HAS_DEVNODE by calling v4l2_device_register_subdev_nodes(). Those device nodes will be automatically removed when sub-devices are unregistered. +The device node handles a subset of the V4L2 API. + +VIDIOC_QUERYCTRL +VIDIOC_QUERYMENU +VIDIOC_G_CTRL +VIDIOC_S_CTRL +VIDIOC_G_EXT_CTRLS +VIDIOC_S_EXT_CTRLS +VIDIOC_TRY_EXT_CTRLS + + The controls ioctls are identical to the ones defined in V4L2. They + behave identically, with the only exception that they deal only with + controls implemented in the sub-device. Depending on the driver, those + controls can be also be accessed through one (or several) V4L2 device + nodes. + I2C sub-device drivers ---------------------- diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 460b33697c9..da10430051c 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -39,7 +40,31 @@ static int subdev_close(struct file *file) static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) { + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + switch (cmd) { + case VIDIOC_QUERYCTRL: + return v4l2_subdev_queryctrl(sd, arg); + + case VIDIOC_QUERYMENU: + return v4l2_subdev_querymenu(sd, arg); + + case VIDIOC_G_CTRL: + return v4l2_subdev_g_ctrl(sd, arg); + + case VIDIOC_S_CTRL: + return v4l2_subdev_s_ctrl(sd, arg); + + case VIDIOC_G_EXT_CTRLS: + return v4l2_subdev_g_ext_ctrls(sd, arg); + + case VIDIOC_S_EXT_CTRLS: + return v4l2_subdev_s_ext_ctrls(sd, arg); + + case VIDIOC_TRY_EXT_CTRLS: + return v4l2_subdev_try_ext_ctrls(sd, arg); + default: return -ENOIOCTLCMD; } -- cgit v1.2.3-70-g09d2 From 02adb1cc765b8c29dc83c6602bda19003cce62f1 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 3 Mar 2010 12:49:38 -0300 Subject: [media] v4l: subdev: Events support Provide v4l2_subdevs with v4l2_event support. Subdev drivers only need very little to support events. Signed-off-by: Sakari Ailus Signed-off-by: David Cohen Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 18 +++++++ drivers/media/video/v4l2-subdev.c | 78 +++++++++++++++++++++++++++- include/media/v4l2-subdev.h | 10 ++++ 3 files changed, 105 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 1feecfc59c3..eb8479565dc 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -350,6 +350,24 @@ VIDIOC_TRY_EXT_CTRLS controls can be also be accessed through one (or several) V4L2 device nodes. +VIDIOC_DQEVENT +VIDIOC_SUBSCRIBE_EVENT +VIDIOC_UNSUBSCRIBE_EVENT + + The events ioctls are identical to the ones defined in V4L2. They + behave identically, with the only exception that they deal only with + events generated by the sub-device. Depending on the driver, those + events can also be reported by one (or several) V4L2 device nodes. + + Sub-device drivers that want to use events need to set the + V4L2_SUBDEV_USES_EVENTS v4l2_subdev::flags and initialize + v4l2_subdev::nevents to events queue depth before registering the + sub-device. After registration events can be queued as usual on the + v4l2_subdev::devnode device node. + + To properly support events, the poll() file operation is also + implemented. + I2C sub-device drivers ---------------------- diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index da10430051c..0c67f5a278f 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -20,21 +20,66 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include +#include +#include #include #include #include #include +#include +#include static int subdev_open(struct file *file) { + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + struct v4l2_fh *vfh; + int ret; + + if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) { + vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); + if (vfh == NULL) + return -ENOMEM; + + ret = v4l2_fh_init(vfh, vdev); + if (ret) + goto err; + + ret = v4l2_event_init(vfh); + if (ret) + goto err; + + ret = v4l2_event_alloc(vfh, sd->nevents); + if (ret) + goto err; + + v4l2_fh_add(vfh); + file->private_data = vfh; + } + return 0; + +err: + if (vfh != NULL) { + v4l2_fh_exit(vfh); + kfree(vfh); + } + + return ret; } static int subdev_close(struct file *file) { + struct v4l2_fh *vfh = file->private_data; + + if (vfh != NULL) { + v4l2_fh_del(vfh); + v4l2_fh_exit(vfh); + kfree(vfh); + } + return 0; } @@ -42,6 +87,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + struct v4l2_fh *fh = file->private_data; switch (cmd) { case VIDIOC_QUERYCTRL: @@ -65,6 +111,18 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_TRY_EXT_CTRLS: return v4l2_subdev_try_ext_ctrls(sd, arg); + case VIDIOC_DQEVENT: + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) + return -ENOIOCTLCMD; + + return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK); + + case VIDIOC_SUBSCRIBE_EVENT: + return v4l2_subdev_call(sd, core, subscribe_event, fh, arg); + + case VIDIOC_UNSUBSCRIBE_EVENT: + return v4l2_subdev_call(sd, core, unsubscribe_event, fh, arg); + default: return -ENOIOCTLCMD; } @@ -78,11 +136,29 @@ static long subdev_ioctl(struct file *file, unsigned int cmd, return video_usercopy(file, cmd, arg, subdev_do_ioctl); } +static unsigned int subdev_poll(struct file *file, poll_table *wait) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + struct v4l2_fh *fh = file->private_data; + + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) + return POLLERR; + + poll_wait(file, &fh->events->wait, wait); + + if (v4l2_event_pending(fh)) + return POLLPRI; + + return 0; +} + const struct v4l2_file_operations v4l2_subdev_fops = { .owner = THIS_MODULE, .open = subdev_open, .unlocked_ioctl = subdev_ioctl, .release = subdev_close, + .poll = subdev_poll, }; void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 3276065022e..0f9937be53d 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -37,6 +37,8 @@ struct v4l2_device; struct v4l2_ctrl_handler; +struct v4l2_event_subscription; +struct v4l2_fh; struct v4l2_subdev; struct tuner_setup; @@ -161,6 +163,10 @@ struct v4l2_subdev_core_ops { int (*s_power)(struct v4l2_subdev *sd, int on); int (*interrupt_service_routine)(struct v4l2_subdev *sd, u32 status, bool *handled); + int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); + int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); }; /* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio. @@ -437,6 +443,8 @@ struct v4l2_subdev_internal_ops { #define V4L2_SUBDEV_FL_IS_SPI (1U << 1) /* Set this flag if this subdev needs a device node. */ #define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2) +/* Set this flag if this subdev generates events. */ +#define V4L2_SUBDEV_FL_HAS_EVENTS (1U << 3) /* Each instance of a subdev driver should create this struct, either stand-alone or embedded in a larger struct. @@ -460,6 +468,8 @@ struct v4l2_subdev { void *host_priv; /* subdev device node */ struct video_device devnode; + /* number of events to be allocated on open */ + unsigned int nevents; }; #define vdev_to_v4l2_subdev(vdev) \ -- cgit v1.2.3-70-g09d2 From 176fb0d108f7495ccf9aa127e1342a1a0d87e004 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:39:58 -0300 Subject: [media] media: Media device The media_device structure abstracts functions common to all kind of media devices (v4l2, dvb, alsa, ...). It manages media entities and offers a userspace API to discover and configure the media device internal topology. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/ABI/testing/sysfs-bus-media | 6 ++ Documentation/DocBook/media-entities.tmpl | 2 + Documentation/DocBook/media.tmpl | 3 + Documentation/DocBook/v4l/media-controller.xml | 56 ++++++++++++++ Documentation/media-framework.txt | 67 +++++++++++++++++ drivers/media/Makefile | 2 +- drivers/media/media-device.c | 100 +++++++++++++++++++++++++ include/media/media-device.h | 69 +++++++++++++++++ 8 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-media create mode 100644 Documentation/DocBook/v4l/media-controller.xml create mode 100644 Documentation/media-framework.txt create mode 100644 drivers/media/media-device.c create mode 100644 include/media/media-device.h (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-bus-media b/Documentation/ABI/testing/sysfs-bus-media new file mode 100644 index 00000000000..7057e574154 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-media @@ -0,0 +1,6 @@ +What: /sys/bus/media/devices/.../model +Date: January 2011 +Contact: Laurent Pinchart + linux-media@vger.kernel.org +Description: Contains the device model name in UTF-8. The device version is + is not be appended to the model name. diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index d2f99e5a3a2..c47897f046b 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -327,6 +327,8 @@ + + diff --git a/Documentation/DocBook/media.tmpl b/Documentation/DocBook/media.tmpl index a99088aae1a..88f2cc680cc 100644 --- a/Documentation/DocBook/media.tmpl +++ b/Documentation/DocBook/media.tmpl @@ -106,6 +106,9 @@ Foundation. A copy of the license is included in the chapter entitled &sub-remote_controllers; + +&sub-media-controller; + &sub-fdl-appendix; diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml new file mode 100644 index 00000000000..253ddb4426c --- /dev/null +++ b/Documentation/DocBook/v4l/media-controller.xml @@ -0,0 +1,56 @@ + + + + Laurent + Pinchart +
laurent.pinchart@ideasonboard.com
+ Initial version. +
+
+ + 2010 + Laurent Pinchart + + + + + + 1.0.0 + 2010-11-10 + lp + Initial revision + + +
+ +Media Controller API + + + Media Controller + +
+ Introduction + Media devices increasingly handle multiple related functions. Many USB + cameras include microphones, video capture hardware can also output video, + or SoC camera interfaces also perform memory-to-memory operations similar to + video codecs. + Independent functions, even when implemented in the same hardware, can + be modelled as separate devices. A USB camera with a microphone will be + presented to userspace applications as V4L2 and ALSA capture devices. The + devices' relationships (when using a webcam, end-users shouldn't have to + manually select the associated USB microphone), while not made available + directly to applications by the drivers, can usually be retrieved from + sysfs. + With more and more advanced SoC devices being introduced, the current + approach will not scale. Device topologies are getting increasingly complex + and can't always be represented by a tree structure. Hardware blocks are + shared between different functions, creating dependencies between seemingly + unrelated devices. + Kernel abstraction APIs such as V4L2 and ALSA provide means for + applications to access hardware parameters. As newer hardware expose an + increasingly high number of those parameters, drivers need to guess what + applications really require based on limited information, thereby + implementing policies that belong to userspace. + The media controller API aims at solving those problems. +
+
diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt new file mode 100644 index 00000000000..1844c3f1072 --- /dev/null +++ b/Documentation/media-framework.txt @@ -0,0 +1,67 @@ +Linux kernel media framework +============================ + +This document describes the Linux kernel media framework, its data structures, +functions and their usage. + + +Introduction +------------ + +The media controller API is documented in DocBook format in +Documentation/DocBook/v4l/media-controller.xml. This document will focus on +the kernel-side implementation of the media framework. + + +Media device +------------ + +A media device is represented by a struct media_device instance, defined in +include/media/media-device.h. Allocation of the structure is handled by the +media device driver, usually by embedding the media_device instance in a +larger driver-specific structure. + +Drivers register media device instances by calling + + media_device_register(struct media_device *mdev); + +The caller is responsible for initializing the media_device structure before +registration. The following fields must be set: + + - dev must point to the parent device (usually a pci_dev, usb_interface or + platform_device instance). + + - model must be filled with the device model name as a NUL-terminated UTF-8 + string. The device/model revision must not be stored in this field. + +The following fields are optional: + + - serial is a unique serial number stored as a NUL-terminated ASCII string. + The field is big enough to store a GUID in text form. If the hardware + doesn't provide a unique serial number this field must be left empty. + + - bus_info represents the location of the device in the system as a + NUL-terminated ASCII string. For PCI/PCIe devices bus_info must be set to + "PCI:" (or "PCIe:") followed by the value of pci_name(). For USB devices, + the usb_make_path() function must be used. This field is used by + applications to distinguish between otherwise identical devices that don't + provide a serial number. + + - hw_revision is the hardware device revision in a driver-specific format. + When possible the revision should be formatted with the KERNEL_VERSION + macro. + + - driver_version is formatted with the KERNEL_VERSION macro. The version + minor must be incremented when new features are added to the userspace API + without breaking binary compatibility. The version major must be + incremented when binary compatibility is broken. + +Upon successful registration a character device named media[0-9]+ is created. +The device major and minor numbers are dynamic. The model name is exported as +a sysfs attribute. + +Drivers unregister media device instances by calling + + media_device_unregister(struct media_device *mdev); + +Unregistering a media device that hasn't been registered is *NOT* safe. diff --git a/drivers/media/Makefile b/drivers/media/Makefile index d56349f6103..36731aae57e 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -2,7 +2,7 @@ # Makefile for the kernel multimedia device drivers. # -media-objs := media-devnode.o +media-objs := media-device.o media-devnode.o ifeq ($(CONFIG_MEDIA_CONTROLLER),y) obj-$(CONFIG_MEDIA_SUPPORT) += media.o diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c new file mode 100644 index 00000000000..bcd3985d415 --- /dev/null +++ b/drivers/media/media-device.c @@ -0,0 +1,100 @@ +/* + * Media device + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include +#include + +static const struct media_file_operations media_device_fops = { + .owner = THIS_MODULE, +}; + +/* ----------------------------------------------------------------------------- + * sysfs + */ + +static ssize_t show_model(struct device *cd, + struct device_attribute *attr, char *buf) +{ + struct media_device *mdev = to_media_device(to_media_devnode(cd)); + + return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model); +} + +static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); + +/* ----------------------------------------------------------------------------- + * Registration/unregistration + */ + +static void media_device_release(struct media_devnode *mdev) +{ +} + +/** + * media_device_register - register a media device + * @mdev: The media device + * + * The caller is responsible for initializing the media device before + * registration. The following fields must be set: + * + * - dev must point to the parent device + * - model must be filled with the device model name + */ +int __must_check media_device_register(struct media_device *mdev) +{ + int ret; + + if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0)) + return -EINVAL; + + /* Register the device node. */ + mdev->devnode.fops = &media_device_fops; + mdev->devnode.parent = mdev->dev; + mdev->devnode.release = media_device_release; + ret = media_devnode_register(&mdev->devnode); + if (ret < 0) + return ret; + + ret = device_create_file(&mdev->devnode.dev, &dev_attr_model); + if (ret < 0) { + media_devnode_unregister(&mdev->devnode); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(media_device_register); + +/** + * media_device_unregister - unregister a media device + * @mdev: The media device + * + */ +void media_device_unregister(struct media_device *mdev) +{ + device_remove_file(&mdev->devnode.dev, &dev_attr_model); + media_devnode_unregister(&mdev->devnode); +} +EXPORT_SYMBOL_GPL(media_device_unregister); diff --git a/include/media/media-device.h b/include/media/media-device.h new file mode 100644 index 00000000000..30857f7fc22 --- /dev/null +++ b/include/media/media-device.h @@ -0,0 +1,69 @@ +/* + * Media device + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MEDIA_DEVICE_H +#define _MEDIA_DEVICE_H + +#include +#include + +#include + +/** + * struct media_device - Media device + * @dev: Parent device + * @devnode: Media device node + * @model: Device model name + * @serial: Device serial number (optional) + * @bus_info: Unique and stable device location identifier + * @hw_revision: Hardware device revision + * @driver_version: Device driver version + * + * This structure represents an abstract high-level media device. It allows easy + * access to entities and provides basic media device-level support. The + * structure can be allocated directly or embedded in a larger structure. + * + * The parent @dev is a physical device. It must be set before registering the + * media device. + * + * @model is a descriptive model name exported through sysfs. It doesn't have to + * be unique. + */ +struct media_device { + /* dev->driver_data points to this struct. */ + struct device *dev; + struct media_devnode devnode; + + char model[32]; + char serial[40]; + char bus_info[32]; + u32 hw_revision; + u32 driver_version; +}; + +/* media_devnode to media_device */ +#define to_media_device(node) container_of(node, struct media_device, devnode) + +int __must_check media_device_register(struct media_device *mdev); +void media_device_unregister(struct media_device *mdev); + +#endif -- cgit v1.2.3-70-g09d2 From 53e269c102fbaf77e7dc526b1606ad4a48e57200 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:40:00 -0300 Subject: [media] media: Entities, pads and links As video hardware pipelines become increasingly complex and configurable, the current hardware description through v4l2 subdevices reaches its limits. In addition to enumerating and configuring subdevices, video camera drivers need a way to discover and modify at runtime how those subdevices are connected. This is done through new elements called entities, pads and links. An entity is a basic media hardware building block. It can correspond to a large variety of logical blocks such as physical hardware devices (CMOS sensor for instance), logical hardware devices (a building block in a System-on-Chip image processing pipeline), DMA channels or physical connectors. A pad is a connection endpoint through which an entity can interact with other entities. Data (not restricted to video) produced by an entity flows from the entity's output to one or more entity inputs. Pads should not be confused with physical pins at chip boundaries. A link is a point-to-point oriented connection between two pads, either on the same entity or on different entities. Data flows from a source pad to a sink pad. Links are stored in the source entity. To make backwards graph walk faster, a copy of all links is also stored in the sink entity. The copy is known as a backlink and is only used to help graph traversal. The entity API is made of three functions: - media_entity_init() initializes an entity. The caller must provide an array of pads as well as an estimated number of links. The links array is allocated dynamically and will be reallocated if it grows beyond the initial estimate. - media_entity_cleanup() frees resources allocated for an entity. It must be called during the cleanup phase after unregistering the entity and before freeing it. - media_entity_create_link() creates a link between two entities. An entry in the link array of each entity is allocated and stores pointers to source and sink pads. When a media device is unregistered, all its entities are unregistered automatically. The code is based on Hans Verkuil initial work. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/media-controller.xml | 20 ++++ Documentation/media-framework.txt | 151 +++++++++++++++++++++++++ drivers/media/Makefile | 2 +- drivers/media/media-device.c | 56 +++++++++ drivers/media/media-entity.c | 147 ++++++++++++++++++++++++ include/media/media-device.h | 19 ++++ include/media/media-entity.h | 122 ++++++++++++++++++++ 7 files changed, 516 insertions(+), 1 deletion(-) create mode 100644 drivers/media/media-entity.c create mode 100644 include/media/media-entity.h (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml index 253ddb4426c..f89228d3ec2 100644 --- a/Documentation/DocBook/v4l/media-controller.xml +++ b/Documentation/DocBook/v4l/media-controller.xml @@ -53,4 +53,24 @@ implementing policies that belong to userspace. The media controller API aims at solving those problems.
+ +
+ Media device model + Discovering a device internal topology, and configuring it at runtime, + is one of the goals of the media controller API. To achieve this, hardware + devices are modelled as an oriented graph of building blocks called entities + connected through pads. + An entity is a basic media hardware or software building block. It can + correspond to a large variety of logical blocks such as physical hardware + devices (CMOS sensor for instance), logical hardware devices (a building + block in a System-on-Chip image processing pipeline), DMA channels or + physical connectors. + A pad is a connection endpoint through which an entity can interact + with other entities. Data (not restricted to video) produced by an entity + flows from the entity's output to one or more entity inputs. Pads should not + be confused with physical pins at chip boundaries. + A link is a point-to-point oriented connection between two pads, + either on the same entity or on different entities. Data flows from a source + pad to a sink pad. +
diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index 1844c3f1072..0257bad2a10 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -13,6 +13,30 @@ Documentation/DocBook/v4l/media-controller.xml. This document will focus on the kernel-side implementation of the media framework. +Abstract media device model +--------------------------- + +Discovering a device internal topology, and configuring it at runtime, is one +of the goals of the media framework. To achieve this, hardware devices are +modeled as an oriented graph of building blocks called entities connected +through pads. + +An entity is a basic media hardware building block. It can correspond to +a large variety of logical blocks such as physical hardware devices +(CMOS sensor for instance), logical hardware devices (a building block +in a System-on-Chip image processing pipeline), DMA channels or physical +connectors. + +A pad is a connection endpoint through which an entity can interact with +other entities. Data (not restricted to video) produced by an entity +flows from the entity's output to one or more entity inputs. Pads should +not be confused with physical pins at chip boundaries. + +A link is a point-to-point oriented connection between two pads, either +on the same entity or on different entities. Data flows from a source +pad to a sink pad. + + Media device ------------ @@ -65,3 +89,130 @@ Drivers unregister media device instances by calling media_device_unregister(struct media_device *mdev); Unregistering a media device that hasn't been registered is *NOT* safe. + + +Entities, pads and links +------------------------ + +- Entities + +Entities are represented by a struct media_entity instance, defined in +include/media/media-entity.h. The structure is usually embedded into a +higher-level structure, such as a v4l2_subdev or video_device instance, +although drivers can allocate entities directly. + +Drivers initialize entities by calling + + media_entity_init(struct media_entity *entity, u16 num_pads, + struct media_pad *pads, u16 extra_links); + +The media_entity name, type, flags, revision and group_id fields can be +initialized before or after calling media_entity_init. Entities embedded in +higher-level standard structures can have some of those fields set by the +higher-level framework. + +As the number of pads is known in advance, the pads array is not allocated +dynamically but is managed by the entity driver. Most drivers will embed the +pads array in a driver-specific structure, avoiding dynamic allocation. + +Drivers must set the direction of every pad in the pads array before calling +media_entity_init. The function will initialize the other pads fields. + +Unlike the number of pads, the total number of links isn't always known in +advance by the entity driver. As an initial estimate, media_entity_init +pre-allocates a number of links equal to the number of pads plus an optional +number of extra links. The links array will be reallocated if it grows beyond +the initial estimate. + +Drivers register entities with a media device by calling + + media_device_register_entity(struct media_device *mdev, + struct media_entity *entity); + +Entities are identified by a unique positive integer ID. Drivers can provide an +ID by filling the media_entity id field prior to registration, or request the +media controller framework to assign an ID automatically. Drivers that provide +IDs manually must ensure that all IDs are unique. IDs are not guaranteed to be +contiguous even when they are all assigned automatically by the framework. + +Drivers unregister entities by calling + + media_device_unregister_entity(struct media_entity *entity); + +Unregistering an entity will not change the IDs of the other entities, and the +ID will never be reused for a newly registered entity. + +When a media device is unregistered, all its entities are unregistered +automatically. No manual entities unregistration is then required. + +Drivers free resources associated with an entity by calling + + media_entity_cleanup(struct media_entity *entity); + +This function must be called during the cleanup phase after unregistering the +entity. Note that the media_entity instance itself must be freed explicitly by +the driver if required. + +Entities have flags that describe the entity capabilities and state. + + MEDIA_ENT_FL_DEFAULT indicates the default entity for a given type. + This can be used to report the default audio and video devices or the + default camera sensor. + +Logical entity groups can be defined by setting the group ID of all member +entities to the same non-zero value. An entity group serves no purpose in the +kernel, but is reported to userspace during entities enumeration. The group_id +field belongs to the media device driver and must not by touched by entity +drivers. + +Media device drivers should define groups if several entities are logically +bound together. Example usages include reporting + + - ALSA, VBI and video nodes that carry the same media stream + - lens and flash controllers associated with a sensor + +- Pads + +Pads are represented by a struct media_pad instance, defined in +include/media/media-entity.h. Each entity stores its pads in a pads array +managed by the entity driver. Drivers usually embed the array in a +driver-specific structure. + +Pads are identified by their entity and their 0-based index in the pads array. +Both information are stored in the media_pad structure, making the media_pad +pointer the canonical way to store and pass link references. + +Pads have flags that describe the pad capabilities and state. + + MEDIA_PAD_FL_SINK indicates that the pad supports sinking data. + MEDIA_PAD_FL_SOURCE indicates that the pad supports sourcing data. + +One and only one of MEDIA_PAD_FL_SINK and MEDIA_PAD_FL_SOURCE must be set for +each pad. + +- Links + +Links are represented by a struct media_link instance, defined in +include/media/media-entity.h. Each entity stores all links originating at or +targetting any of its pads in a links array. A given link is thus stored +twice, once in the source entity and once in the target entity. The array is +pre-allocated and grows dynamically as needed. + +Drivers create links by calling + + media_entity_create_link(struct media_entity *source, u16 source_pad, + struct media_entity *sink, u16 sink_pad, + u32 flags); + +An entry in the link array of each entity is allocated and stores pointers +to source and sink pads. + +Links have flags that describe the link capabilities and state. + + MEDIA_LNK_FL_ENABLED indicates that the link is enabled and can be used + to transfer media data. When two or more links target a sink pad, only + one of them can be enabled at a time. + MEDIA_LNK_FL_IMMUTABLE indicates that the link enabled state can't be + modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then + MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always + enabled. diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 36731aae57e..64755c99ded 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -2,7 +2,7 @@ # Makefile for the kernel multimedia device drivers. # -media-objs := media-device.o media-devnode.o +media-objs := media-device.o media-devnode.o media-entity.o ifeq ($(CONFIG_MEDIA_CONTROLLER),y) obj-$(CONFIG_MEDIA_SUPPORT) += media.o diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index bcd3985d415..a36509a1df0 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -25,6 +25,7 @@ #include #include +#include static const struct media_file_operations media_device_fops = { .owner = THIS_MODULE, @@ -69,6 +70,10 @@ int __must_check media_device_register(struct media_device *mdev) if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0)) return -EINVAL; + mdev->entity_id = 1; + INIT_LIST_HEAD(&mdev->entities); + spin_lock_init(&mdev->lock); + /* Register the device node. */ mdev->devnode.fops = &media_device_fops; mdev->devnode.parent = mdev->dev; @@ -94,7 +99,58 @@ EXPORT_SYMBOL_GPL(media_device_register); */ void media_device_unregister(struct media_device *mdev) { + struct media_entity *entity; + struct media_entity *next; + + list_for_each_entry_safe(entity, next, &mdev->entities, list) + media_device_unregister_entity(entity); + device_remove_file(&mdev->devnode.dev, &dev_attr_model); media_devnode_unregister(&mdev->devnode); } EXPORT_SYMBOL_GPL(media_device_unregister); + +/** + * media_device_register_entity - Register an entity with a media device + * @mdev: The media device + * @entity: The entity + */ +int __must_check media_device_register_entity(struct media_device *mdev, + struct media_entity *entity) +{ + /* Warn if we apparently re-register an entity */ + WARN_ON(entity->parent != NULL); + entity->parent = mdev; + + spin_lock(&mdev->lock); + if (entity->id == 0) + entity->id = mdev->entity_id++; + else + mdev->entity_id = max(entity->id + 1, mdev->entity_id); + list_add_tail(&entity->list, &mdev->entities); + spin_unlock(&mdev->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(media_device_register_entity); + +/** + * media_device_unregister_entity - Unregister an entity + * @entity: The entity + * + * If the entity has never been registered this function will return + * immediately. + */ +void media_device_unregister_entity(struct media_entity *entity) +{ + struct media_device *mdev = entity->parent; + + if (mdev == NULL) + return; + + spin_lock(&mdev->lock); + list_del(&entity->list); + spin_unlock(&mdev->lock); + entity->parent = NULL; +} +EXPORT_SYMBOL_GPL(media_device_unregister_entity); diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c new file mode 100644 index 00000000000..5c31df9ed76 --- /dev/null +++ b/drivers/media/media-entity.c @@ -0,0 +1,147 @@ +/* + * Media entity + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +/** + * media_entity_init - Initialize a media entity + * + * @num_pads: Total number of sink and source pads. + * @extra_links: Initial estimate of the number of extra links. + * @pads: Array of 'num_pads' pads. + * + * The total number of pads is an intrinsic property of entities known by the + * entity driver, while the total number of links depends on hardware design + * and is an extrinsic property unknown to the entity driver. However, in most + * use cases the entity driver can guess the number of links which can safely + * be assumed to be equal to or larger than the number of pads. + * + * For those reasons the links array can be preallocated based on the entity + * driver guess and will be reallocated later if extra links need to be + * created. + * + * This function allocates a links array with enough space to hold at least + * 'num_pads' + 'extra_links' elements. The media_entity::max_links field will + * be set to the number of allocated elements. + * + * The pads array is managed by the entity driver and passed to + * media_entity_init() where its pointer will be stored in the entity structure. + */ +int +media_entity_init(struct media_entity *entity, u16 num_pads, + struct media_pad *pads, u16 extra_links) +{ + struct media_link *links; + unsigned int max_links = num_pads + extra_links; + unsigned int i; + + links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL); + if (links == NULL) + return -ENOMEM; + + entity->group_id = 0; + entity->max_links = max_links; + entity->num_links = 0; + entity->num_backlinks = 0; + entity->num_pads = num_pads; + entity->pads = pads; + entity->links = links; + + for (i = 0; i < num_pads; i++) { + pads[i].entity = entity; + pads[i].index = i; + } + + return 0; +} +EXPORT_SYMBOL_GPL(media_entity_init); + +void +media_entity_cleanup(struct media_entity *entity) +{ + kfree(entity->links); +} +EXPORT_SYMBOL_GPL(media_entity_cleanup); + +static struct media_link *media_entity_add_link(struct media_entity *entity) +{ + if (entity->num_links >= entity->max_links) { + struct media_link *links = entity->links; + unsigned int max_links = entity->max_links + 2; + unsigned int i; + + links = krealloc(links, max_links * sizeof(*links), GFP_KERNEL); + if (links == NULL) + return NULL; + + for (i = 0; i < entity->num_links; i++) + links[i].reverse->reverse = &links[i]; + + entity->max_links = max_links; + entity->links = links; + } + + return &entity->links[entity->num_links++]; +} + +int +media_entity_create_link(struct media_entity *source, u16 source_pad, + struct media_entity *sink, u16 sink_pad, u32 flags) +{ + struct media_link *link; + struct media_link *backlink; + + BUG_ON(source == NULL || sink == NULL); + BUG_ON(source_pad >= source->num_pads); + BUG_ON(sink_pad >= sink->num_pads); + + link = media_entity_add_link(source); + if (link == NULL) + return -ENOMEM; + + link->source = &source->pads[source_pad]; + link->sink = &sink->pads[sink_pad]; + link->flags = flags; + + /* Create the backlink. Backlinks are used to help graph traversal and + * are not reported to userspace. + */ + backlink = media_entity_add_link(sink); + if (backlink == NULL) { + source->num_links--; + return -ENOMEM; + } + + backlink->source = &source->pads[source_pad]; + backlink->sink = &sink->pads[sink_pad]; + backlink->flags = flags; + + link->reverse = backlink; + backlink->reverse = link; + + sink->num_backlinks++; + + return 0; +} +EXPORT_SYMBOL_GPL(media_entity_create_link); diff --git a/include/media/media-device.h b/include/media/media-device.h index 30857f7fc22..a8390fe87e8 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -25,8 +25,10 @@ #include #include +#include #include +#include /** * struct media_device - Media device @@ -37,6 +39,9 @@ * @bus_info: Unique and stable device location identifier * @hw_revision: Hardware device revision * @driver_version: Device driver version + * @entity_id: ID of the next entity to be registered + * @entities: List of registered entities + * @lock: Entities list lock * * This structure represents an abstract high-level media device. It allows easy * access to entities and provides basic media device-level support. The @@ -58,6 +63,12 @@ struct media_device { char bus_info[32]; u32 hw_revision; u32 driver_version; + + u32 entity_id; + struct list_head entities; + + /* Protects the entities list */ + spinlock_t lock; }; /* media_devnode to media_device */ @@ -66,4 +77,12 @@ struct media_device { int __must_check media_device_register(struct media_device *mdev); void media_device_unregister(struct media_device *mdev); +int __must_check media_device_register_entity(struct media_device *mdev, + struct media_entity *entity); +void media_device_unregister_entity(struct media_entity *entity); + +/* Iterate over all entities. */ +#define media_device_for_each_entity(entity, mdev) \ + list_for_each_entry(entity, &(mdev)->entities, list) + #endif diff --git a/include/media/media-entity.h b/include/media/media-entity.h new file mode 100644 index 00000000000..f6c856c9ac1 --- /dev/null +++ b/include/media/media-entity.h @@ -0,0 +1,122 @@ +/* + * Media entity + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MEDIA_ENTITY_H +#define _MEDIA_ENTITY_H + +#include + +#define MEDIA_ENT_TYPE_SHIFT 16 +#define MEDIA_ENT_TYPE_MASK 0x00ff0000 +#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff + +#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENT_TYPE_SHIFT) +#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENT_T_DEVNODE + 1) +#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENT_T_DEVNODE + 2) +#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENT_T_DEVNODE + 3) +#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENT_T_DEVNODE + 4) + +#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENT_TYPE_SHIFT) +#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENT_T_V4L2_SUBDEV + 1) +#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENT_T_V4L2_SUBDEV + 2) +#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENT_T_V4L2_SUBDEV + 3) + +#define MEDIA_ENT_FL_DEFAULT (1 << 0) + +#define MEDIA_LNK_FL_ENABLED (1 << 0) +#define MEDIA_LNK_FL_IMMUTABLE (1 << 1) + +#define MEDIA_PAD_FL_SINK (1 << 0) +#define MEDIA_PAD_FL_SOURCE (1 << 1) + +struct media_link { + struct media_pad *source; /* Source pad */ + struct media_pad *sink; /* Sink pad */ + struct media_link *reverse; /* Link in the reverse direction */ + unsigned long flags; /* Link flags (MEDIA_LNK_FL_*) */ +}; + +struct media_pad { + struct media_entity *entity; /* Entity this pad belongs to */ + u16 index; /* Pad index in the entity pads array */ + unsigned long flags; /* Pad flags (MEDIA_PAD_FL_*) */ +}; + +struct media_entity { + struct list_head list; + struct media_device *parent; /* Media device this entity belongs to*/ + u32 id; /* Entity ID, unique in the parent media + * device context */ + const char *name; /* Entity name */ + u32 type; /* Entity type (MEDIA_ENT_T_*) */ + u32 revision; /* Entity revision, driver specific */ + unsigned long flags; /* Entity flags (MEDIA_ENT_FL_*) */ + u32 group_id; /* Entity group ID */ + + u16 num_pads; /* Number of sink and source pads */ + u16 num_links; /* Number of existing links, both + * enabled and disabled */ + u16 num_backlinks; /* Number of backlinks */ + u16 max_links; /* Maximum number of links */ + + struct media_pad *pads; /* Pads array (num_pads elements) */ + struct media_link *links; /* Links array (max_links elements)*/ + + union { + /* Node specifications */ + struct { + u32 major; + u32 minor; + } v4l; + struct { + u32 major; + u32 minor; + } fb; + struct { + u32 card; + u32 device; + u32 subdevice; + } alsa; + int dvb; + + /* Sub-device specifications */ + /* Nothing needed yet */ + }; +}; + +static inline u32 media_entity_type(struct media_entity *entity) +{ + return entity->type & MEDIA_ENT_TYPE_MASK; +} + +static inline u32 media_entity_subtype(struct media_entity *entity) +{ + return entity->type & MEDIA_ENT_SUBTYPE_MASK; +} + +int media_entity_init(struct media_entity *entity, u16 num_pads, + struct media_pad *pads, u16 extra_links); +void media_entity_cleanup(struct media_entity *entity); +int media_entity_create_link(struct media_entity *source, u16 source_pad, + struct media_entity *sink, u16 sink_pad, u32 flags); + +#endif -- cgit v1.2.3-70-g09d2 From a5ccc48a7c48610e7f92fa599406738d69195d51 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sun, 7 Mar 2010 16:14:14 -0300 Subject: [media] media: Entity graph traversal Add media entity graph traversal. The traversal follows enabled links by depth first. Traversing graph backwards is prevented by comparing the next possible entity in the graph with the previous one. Multiply connected graphs are thus not supported. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Vimarsh Zutshi Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media-framework.txt | 42 ++++++++++++++ drivers/media/media-entity.c | 115 ++++++++++++++++++++++++++++++++++++++ include/media/media-entity.h | 15 +++++ 3 files changed, 172 insertions(+) (limited to 'Documentation') diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index 0257bad2a10..ab17f33dded 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -216,3 +216,45 @@ Links have flags that describe the link capabilities and state. modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always enabled. + + +Graph traversal +--------------- + +The media framework provides APIs to iterate over entities in a graph. + +To iterate over all entities belonging to a media device, drivers can use the +media_device_for_each_entity macro, defined in include/media/media-device.h. + + struct media_entity *entity; + + media_device_for_each_entity(entity, mdev) { + /* entity will point to each entity in turn */ + ... + } + +Drivers might also need to iterate over all entities in a graph that can be +reached only through enabled links starting at a given entity. The media +framework provides a depth-first graph traversal API for that purpose. + +Note that graphs with cycles (whether directed or undirected) are *NOT* +supported by the graph traversal API. To prevent infinite loops, the graph +traversal code limits the maximum depth to MEDIA_ENTITY_ENUM_MAX_DEPTH, +currently defined as 16. + +Drivers initiate a graph traversal by calling + + media_entity_graph_walk_start(struct media_entity_graph *graph, + struct media_entity *entity); + +The graph structure, provided by the caller, is initialized to start graph +traversal at the given entity. + +Drivers can then retrieve the next entity by calling + + media_entity_graph_walk_next(struct media_entity_graph *graph); + +When the graph traversal is complete the function will return NULL. + +Graph traversal can be interrupted at any moment. No cleanup function call is +required and the graph structure can be freed normally. diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 5c31df9ed76..166f2b5505c 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -84,6 +84,121 @@ media_entity_cleanup(struct media_entity *entity) } EXPORT_SYMBOL_GPL(media_entity_cleanup); +/* ----------------------------------------------------------------------------- + * Graph traversal + */ + +static struct media_entity * +media_entity_other(struct media_entity *entity, struct media_link *link) +{ + if (link->source->entity == entity) + return link->sink->entity; + else + return link->source->entity; +} + +/* push an entity to traversal stack */ +static void stack_push(struct media_entity_graph *graph, + struct media_entity *entity) +{ + if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) { + WARN_ON(1); + return; + } + graph->top++; + graph->stack[graph->top].link = 0; + graph->stack[graph->top].entity = entity; +} + +static struct media_entity *stack_pop(struct media_entity_graph *graph) +{ + struct media_entity *entity; + + entity = graph->stack[graph->top].entity; + graph->top--; + + return entity; +} + +#define stack_peek(en) ((en)->stack[(en)->top - 1].entity) +#define link_top(en) ((en)->stack[(en)->top].link) +#define stack_top(en) ((en)->stack[(en)->top].entity) + +/** + * media_entity_graph_walk_start - Start walking the media graph at a given entity + * @graph: Media graph structure that will be used to walk the graph + * @entity: Starting entity + * + * This function initializes the graph traversal structure to walk the entities + * graph starting at the given entity. The traversal structure must not be + * modified by the caller during graph traversal. When done the structure can + * safely be freed. + */ +void media_entity_graph_walk_start(struct media_entity_graph *graph, + struct media_entity *entity) +{ + graph->top = 0; + graph->stack[graph->top].entity = NULL; + stack_push(graph, entity); +} +EXPORT_SYMBOL_GPL(media_entity_graph_walk_start); + +/** + * media_entity_graph_walk_next - Get the next entity in the graph + * @graph: Media graph structure + * + * Perform a depth-first traversal of the given media entities graph. + * + * The graph structure must have been previously initialized with a call to + * media_entity_graph_walk_start(). + * + * Return the next entity in the graph or NULL if the whole graph have been + * traversed. + */ +struct media_entity * +media_entity_graph_walk_next(struct media_entity_graph *graph) +{ + if (stack_top(graph) == NULL) + return NULL; + + /* + * Depth first search. Push entity to stack and continue from + * top of the stack until no more entities on the level can be + * found. + */ + while (link_top(graph) < stack_top(graph)->num_links) { + struct media_entity *entity = stack_top(graph); + struct media_link *link = &entity->links[link_top(graph)]; + struct media_entity *next; + + /* The link is not enabled so we do not follow. */ + if (!(link->flags & MEDIA_LNK_FL_ENABLED)) { + link_top(graph)++; + continue; + } + + /* Get the entity in the other end of the link . */ + next = media_entity_other(entity, link); + + /* Was it the entity we came here from? */ + if (next == stack_peek(graph)) { + link_top(graph)++; + continue; + } + + /* Push the new entity to stack and start over. */ + link_top(graph)++; + stack_push(graph, next); + } + + return stack_pop(graph); +} +EXPORT_SYMBOL_GPL(media_entity_graph_walk_next); + +/* ----------------------------------------------------------------------------- + * Links management + */ + static struct media_link *media_entity_add_link(struct media_entity *entity) { if (entity->num_links >= entity->max_links) { diff --git a/include/media/media-entity.h b/include/media/media-entity.h index f6c856c9ac1..28f61f6ee54 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -113,10 +113,25 @@ static inline u32 media_entity_subtype(struct media_entity *entity) return entity->type & MEDIA_ENT_SUBTYPE_MASK; } +#define MEDIA_ENTITY_ENUM_MAX_DEPTH 16 + +struct media_entity_graph { + struct { + struct media_entity *entity; + int link; + } stack[MEDIA_ENTITY_ENUM_MAX_DEPTH]; + int top; +}; + int media_entity_init(struct media_entity *entity, u16 num_pads, struct media_pad *pads, u16 extra_links); void media_entity_cleanup(struct media_entity *entity); int media_entity_create_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags); +void media_entity_graph_walk_start(struct media_entity_graph *graph, + struct media_entity *entity); +struct media_entity * +media_entity_graph_walk_next(struct media_entity_graph *graph); + #endif -- cgit v1.2.3-70-g09d2 From 503c3d829eaf48837dd5bff5d97ad66369bb955a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 7 Mar 2010 15:04:59 -0300 Subject: [media] media: Entity use count Due to the wide differences between drivers regarding power management needs, the media controller does not implement power management. However, the media_entity structure includes a use_count field that media drivers can use to track the number of users of every entity for power management needs. The use_count field is owned by media drivers and must not be touched by entity drivers. Access to the field must be protected by the media device graph_mutex lock. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media-framework.txt | 13 +++++++++++ drivers/media/media-device.c | 1 + drivers/media/media-entity.c | 46 +++++++++++++++++++++++++++++++++++++++ include/media/media-device.h | 4 ++++ include/media/media-entity.h | 9 ++++++++ 5 files changed, 73 insertions(+) (limited to 'Documentation') diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index ab17f33dded..78ae0209537 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -258,3 +258,16 @@ When the graph traversal is complete the function will return NULL. Graph traversal can be interrupted at any moment. No cleanup function call is required and the graph structure can be freed normally. + + +Use count and power handling +---------------------------- + +Due to the wide differences between drivers regarding power management needs, +the media controller does not implement power management. However, the +media_entity structure includes a use_count field that media drivers can use to +track the number of users of every entity for power management needs. + +The use_count field is owned by media drivers and must not be touched by entity +drivers. Access to the field must be protected by the media device graph_mutex +lock. diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index a36509a1df0..d2bc809d7a2 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -73,6 +73,7 @@ int __must_check media_device_register(struct media_device *mdev) mdev->entity_id = 1; INIT_LIST_HEAD(&mdev->entities); spin_lock_init(&mdev->lock); + mutex_init(&mdev->graph_mutex); /* Register the device node. */ mdev->devnode.fops = &media_device_fops; diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 166f2b5505c..3e7e2d569ce 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -23,6 +23,7 @@ #include #include #include +#include /** * media_entity_init - Initialize a media entity @@ -195,6 +196,51 @@ media_entity_graph_walk_next(struct media_entity_graph *graph) } EXPORT_SYMBOL_GPL(media_entity_graph_walk_next); +/* ----------------------------------------------------------------------------- + * Module use count + */ + +/* + * media_entity_get - Get a reference to the parent module + * @entity: The entity + * + * Get a reference to the parent media device module. + * + * The function will return immediately if @entity is NULL. + * + * Return a pointer to the entity on success or NULL on failure. + */ +struct media_entity *media_entity_get(struct media_entity *entity) +{ + if (entity == NULL) + return NULL; + + if (entity->parent->dev && + !try_module_get(entity->parent->dev->driver->owner)) + return NULL; + + return entity; +} +EXPORT_SYMBOL_GPL(media_entity_get); + +/* + * media_entity_put - Release the reference to the parent module + * @entity: The entity + * + * Release the reference count acquired by media_entity_get(). + * + * The function will return immediately if @entity is NULL. + */ +void media_entity_put(struct media_entity *entity) +{ + if (entity == NULL) + return; + + if (entity->parent->dev) + module_put(entity->parent->dev->driver->owner); +} +EXPORT_SYMBOL_GPL(media_entity_put); + /* ----------------------------------------------------------------------------- * Links management */ diff --git a/include/media/media-device.h b/include/media/media-device.h index a8390fe87e8..5d2bff4fc9e 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -42,6 +43,7 @@ * @entity_id: ID of the next entity to be registered * @entities: List of registered entities * @lock: Entities list lock + * @graph_mutex: Entities graph operation lock * * This structure represents an abstract high-level media device. It allows easy * access to entities and provides basic media device-level support. The @@ -69,6 +71,8 @@ struct media_device { /* Protects the entities list */ spinlock_t lock; + /* Serializes graph operations. */ + struct mutex graph_mutex; }; /* media_devnode to media_device */ diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 28f61f6ee54..a9b31d98e3c 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -81,6 +81,12 @@ struct media_entity { struct media_pad *pads; /* Pads array (num_pads elements) */ struct media_link *links; /* Links array (max_links elements)*/ + /* Reference counts must never be negative, but are signed integers on + * purpose: a simple WARN_ON(<0) check can be used to detect reference + * count bugs that would make them negative. + */ + int use_count; /* Use count for the entity. */ + union { /* Node specifications */ struct { @@ -129,6 +135,9 @@ void media_entity_cleanup(struct media_entity *entity); int media_entity_create_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags); +struct media_entity *media_entity_get(struct media_entity *entity); +void media_entity_put(struct media_entity *entity); + void media_entity_graph_walk_start(struct media_entity_graph *graph, struct media_entity *entity); struct media_entity * -- cgit v1.2.3-70-g09d2 From 140d88165c25137e871f9559e67986ed89251105 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 18 Aug 2010 11:41:22 -0300 Subject: [media] media: Media device information query Create the following ioctl and implement it at the media device level to query device information. - MEDIA_IOC_DEVICE_INFO: Query media device information The ioctl and its data structure are defined in the new kernel header linux/media.h available to userspace applications. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 12 ++ Documentation/DocBook/v4l/media-controller.xml | 10 ++ Documentation/DocBook/v4l/media-func-close.xml | 59 +++++++++ Documentation/DocBook/v4l/media-func-ioctl.xml | 116 ++++++++++++++++++ Documentation/DocBook/v4l/media-func-open.xml | 94 +++++++++++++++ .../DocBook/v4l/media-ioc-device-info.xml | 132 +++++++++++++++++++++ drivers/media/media-device.c | 57 +++++++++ include/linux/Kbuild | 1 + include/linux/media.h | 45 +++++++ 9 files changed, 526 insertions(+) create mode 100644 Documentation/DocBook/v4l/media-func-close.xml create mode 100644 Documentation/DocBook/v4l/media-func-ioctl.xml create mode 100644 Documentation/DocBook/v4l/media-func-open.xml create mode 100644 Documentation/DocBook/v4l/media-ioc-device-info.xml create mode 100644 include/linux/media.h (limited to 'Documentation') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index c47897f046b..034f891399e 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -11,6 +11,10 @@ select()"> write()"> +close()"> +ioctl()"> +open()"> + VIDIOC_CROPCAP"> VIDIOC_DBG_G_CHIP_IDENT"> @@ -87,6 +91,8 @@ VIDIOC_TRY_FMT"> VIDIOC_UNSUBSCRIBE_EVENT"> +MEDIA_IOC_DEVICE_INFO"> + v4l2_std_id"> @@ -184,6 +190,8 @@ v4l2_vbi_format"> v4l2_window"> +media_device_info"> + EACCES error code"> EAGAIN error code"> @@ -328,6 +336,10 @@ + + + + diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml index f89228d3ec2..a46b786e9f2 100644 --- a/Documentation/DocBook/v4l/media-controller.xml +++ b/Documentation/DocBook/v4l/media-controller.xml @@ -74,3 +74,13 @@ pad to a sink pad.
+ + + Function Reference + + &sub-media-open; + &sub-media-close; + &sub-media-ioctl; + + &sub-media-ioc-device-info; + diff --git a/Documentation/DocBook/v4l/media-func-close.xml b/Documentation/DocBook/v4l/media-func-close.xml new file mode 100644 index 00000000000..be149c802ae --- /dev/null +++ b/Documentation/DocBook/v4l/media-func-close.xml @@ -0,0 +1,59 @@ + + + media close() + &manvol; + + + + media-close + Close a media device + + + + + #include <unistd.h> + + int close + int fd + + + + + + Arguments + + + + fd + + &fd; + + + + + + + Description + + Closes the media device. Resources associated with the file descriptor + are freed. The device configuration remain unchanged. + + + + Return Value + + close returns 0 on success. On error, -1 is + returned, and errno is set appropriately. Possible error + codes are: + + + + EBADF + + fd is not a valid open file descriptor. + + + + + + diff --git a/Documentation/DocBook/v4l/media-func-ioctl.xml b/Documentation/DocBook/v4l/media-func-ioctl.xml new file mode 100644 index 00000000000..bda8604de15 --- /dev/null +++ b/Documentation/DocBook/v4l/media-func-ioctl.xml @@ -0,0 +1,116 @@ + + + media ioctl() + &manvol; + + + + media-ioctl + Control a media device + + + + + #include <sys/ioctl.h> + + int ioctl + int fd + int request + void *argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + Media ioctl request code as defined in the media.h header file, + for example MEDIA_IOC_SETUP_LINK. + + + + argp + + Pointer to a request-specific structure. + + + + + + + Description + The ioctl() function manipulates media device + parameters. The argument fd must be an open file + descriptor. + The ioctl request code specifies the media + function to be called. It has encoded in it whether the argument is an + input, output or read/write parameter, and the size of the argument + argp in bytes. + Macros and structures definitions specifying media ioctl requests and + their parameters are located in the media.h header file. All media ioctl + requests, their respective function and parameters are specified in + . + + + + Return Value + + ioctl() returns 0 on + success. On failure, -1 is returned, and the + errno variable is set appropriately. Generic error codes + are listed below, and request-specific error codes are listed in the + individual requests descriptions. + When an ioctl that takes an output or read/write parameter fails, + the parameter remains unmodified. + + + + EBADF + + fd is not a valid open file descriptor. + + + + + EFAULT + + argp references an inaccessible memory + area. + + + + EINVAL + + The request or the data pointed to by + argp is not valid. This is a very common error + code, see the individual ioctl requests listed in + for actual causes. + + + + ENOMEM + + Insufficient kernel memory was available to complete the + request. + + + + ENOTTY + + fd is not associated with a character + special device. + + + + + diff --git a/Documentation/DocBook/v4l/media-func-open.xml b/Documentation/DocBook/v4l/media-func-open.xml new file mode 100644 index 00000000000..f7df034dc9e --- /dev/null +++ b/Documentation/DocBook/v4l/media-func-open.xml @@ -0,0 +1,94 @@ + + + media open() + &manvol; + + + + media-open + Open a media device + + + + + #include <fcntl.h> + + int open + const char *device_name + int flags + + + + + + Arguments + + + + device_name + + Device to be opened. + + + + flags + + Open flags. Access mode must be either O_RDONLY + or O_RDWR. Other flags have no effect. + + + + + + Description + To open a media device applications call open() + with the desired device name. The function has no side effects; the device + configuration remain unchanged. + When the device is opened in read-only mode, attemps to modify its + configuration will result in an error, and errno will be + set to EBADF. + + + Return Value + + open returns the new file descriptor on success. + On error, -1 is returned, and errno is set appropriately. + Possible error codes are: + + + + EACCES + + The requested access to the file is not allowed. + + + + EMFILE + + The process already has the maximum number of files open. + + + + + ENFILE + + The system limit on the total number of open files has been + reached. + + + + ENOMEM + + Insufficient kernel memory was available. + + + + ENXIO + + No device corresponding to this device special file exists. + + + + + + diff --git a/Documentation/DocBook/v4l/media-ioc-device-info.xml b/Documentation/DocBook/v4l/media-ioc-device-info.xml new file mode 100644 index 00000000000..278a3120ee2 --- /dev/null +++ b/Documentation/DocBook/v4l/media-ioc-device-info.xml @@ -0,0 +1,132 @@ + + + ioctl MEDIA_IOC_DEVICE_INFO + &manvol; + + + + MEDIA_IOC_DEVICE_INFO + Query device information + + + + + + int ioctl + int fd + int request + struct media_device_info *argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + MEDIA_IOC_DEVICE_INFO + + + + argp + + + + + + + + + Description + + All media devices must support the MEDIA_IOC_DEVICE_INFO + ioctl. To query device information, applications call the ioctl with a + pointer to a &media-device-info;. The driver fills the structure and returns + the information to the application. + The ioctl never fails. + + + struct <structname>media_device_info</structname> + + &cs-str; + + + char + driver[16] + Name of the driver implementing the media API as a + NUL-terminated ASCII string. The driver version is stored in the + driver_version field. + Driver specific applications can use this information to + verify the driver identity. It is also useful to work around + known bugs, or to identify drivers in error reports. + + + char + model[32] + Device model name as a NUL-terminated UTF-8 string. The + device version is stored in the device_version + field and is not be appended to the model name. + + + char + serial[40] + Serial number as a NUL-terminated ASCII string. + + + char + bus_info[32] + Location of the device in the system as a NUL-terminated + ASCII string. This includes the bus type name (PCI, USB, ...) and a + bus-specific identifier. + + + __u32 + media_version + Media API version, formatted with the + KERNEL_VERSION() macro. + + + __u32 + hw_revision + Hardware device revision in a driver-specific format. + + + __u32 + media_version + Media device driver version, formatted with the + KERNEL_VERSION() macro. Together with the + driver field this identifies a particular + driver. + + + __u32 + reserved[31] + Reserved for future extensions. Drivers and applications must + set this array to zero. + + + +
+ The serial and bus_info + fields can be used to distinguish between multiple instances of otherwise + identical hardware. The serial number takes precedence when provided and can + be assumed to be unique. If the serial number is an empty string, the + bus_info field can be used instead. The + bus_info field is guaranteed to be unique, but + can vary across reboots or device unplug/replug. +
+ + + Return value + This function doesn't return specific error codes. + +
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index d2bc809d7a2..92e0d4eb84b 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -22,13 +22,70 @@ #include #include +#include #include #include #include +/* ----------------------------------------------------------------------------- + * Userspace API + */ + +static int media_device_open(struct file *filp) +{ + return 0; +} + +static int media_device_close(struct file *filp) +{ + return 0; +} + +static int media_device_get_info(struct media_device *dev, + struct media_device_info __user *__info) +{ + struct media_device_info info; + + memset(&info, 0, sizeof(info)); + + strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver)); + strlcpy(info.model, dev->model, sizeof(info.model)); + strlcpy(info.serial, dev->serial, sizeof(info.serial)); + strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info)); + + info.media_version = MEDIA_API_VERSION; + info.hw_revision = dev->hw_revision; + info.driver_version = dev->driver_version; + + return copy_to_user(__info, &info, sizeof(*__info)); +} + +static long media_device_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct media_devnode *devnode = media_devnode_data(filp); + struct media_device *dev = to_media_device(devnode); + long ret; + + switch (cmd) { + case MEDIA_IOC_DEVICE_INFO: + ret = media_device_get_info(dev, + (struct media_device_info __user *)arg); + break; + + default: + ret = -ENOIOCTLCMD; + } + + return ret; +} + static const struct media_file_operations media_device_fops = { .owner = THIS_MODULE, + .open = media_device_open, + .ioctl = media_device_ioctl, + .release = media_device_close, }; /* ----------------------------------------------------------------------------- diff --git a/include/linux/Kbuild b/include/linux/Kbuild index b0ada6f37dd..31eb174a226 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -233,6 +233,7 @@ header-y += magic.h header-y += major.h header-y += map_to_7segment.h header-y += matroxfb.h +header-y += media.h header-y += mempolicy.h header-y += meye.h header-y += mii.h diff --git a/include/linux/media.h b/include/linux/media.h new file mode 100644 index 00000000000..64090db3c1f --- /dev/null +++ b/include/linux/media.h @@ -0,0 +1,45 @@ +/* + * Multimedia device API + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_MEDIA_H +#define __LINUX_MEDIA_H + +#include +#include +#include + +#define MEDIA_API_VERSION KERNEL_VERSION(0, 1, 0) + +struct media_device_info { + char driver[16]; + char model[32]; + char serial[40]; + char bus_info[32]; + __u32 media_version; + __u32 hw_revision; + __u32 driver_version; + __u32 reserved[31]; +}; + +#define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info) + +#endif /* __LINUX_MEDIA_H */ -- cgit v1.2.3-70-g09d2 From 1651333b09743887bc2dd3d158a11853a2be3fe7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:40:01 -0300 Subject: [media] media: Entities, pads and links enumeration Create the following two ioctls and implement them at the media device level to enumerate entities, pads and links. - MEDIA_IOC_ENUM_ENTITIES: Enumerate entities and their properties - MEDIA_IOC_ENUM_LINKS: Enumerate all pads and links for a given entity Entity IDs can be non-contiguous. Userspace applications should enumerate entities using the MEDIA_ENT_ID_FLAG_NEXT flag. When the flag is set in the entity ID, the MEDIA_IOC_ENUM_ENTITIES will return the next entity with an ID bigger than the requested one. Only forward links that originate at one of the entity's source pads are returned during the enumeration process. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 8 + Documentation/DocBook/v4l/media-controller.xml | 2 + .../DocBook/v4l/media-ioc-device-info.xml | 3 +- .../DocBook/v4l/media-ioc-enum-entities.xml | 308 +++++++++++++++++++++ Documentation/DocBook/v4l/media-ioc-enum-links.xml | 202 ++++++++++++++ drivers/media/media-device.c | 123 ++++++++ include/linux/media.h | 85 ++++++ include/media/media-entity.h | 24 +- 8 files changed, 731 insertions(+), 24 deletions(-) create mode 100644 Documentation/DocBook/v4l/media-ioc-enum-entities.xml create mode 100644 Documentation/DocBook/v4l/media-ioc-enum-links.xml (limited to 'Documentation') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index 034f891399e..2bd7b27f855 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -92,6 +92,8 @@ VIDIOC_UNSUBSCRIBE_EVENT"> MEDIA_IOC_DEVICE_INFO"> +MEDIA_IOC_ENUM_ENTITIES"> +MEDIA_IOC_ENUM_LINKS"> v4l2_std_id"> @@ -191,6 +193,10 @@ v4l2_window"> media_device_info"> +media_entity_desc"> +media_links_enum"> +media_pad_desc"> +media_link_desc"> EACCES error code"> @@ -340,6 +346,8 @@ + + diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml index a46b786e9f2..2c4fd2b2768 100644 --- a/Documentation/DocBook/v4l/media-controller.xml +++ b/Documentation/DocBook/v4l/media-controller.xml @@ -83,4 +83,6 @@ &sub-media-ioctl; &sub-media-ioc-device-info; + &sub-media-ioc-enum-entities; + &sub-media-ioc-enum-links; diff --git a/Documentation/DocBook/v4l/media-ioc-device-info.xml b/Documentation/DocBook/v4l/media-ioc-device-info.xml index 278a3120ee2..1f3237351bb 100644 --- a/Documentation/DocBook/v4l/media-ioc-device-info.xml +++ b/Documentation/DocBook/v4l/media-ioc-device-info.xml @@ -27,7 +27,8 @@ fd - &fd; + File descriptor returned by + open(). diff --git a/Documentation/DocBook/v4l/media-ioc-enum-entities.xml b/Documentation/DocBook/v4l/media-ioc-enum-entities.xml new file mode 100644 index 00000000000..13d0cc44865 --- /dev/null +++ b/Documentation/DocBook/v4l/media-ioc-enum-entities.xml @@ -0,0 +1,308 @@ + + + ioctl MEDIA_IOC_ENUM_ENTITIES + &manvol; + + + + MEDIA_IOC_ENUM_ENTITIES + Enumerate entities and their properties + + + + + + int ioctl + int fd + int request + struct media_entity_desc *argp + + + + + + Arguments + + + + fd + + File descriptor returned by + open(). + + + + request + + MEDIA_IOC_ENUM_ENTITIES + + + + argp + + + + + + + + + Description + To query the attributes of an entity, applications set the id field + of a &media-entity-desc; structure and call the MEDIA_IOC_ENUM_ENTITIES + ioctl with a pointer to this structure. The driver fills the rest of the + structure or returns an &EINVAL; when the id is invalid. + Entities can be enumerated by or'ing the id with the + MEDIA_ENT_ID_FLAG_NEXT flag. The driver will return + information about the entity with the smallest id strictly larger than the + requested one ('next entity'), or the &EINVAL; if there is none. + Entity IDs can be non-contiguous. Applications must + not try to enumerate entities by calling + MEDIA_IOC_ENUM_ENTITIES with increasing id's until they get an error. + Two or more entities that share a common non-zero + group_id value are considered as logically + grouped. Groups are used to report + + ALSA, VBI and video nodes that carry the same media + stream + lens and flash controllers associated with a sensor + + + + + struct <structname>media_entity_desc</structname> + + + + + + + + + __u32 + id + + + Entity id, set by the application. When the id is or'ed with + MEDIA_ENT_ID_FLAG_NEXT, the driver clears the + flag and returns the first entity with a larger id. + + + char + name[32] + + + Entity name as an UTF-8 NULL-terminated string. + + + __u32 + type + + + Entity type, see for details. + + + __u32 + revision + + + Entity revision in a driver/hardware specific format. + + + __u32 + flags + + + Entity flags, see for details. + + + __u32 + group_id + + + Entity group ID + + + __u16 + pads + + + Number of pads + + + __u16 + links + + + Total number of outbound links. Inbound links are not counted + in this field. + + + union + + + + struct + v4l + + Valid for V4L sub-devices and nodes only. + + + + + __u32 + major + V4L device node major number. For V4L sub-devices with no + device node, set by the driver to 0. + + + + + __u32 + minor + V4L device node minor number. For V4L sub-devices with no + device node, set by the driver to 0. + + + + struct + fb + + Valid for frame buffer nodes only. + + + + + __u32 + major + Frame buffer device node major number. + + + + + __u32 + minor + Frame buffer device node minor number. + + + + struct + alsa + + Valid for ALSA devices only. + + + + + __u32 + card + ALSA card number + + + + + __u32 + device + ALSA device number + + + + + __u32 + subdevice + ALSA sub-device number + + + + int + dvb + + DVB card number + + + + __u8 + raw[180] + + + + + +
+ + + Media entity types + + + + + + MEDIA_ENT_T_DEVNODE + Unknown device node + + + MEDIA_ENT_T_DEVNODE_V4L + V4L video, radio or vbi device node + + + MEDIA_ENT_T_DEVNODE_FB + Frame buffer device node + + + MEDIA_ENT_T_DEVNODE_ALSA + ALSA card + + + MEDIA_ENT_T_DEVNODE_DVB + DVB card + + + MEDIA_ENT_T_V4L2_SUBDEV + Unknown V4L sub-device + + + MEDIA_ENT_T_V4L2_SUBDEV_SENSOR + Video sensor + + + MEDIA_ENT_T_V4L2_SUBDEV_FLASH + Flash controller + + + MEDIA_ENT_T_V4L2_SUBDEV_LENS + Lens controller + + + +
+ + + Media entity flags + + + + + + MEDIA_ENT_FL_DEFAULT + Default entity for its type. Used to discover the default + audio, VBI and video devices, the default camera sensor, ... + + + +
+
+ + + &return-value; + + + + EINVAL + + The &media-entity-desc; id references + a non-existing entity. + + + + +
diff --git a/Documentation/DocBook/v4l/media-ioc-enum-links.xml b/Documentation/DocBook/v4l/media-ioc-enum-links.xml new file mode 100644 index 00000000000..6da884159ca --- /dev/null +++ b/Documentation/DocBook/v4l/media-ioc-enum-links.xml @@ -0,0 +1,202 @@ + + + ioctl MEDIA_IOC_ENUM_LINKS + &manvol; + + + + MEDIA_IOC_ENUM_LINKS + Enumerate all pads and links for a given entity + + + + + + int ioctl + int fd + int request + struct media_links_enum *argp + + + + + + Arguments + + + + fd + + File descriptor returned by + open(). + + + + request + + MEDIA_IOC_ENUM_LINKS + + + + argp + + + + + + + + + Description + + To enumerate pads and/or links for a given entity, applications set + the entity field of a &media-links-enum; structure and initialize the + &media-pad-desc; and &media-link-desc; structure arrays pointed by the + pads and links fields. + They then call the MEDIA_IOC_ENUM_LINKS ioctl with a pointer to this + structure. + If the pads field is not NULL, the driver + fills the pads array with information about the + entity's pads. The array must have enough room to store all the entity's + pads. The number of pads can be retrieved with the &MEDIA-IOC-ENUM-ENTITIES; + ioctl. + If the links field is not NULL, the driver + fills the links array with information about the + entity's outbound links. The array must have enough room to store all the + entity's outbound links. The number of outbound links can be retrieved with + the &MEDIA-IOC-ENUM-ENTITIES; ioctl. + Only forward links that originate at one of the entity's source pads + are returned during the enumeration process. + + + struct <structname>media_links_enum</structname> + + &cs-str; + + + __u32 + entity + Entity id, set by the application. + + + struct &media-pad-desc; + *pads + Pointer to a pads array allocated by the application. Ignored + if NULL. + + + struct &media-link-desc; + *links + Pointer to a links array allocated by the application. Ignored + if NULL. + + + + + + + struct <structname>media_pad_desc</structname> + + &cs-str; + + + __u32 + entity + ID of the entity this pad belongs to. + + + __u16 + index + 0-based pad index. + + + __u32 + flags + Pad flags, see for more details. + + + +
+ + + Media pad flags + + + + + + MEDIA_PAD_FL_SINK + Input pad, relative to the entity. Input pads sink data and + are targets of links. + + + MEDIA_PAD_FL_SOURCE + Output pad, relative to the entity. Output pads source data + and are origins of links. + + + +
+ + + struct <structname>media_links_desc</structname> + + &cs-str; + + + struct &media-pad-desc; + source + Pad at the origin of this link. + + + struct &media-pad-desc; + sink + Pad at the target of this link. + + + __u32 + flags + Link flags, see for more details. + + + + + + + Media link flags + + + + + + MEDIA_LNK_FL_ENABLED + The link is enabled and can be used to transfer media data. + When two or more links target a sink pad, only one of them can be + enabled at a time. + + + MEDIA_LNK_FL_IMMUTABLE + The link enabled state can't be modified at runtime. An + immutable link is always enabled. + + + + + One and only one of MEDIA_PAD_FL_SINK and + MEDIA_PAD_FL_SOURCE must be set for every pad. +
+ + + &return-value; + + + + EINVAL + + The &media-links-enum; id references + a non-existing entity. + + + + +
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 92e0d4eb84b..648a9d892ac 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -61,6 +61,117 @@ static int media_device_get_info(struct media_device *dev, return copy_to_user(__info, &info, sizeof(*__info)); } +static struct media_entity *find_entity(struct media_device *mdev, u32 id) +{ + struct media_entity *entity; + int next = id & MEDIA_ENT_ID_FLAG_NEXT; + + id &= ~MEDIA_ENT_ID_FLAG_NEXT; + + spin_lock(&mdev->lock); + + media_device_for_each_entity(entity, mdev) { + if ((entity->id == id && !next) || + (entity->id > id && next)) { + spin_unlock(&mdev->lock); + return entity; + } + } + + spin_unlock(&mdev->lock); + + return NULL; +} + +static long media_device_enum_entities(struct media_device *mdev, + struct media_entity_desc __user *uent) +{ + struct media_entity *ent; + struct media_entity_desc u_ent; + + if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id))) + return -EFAULT; + + ent = find_entity(mdev, u_ent.id); + + if (ent == NULL) + return -EINVAL; + + u_ent.id = ent->id; + u_ent.name[0] = '\0'; + if (ent->name) + strlcpy(u_ent.name, ent->name, sizeof(u_ent.name)); + u_ent.type = ent->type; + u_ent.revision = ent->revision; + u_ent.flags = ent->flags; + u_ent.group_id = ent->group_id; + u_ent.pads = ent->num_pads; + u_ent.links = ent->num_links - ent->num_backlinks; + u_ent.v4l.major = ent->v4l.major; + u_ent.v4l.minor = ent->v4l.minor; + if (copy_to_user(uent, &u_ent, sizeof(u_ent))) + return -EFAULT; + return 0; +} + +static void media_device_kpad_to_upad(const struct media_pad *kpad, + struct media_pad_desc *upad) +{ + upad->entity = kpad->entity->id; + upad->index = kpad->index; + upad->flags = kpad->flags; +} + +static long media_device_enum_links(struct media_device *mdev, + struct media_links_enum __user *ulinks) +{ + struct media_entity *entity; + struct media_links_enum links; + + if (copy_from_user(&links, ulinks, sizeof(links))) + return -EFAULT; + + entity = find_entity(mdev, links.entity); + if (entity == NULL) + return -EINVAL; + + if (links.pads) { + unsigned int p; + + for (p = 0; p < entity->num_pads; p++) { + struct media_pad_desc pad; + media_device_kpad_to_upad(&entity->pads[p], &pad); + if (copy_to_user(&links.pads[p], &pad, sizeof(pad))) + return -EFAULT; + } + } + + if (links.links) { + struct media_link_desc __user *ulink; + unsigned int l; + + for (l = 0, ulink = links.links; l < entity->num_links; l++) { + struct media_link_desc link; + + /* Ignore backlinks. */ + if (entity->links[l].source->entity != entity) + continue; + + media_device_kpad_to_upad(entity->links[l].source, + &link.source); + media_device_kpad_to_upad(entity->links[l].sink, + &link.sink); + link.flags = entity->links[l].flags; + if (copy_to_user(ulink, &link, sizeof(*ulink))) + return -EFAULT; + ulink++; + } + } + if (copy_to_user(ulinks, &links, sizeof(*ulinks))) + return -EFAULT; + return 0; +} + static long media_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { @@ -74,6 +185,18 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd, (struct media_device_info __user *)arg); break; + case MEDIA_IOC_ENUM_ENTITIES: + ret = media_device_enum_entities(dev, + (struct media_entity_desc __user *)arg); + break; + + case MEDIA_IOC_ENUM_LINKS: + mutex_lock(&dev->graph_mutex); + ret = media_device_enum_links(dev, + (struct media_links_enum __user *)arg); + mutex_unlock(&dev->graph_mutex); + break; + default: ret = -ENOIOCTLCMD; } diff --git a/include/linux/media.h b/include/linux/media.h index 64090db3c1f..17c93a41367 100644 --- a/include/linux/media.h +++ b/include/linux/media.h @@ -40,6 +40,91 @@ struct media_device_info { __u32 reserved[31]; }; +#define MEDIA_ENT_ID_FLAG_NEXT (1 << 31) + +#define MEDIA_ENT_TYPE_SHIFT 16 +#define MEDIA_ENT_TYPE_MASK 0x00ff0000 +#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff + +#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENT_TYPE_SHIFT) +#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENT_T_DEVNODE + 1) +#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENT_T_DEVNODE + 2) +#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENT_T_DEVNODE + 3) +#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENT_T_DEVNODE + 4) + +#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENT_TYPE_SHIFT) +#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENT_T_V4L2_SUBDEV + 1) +#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENT_T_V4L2_SUBDEV + 2) +#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENT_T_V4L2_SUBDEV + 3) + +#define MEDIA_ENT_FL_DEFAULT (1 << 0) + +struct media_entity_desc { + __u32 id; + char name[32]; + __u32 type; + __u32 revision; + __u32 flags; + __u32 group_id; + __u16 pads; + __u16 links; + + __u32 reserved[4]; + + union { + /* Node specifications */ + struct { + __u32 major; + __u32 minor; + } v4l; + struct { + __u32 major; + __u32 minor; + } fb; + struct { + __u32 card; + __u32 device; + __u32 subdevice; + } alsa; + int dvb; + + /* Sub-device specifications */ + /* Nothing needed yet */ + __u8 raw[184]; + }; +}; + +#define MEDIA_PAD_FL_SINK (1 << 0) +#define MEDIA_PAD_FL_SOURCE (1 << 1) + +struct media_pad_desc { + __u32 entity; /* entity ID */ + __u16 index; /* pad index */ + __u32 flags; /* pad flags */ + __u32 reserved[2]; +}; + +#define MEDIA_LNK_FL_ENABLED (1 << 0) +#define MEDIA_LNK_FL_IMMUTABLE (1 << 1) + +struct media_link_desc { + struct media_pad_desc source; + struct media_pad_desc sink; + __u32 flags; + __u32 reserved[2]; +}; + +struct media_links_enum { + __u32 entity; + /* Should have enough room for pads elements */ + struct media_pad_desc __user *pads; + /* Should have enough room for links elements */ + struct media_link_desc __user *links; + __u32 reserved[4]; +}; + #define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info) +#define MEDIA_IOC_ENUM_ENTITIES _IOWR('M', 2, struct media_entity_desc) +#define MEDIA_IOC_ENUM_LINKS _IOWR('M', 3, struct media_links_enum) #endif /* __LINUX_MEDIA_H */ diff --git a/include/media/media-entity.h b/include/media/media-entity.h index a9b31d98e3c..51bdafce72c 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -24,29 +24,7 @@ #define _MEDIA_ENTITY_H #include - -#define MEDIA_ENT_TYPE_SHIFT 16 -#define MEDIA_ENT_TYPE_MASK 0x00ff0000 -#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff - -#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENT_TYPE_SHIFT) -#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENT_T_DEVNODE + 1) -#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENT_T_DEVNODE + 2) -#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENT_T_DEVNODE + 3) -#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENT_T_DEVNODE + 4) - -#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENT_TYPE_SHIFT) -#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENT_T_V4L2_SUBDEV + 1) -#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENT_T_V4L2_SUBDEV + 2) -#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENT_T_V4L2_SUBDEV + 3) - -#define MEDIA_ENT_FL_DEFAULT (1 << 0) - -#define MEDIA_LNK_FL_ENABLED (1 << 0) -#define MEDIA_LNK_FL_IMMUTABLE (1 << 1) - -#define MEDIA_PAD_FL_SINK (1 << 0) -#define MEDIA_PAD_FL_SOURCE (1 << 1) +#include struct media_link { struct media_pad *source; /* Source pad */ -- cgit v1.2.3-70-g09d2 From 97548ed4c4661502cdfd1aabd5d3876fa4f5cc2e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:40:03 -0300 Subject: [media] media: Links setup Create the following ioctl and implement it at the media device level to setup links. - MEDIA_IOC_SETUP_LINK: Modify the properties of a given link The only property that can currently be modified is the ENABLED link flag to enable/disable a link. Links marked with the IMMUTABLE link flag can not be enabled or disabled. Enabling or disabling a link has effects on entities' use count. Those changes are automatically propagated through the graph. Signed-off-by: Laurent Pinchart Signed-off-by: Stanimir Varbanov Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 2 + Documentation/DocBook/v4l/media-controller.xml | 1 + Documentation/DocBook/v4l/media-ioc-setup-link.xml | 90 ++++++++++++ Documentation/media-framework.txt | 42 ++++++ drivers/media/media-device.c | 45 ++++++ drivers/media/media-entity.c | 155 +++++++++++++++++++++ include/linux/media.h | 1 + include/media/media-device.h | 3 + include/media/media-entity.h | 17 +++ 9 files changed, 356 insertions(+) create mode 100644 Documentation/DocBook/v4l/media-ioc-setup-link.xml (limited to 'Documentation') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index 2bd7b27f855..121db154924 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -94,6 +94,7 @@ MEDIA_IOC_DEVICE_INFO"> MEDIA_IOC_ENUM_ENTITIES"> MEDIA_IOC_ENUM_LINKS"> +MEDIA_IOC_SETUP_LINK"> v4l2_std_id"> @@ -348,6 +349,7 @@ + diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml index 2c4fd2b2768..2dc25e1d408 100644 --- a/Documentation/DocBook/v4l/media-controller.xml +++ b/Documentation/DocBook/v4l/media-controller.xml @@ -85,4 +85,5 @@ &sub-media-ioc-device-info; &sub-media-ioc-enum-entities; &sub-media-ioc-enum-links; + &sub-media-ioc-setup-link; diff --git a/Documentation/DocBook/v4l/media-ioc-setup-link.xml b/Documentation/DocBook/v4l/media-ioc-setup-link.xml new file mode 100644 index 00000000000..09ab3d2b3a5 --- /dev/null +++ b/Documentation/DocBook/v4l/media-ioc-setup-link.xml @@ -0,0 +1,90 @@ + + + ioctl MEDIA_IOC_SETUP_LINK + &manvol; + + + + MEDIA_IOC_SETUP_LINK + Modify the properties of a link + + + + + + int ioctl + int fd + int request + struct media_link_desc *argp + + + + + + Arguments + + + + fd + + File descriptor returned by + open(). + + + + request + + MEDIA_IOC_ENUM_LINKS + + + + argp + + + + + + + + + Description + + To change link properties applications fill a &media-link-desc; with + link identification information (source and sink pad) and the new requested + link flags. They then call the MEDIA_IOC_SETUP_LINK ioctl with a pointer to + that structure. + The only configurable property is the ENABLED + link flag to enable/disable a link. Links marked with the + IMMUTABLE link flag can not be enabled or disabled. + + Link configuration has no side effect on other links. If an enabled + link at the sink pad prevents the link from being enabled, the driver + returns with an &EBUSY;. + If the specified link can't be found the driver returns with an + &EINVAL;. + + + + &return-value; + + + + EBUSY + + The link properties can't be changed because the link is + currently busy. This can be caused, for instance, by an active media + stream (audio or video) on the link. The ioctl shouldn't be retried if + no other action is performed before to fix the problem. + + + + EINVAL + + The &media-link-desc; references a non-existing link, or the + link is immutable and an attempt to modify its configuration was made. + + + + + + diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index 78ae0209537..4809221c0ff 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -259,6 +259,16 @@ When the graph traversal is complete the function will return NULL. Graph traversal can be interrupted at any moment. No cleanup function call is required and the graph structure can be freed normally. +Helper functions can be used to find a link between two given pads, or a pad +connected to another pad through an enabled link + + media_entity_find_link(struct media_pad *source, + struct media_pad *sink); + + media_entity_remote_source(struct media_pad *pad); + +Refer to the kerneldoc documentation for more information. + Use count and power handling ---------------------------- @@ -271,3 +281,35 @@ track the number of users of every entity for power management needs. The use_count field is owned by media drivers and must not be touched by entity drivers. Access to the field must be protected by the media device graph_mutex lock. + + +Links setup +----------- + +Link properties can be modified at runtime by calling + + media_entity_setup_link(struct media_link *link, u32 flags); + +The flags argument contains the requested new link flags. + +The only configurable property is the ENABLED link flag to enable/disable a +link. Links marked with the IMMUTABLE link flag can not be enabled or disabled. + +When a link is enabled or disabled, the media framework calls the +link_setup operation for the two entities at the source and sink of the link, +in that order. If the second link_setup call fails, another link_setup call is +made on the first entity to restore the original link flags. + +Media device drivers can be notified of link setup operations by setting the +media_device::link_notify pointer to a callback function. If provided, the +notification callback will be called before enabling and after disabling +links. + +Entity drivers must implement the link_setup operation if any of their links +is non-immutable. The operation must either configure the hardware or store +the configuration information to be applied later. + +Link configuration must not have any side effect on other links. If an enabled +link at a sink pad prevents another link at the same pad from being disabled, +the link_setup operation must return -EBUSY and can't implicitly disable the +first enabled link. diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 648a9d892ac..16b70b4412f 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -172,6 +172,44 @@ static long media_device_enum_links(struct media_device *mdev, return 0; } +static long media_device_setup_link(struct media_device *mdev, + struct media_link_desc __user *_ulink) +{ + struct media_link *link = NULL; + struct media_link_desc ulink; + struct media_entity *source; + struct media_entity *sink; + int ret; + + if (copy_from_user(&ulink, _ulink, sizeof(ulink))) + return -EFAULT; + + /* Find the source and sink entities and link. + */ + source = find_entity(mdev, ulink.source.entity); + sink = find_entity(mdev, ulink.sink.entity); + + if (source == NULL || sink == NULL) + return -EINVAL; + + if (ulink.source.index >= source->num_pads || + ulink.sink.index >= sink->num_pads) + return -EINVAL; + + link = media_entity_find_link(&source->pads[ulink.source.index], + &sink->pads[ulink.sink.index]); + if (link == NULL) + return -EINVAL; + + /* Setup the link on both entities. */ + ret = __media_entity_setup_link(link, ulink.flags); + + if (copy_to_user(_ulink, &ulink, sizeof(ulink))) + return -EFAULT; + + return ret; +} + static long media_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { @@ -197,6 +235,13 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd, mutex_unlock(&dev->graph_mutex); break; + case MEDIA_IOC_SETUP_LINK: + mutex_lock(&dev->graph_mutex); + ret = media_device_setup_link(dev, + (struct media_link_desc __user *)arg); + mutex_unlock(&dev->graph_mutex); + break; + default: ret = -ENOIOCTLCMD; } diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 3e7e2d569ce..6795c920d46 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -306,3 +306,158 @@ media_entity_create_link(struct media_entity *source, u16 source_pad, return 0; } EXPORT_SYMBOL_GPL(media_entity_create_link); + +static int __media_entity_setup_link_notify(struct media_link *link, u32 flags) +{ + const u32 mask = MEDIA_LNK_FL_ENABLED; + int ret; + + /* Notify both entities. */ + ret = media_entity_call(link->source->entity, link_setup, + link->source, link->sink, flags); + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + + ret = media_entity_call(link->sink->entity, link_setup, + link->sink, link->source, flags); + if (ret < 0 && ret != -ENOIOCTLCMD) { + media_entity_call(link->source->entity, link_setup, + link->source, link->sink, link->flags); + return ret; + } + + link->flags = (link->flags & ~mask) | (flags & mask); + link->reverse->flags = link->flags; + + return 0; +} + +/** + * __media_entity_setup_link - Configure a media link + * @link: The link being configured + * @flags: Link configuration flags + * + * The bulk of link setup is handled by the two entities connected through the + * link. This function notifies both entities of the link configuration change. + * + * If the link is immutable or if the current and new configuration are + * identical, return immediately. + * + * The user is expected to hold link->source->parent->mutex. If not, + * media_entity_setup_link() should be used instead. + */ +int __media_entity_setup_link(struct media_link *link, u32 flags) +{ + struct media_device *mdev; + struct media_entity *source, *sink; + int ret = -EBUSY; + + if (link == NULL) + return -EINVAL; + + if (link->flags & MEDIA_LNK_FL_IMMUTABLE) + return link->flags == flags ? 0 : -EINVAL; + + if (link->flags == flags) + return 0; + + source = link->source->entity; + sink = link->sink->entity; + + mdev = source->parent; + + if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) { + ret = mdev->link_notify(link->source, link->sink, + MEDIA_LNK_FL_ENABLED); + if (ret < 0) + return ret; + } + + ret = __media_entity_setup_link_notify(link, flags); + if (ret < 0) + goto err; + + if (!(flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) + mdev->link_notify(link->source, link->sink, 0); + + return 0; + +err: + if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) + mdev->link_notify(link->source, link->sink, 0); + + return ret; +} + +int media_entity_setup_link(struct media_link *link, u32 flags) +{ + int ret; + + mutex_lock(&link->source->entity->parent->graph_mutex); + ret = __media_entity_setup_link(link, flags); + mutex_unlock(&link->source->entity->parent->graph_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(media_entity_setup_link); + +/** + * media_entity_find_link - Find a link between two pads + * @source: Source pad + * @sink: Sink pad + * + * Return a pointer to the link between the two entities. If no such link + * exists, return NULL. + */ +struct media_link * +media_entity_find_link(struct media_pad *source, struct media_pad *sink) +{ + struct media_link *link; + unsigned int i; + + for (i = 0; i < source->entity->num_links; ++i) { + link = &source->entity->links[i]; + + if (link->source->entity == source->entity && + link->source->index == source->index && + link->sink->entity == sink->entity && + link->sink->index == sink->index) + return link; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(media_entity_find_link); + +/** + * media_entity_remote_source - Find the source pad at the remote end of a link + * @pad: Sink pad at the local end of the link + * + * Search for a remote source pad connected to the given sink pad by iterating + * over all links originating or terminating at that pad until an enabled link + * is found. + * + * Return a pointer to the pad at the remote end of the first found enabled + * link, or NULL if no enabled link has been found. + */ +struct media_pad *media_entity_remote_source(struct media_pad *pad) +{ + unsigned int i; + + for (i = 0; i < pad->entity->num_links; i++) { + struct media_link *link = &pad->entity->links[i]; + + if (!(link->flags & MEDIA_LNK_FL_ENABLED)) + continue; + + if (link->source == pad) + return link->sink; + + if (link->sink == pad) + return link->source; + } + + return NULL; + +} +EXPORT_SYMBOL_GPL(media_entity_remote_source); diff --git a/include/linux/media.h b/include/linux/media.h index 17c93a41367..7c69913c0ad 100644 --- a/include/linux/media.h +++ b/include/linux/media.h @@ -126,5 +126,6 @@ struct media_links_enum { #define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info) #define MEDIA_IOC_ENUM_ENTITIES _IOWR('M', 2, struct media_entity_desc) #define MEDIA_IOC_ENUM_LINKS _IOWR('M', 3, struct media_links_enum) +#define MEDIA_IOC_SETUP_LINK _IOWR('M', 4, struct media_link_desc) #endif /* __LINUX_MEDIA_H */ diff --git a/include/media/media-device.h b/include/media/media-device.h index 5d2bff4fc9e..6a27d916c25 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -73,6 +73,9 @@ struct media_device { spinlock_t lock; /* Serializes graph operations. */ struct mutex graph_mutex; + + int (*link_notify)(struct media_pad *source, + struct media_pad *sink, u32 flags); }; /* media_devnode to media_device */ diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 51bdafce72c..d889dcc67d0 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -39,6 +39,12 @@ struct media_pad { unsigned long flags; /* Pad flags (MEDIA_PAD_FL_*) */ }; +struct media_entity_operations { + int (*link_setup)(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags); +}; + struct media_entity { struct list_head list; struct media_device *parent; /* Media device this entity belongs to*/ @@ -59,6 +65,8 @@ struct media_entity { struct media_pad *pads; /* Pads array (num_pads elements) */ struct media_link *links; /* Links array (max_links elements)*/ + const struct media_entity_operations *ops; /* Entity operations */ + /* Reference counts must never be negative, but are signed integers on * purpose: a simple WARN_ON(<0) check can be used to detect reference * count bugs that would make them negative. @@ -112,6 +120,11 @@ int media_entity_init(struct media_entity *entity, u16 num_pads, void media_entity_cleanup(struct media_entity *entity); int media_entity_create_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags); +int __media_entity_setup_link(struct media_link *link, u32 flags); +int media_entity_setup_link(struct media_link *link, u32 flags); +struct media_link *media_entity_find_link(struct media_pad *source, + struct media_pad *sink); +struct media_pad *media_entity_remote_source(struct media_pad *pad); struct media_entity *media_entity_get(struct media_entity *entity); void media_entity_put(struct media_entity *entity); @@ -121,4 +134,8 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph, struct media_entity * media_entity_graph_walk_next(struct media_entity_graph *graph); +#define media_entity_call(entity, operation, args...) \ + (((entity)->ops && (entity)->ops->operation) ? \ + (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD) + #endif -- cgit v1.2.3-70-g09d2 From e02188c90f6ef61f0844c42508fe603c5d4fa42b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 Aug 2010 09:00:41 -0300 Subject: [media] media: Pipelines and media streams Drivers often need to associate pipeline objects to entities, and to take stream state into account when configuring entities and links. The pipeline API helps drivers manage that information. When starting streaming, drivers call media_entity_pipeline_start(). The function marks all entities connected to the given entity through enabled links, either directly or indirectly, as streaming. Similarly, when stopping the stream, drivers call media_entity_pipeline_stop(). The media_entity_pipeline_start() function takes a pointer to a media pipeline and stores it in every entity in the graph. Drivers should embed the media_pipeline structure in higher-level pipeline structures and can then access the pipeline through the media_entity structure. Link configuration will fail with -EBUSY by default if either end of the link is a streaming entity, unless the link is marked with the MEDIA_LNK_FL_DYNAMIC flag. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/media-ioc-enum-links.xml | 5 ++ Documentation/DocBook/v4l/media-ioc-setup-link.xml | 3 + Documentation/media-framework.txt | 38 +++++++++++ drivers/media/media-entity.c | 73 ++++++++++++++++++++++ include/linux/media.h | 1 + include/media/media-entity.h | 10 +++ 6 files changed, 130 insertions(+) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/media-ioc-enum-links.xml b/Documentation/DocBook/v4l/media-ioc-enum-links.xml index 6da884159ca..d2fc73ef8d5 100644 --- a/Documentation/DocBook/v4l/media-ioc-enum-links.xml +++ b/Documentation/DocBook/v4l/media-ioc-enum-links.xml @@ -179,6 +179,11 @@ The link enabled state can't be modified at runtime. An immutable link is always enabled. + + MEDIA_LNK_FL_DYNAMIC + The link enabled state can be modified during streaming. This + flag is set by drivers and is read-only for applications. + diff --git a/Documentation/DocBook/v4l/media-ioc-setup-link.xml b/Documentation/DocBook/v4l/media-ioc-setup-link.xml index 09ab3d2b3a5..2331e76ded1 100644 --- a/Documentation/DocBook/v4l/media-ioc-setup-link.xml +++ b/Documentation/DocBook/v4l/media-ioc-setup-link.xml @@ -60,6 +60,9 @@ Link configuration has no side effect on other links. If an enabled link at the sink pad prevents the link from being enabled, the driver returns with an &EBUSY;. + Only links marked with the DYNAMIC link flag can + be enabled/disabled while streaming media data. Attempting to enable or + disable a streaming non-dynamic link will return an &EBUSY;. If the specified link can't be found the driver returns with an &EINVAL;. diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index 4809221c0ff..fd48add02cb 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -313,3 +313,41 @@ Link configuration must not have any side effect on other links. If an enabled link at a sink pad prevents another link at the same pad from being disabled, the link_setup operation must return -EBUSY and can't implicitly disable the first enabled link. + + +Pipelines and media streams +--------------------------- + +When starting streaming, drivers must notify all entities in the pipeline to +prevent link states from being modified during streaming by calling + + media_entity_pipeline_start(struct media_entity *entity, + struct media_pipeline *pipe); + +The function will mark all entities connected to the given entity through +enabled links, either directly or indirectly, as streaming. + +The media_pipeline instance pointed to by the pipe argument will be stored in +every entity in the pipeline. Drivers should embed the media_pipeline structure +in higher-level pipeline structures and can then access the pipeline through +the media_entity pipe field. + +Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must +be identical for all nested calls to the function. + +When stopping the stream, drivers must notify the entities with + + media_entity_pipeline_stop(struct media_entity *entity); + +If multiple calls to media_entity_pipeline_start() have been made the same +number of media_entity_pipeline_stop() calls are required to stop streaming. The +media_entity pipe field is reset to NULL on the last nested stop call. + +Link configuration will fail with -EBUSY by default if either end of the link is +a streaming entity. Links that can be modified while streaming must be marked +with the MEDIA_LNK_FL_DYNAMIC flag. + +If other operations need to be disallowed on streaming entities (such as +changing entities configuration parameters) drivers can explictly check the +media_entity stream_count field to find out if an entity is streaming. This +operation must be done with the media_device graph_mutex held. diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 6795c920d46..23640ed44d8 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -196,6 +196,75 @@ media_entity_graph_walk_next(struct media_entity_graph *graph) } EXPORT_SYMBOL_GPL(media_entity_graph_walk_next); +/* ----------------------------------------------------------------------------- + * Pipeline management + */ + +/** + * media_entity_pipeline_start - Mark a pipeline as streaming + * @entity: Starting entity + * @pipe: Media pipeline to be assigned to all entities in the pipeline. + * + * Mark all entities connected to a given entity through enabled links, either + * directly or indirectly, as streaming. The given pipeline object is assigned to + * every entity in the pipeline and stored in the media_entity pipe field. + * + * Calls to this function can be nested, in which case the same number of + * media_entity_pipeline_stop() calls will be required to stop streaming. The + * pipeline pointer must be identical for all nested calls to + * media_entity_pipeline_start(). + */ +void media_entity_pipeline_start(struct media_entity *entity, + struct media_pipeline *pipe) +{ + struct media_device *mdev = entity->parent; + struct media_entity_graph graph; + + mutex_lock(&mdev->graph_mutex); + + media_entity_graph_walk_start(&graph, entity); + + while ((entity = media_entity_graph_walk_next(&graph))) { + entity->stream_count++; + WARN_ON(entity->pipe && entity->pipe != pipe); + entity->pipe = pipe; + } + + mutex_unlock(&mdev->graph_mutex); +} +EXPORT_SYMBOL_GPL(media_entity_pipeline_start); + +/** + * media_entity_pipeline_stop - Mark a pipeline as not streaming + * @entity: Starting entity + * + * Mark all entities connected to a given entity through enabled links, either + * directly or indirectly, as not streaming. The media_entity pipe field is + * reset to NULL. + * + * If multiple calls to media_entity_pipeline_start() have been made, the same + * number of calls to this function are required to mark the pipeline as not + * streaming. + */ +void media_entity_pipeline_stop(struct media_entity *entity) +{ + struct media_device *mdev = entity->parent; + struct media_entity_graph graph; + + mutex_lock(&mdev->graph_mutex); + + media_entity_graph_walk_start(&graph, entity); + + while ((entity = media_entity_graph_walk_next(&graph))) { + entity->stream_count--; + if (entity->stream_count == 0) + entity->pipe = NULL; + } + + mutex_unlock(&mdev->graph_mutex); +} +EXPORT_SYMBOL_GPL(media_entity_pipeline_stop); + /* ----------------------------------------------------------------------------- * Module use count */ @@ -364,6 +433,10 @@ int __media_entity_setup_link(struct media_link *link, u32 flags) source = link->source->entity; sink = link->sink->entity; + if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) && + (source->stream_count || sink->stream_count)) + return -EBUSY; + mdev = source->parent; if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) { diff --git a/include/linux/media.h b/include/linux/media.h index 7c69913c0ad..7ed23b43f43 100644 --- a/include/linux/media.h +++ b/include/linux/media.h @@ -106,6 +106,7 @@ struct media_pad_desc { #define MEDIA_LNK_FL_ENABLED (1 << 0) #define MEDIA_LNK_FL_IMMUTABLE (1 << 1) +#define MEDIA_LNK_FL_DYNAMIC (1 << 2) struct media_link_desc { struct media_pad_desc source; diff --git a/include/media/media-entity.h b/include/media/media-entity.h index d889dcc67d0..cd8bca63a50 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -26,6 +26,9 @@ #include #include +struct media_pipeline { +}; + struct media_link { struct media_pad *source; /* Source pad */ struct media_pad *sink; /* Sink pad */ @@ -71,8 +74,11 @@ struct media_entity { * purpose: a simple WARN_ON(<0) check can be used to detect reference * count bugs that would make them negative. */ + int stream_count; /* Stream count for the entity. */ int use_count; /* Use count for the entity. */ + struct media_pipeline *pipe; /* Pipeline this entity belongs to. */ + union { /* Node specifications */ struct { @@ -118,6 +124,7 @@ struct media_entity_graph { int media_entity_init(struct media_entity *entity, u16 num_pads, struct media_pad *pads, u16 extra_links); void media_entity_cleanup(struct media_entity *entity); + int media_entity_create_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags); int __media_entity_setup_link(struct media_link *link, u32 flags); @@ -133,6 +140,9 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph, struct media_entity *entity); struct media_entity * media_entity_graph_walk_next(struct media_entity_graph *graph); +void media_entity_pipeline_start(struct media_entity *entity, + struct media_pipeline *pipe); +void media_entity_pipeline_stop(struct media_entity *entity); #define media_entity_call(entity, operation, args...) \ (((entity)->ops && (entity)->ops->operation) ? \ -- cgit v1.2.3-70-g09d2 From 95db3a60e0652a52df145aacade1a88c5acef659 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:40:05 -0300 Subject: [media] v4l: Add a media_device pointer to the v4l2_device structure The pointer will later be used to register/unregister media entities when registering/unregistering a v4l2_subdev or a video_device. With the introduction of media devices, device drivers need to store a pointer to a driver-specific structure in the device's drvdata. v4l2_device can't claim ownership of the drvdata anymore. To maintain compatibility with drivers that rely on v4l2_device storing a pointer to itself in the device's drvdata, v4l2_device_register() will keep doing so if the drvdata is NULL. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 17 ++++++++++++----- drivers/media/video/v4l2-device.c | 13 +++++++------ include/media/v4l2-device.h | 4 ++++ 3 files changed, 23 insertions(+), 11 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index eb8479565dc..7de55cfae04 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -83,11 +83,17 @@ You must register the device instance: v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); -Registration will initialize the v4l2_device struct and link dev->driver_data -to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived -from dev (driver name followed by the bus_id, to be precise). If you set it -up before calling v4l2_device_register then it will be untouched. If dev is -NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register. +Registration will initialize the v4l2_device struct. If the dev->driver_data +field is NULL, it will be linked to v4l2_dev. Drivers that use the media +device framework in addition to the V4L2 framework need to set +dev->driver_data manually to point to the driver-specific device structure +that embed the struct v4l2_device instance. This is achieved by a +dev_set_drvdata() call before registering the V4L2 device instance. + +If v4l2_dev->name is empty then it will be set to a value derived from dev +(driver name followed by the bus_id, to be precise). If you set it up before +calling v4l2_device_register then it will be untouched. If dev is NULL, then +you *must* setup v4l2_dev->name before calling v4l2_device_register. You can use v4l2_device_set_name() to set the name based on a driver name and a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1, @@ -108,6 +114,7 @@ You unregister with: v4l2_device_unregister(struct v4l2_device *v4l2_dev); +If the dev->driver_data field points to v4l2_dev, it will be reset to NULL. Unregistering will also automatically unregister all subdevs from the device. If you have a hotpluggable device (e.g. a USB device), then when a disconnect diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 8c0ad8b372d..cfbd8a38991 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -47,9 +47,8 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) if (!v4l2_dev->name[0]) snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", dev->driver->name, dev_name(dev)); - if (dev_get_drvdata(dev)) - v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n"); - dev_set_drvdata(dev, v4l2_dev); + if (!dev_get_drvdata(dev)) + dev_set_drvdata(dev, v4l2_dev); return 0; } EXPORT_SYMBOL_GPL(v4l2_device_register); @@ -72,10 +71,12 @@ EXPORT_SYMBOL_GPL(v4l2_device_set_name); void v4l2_device_disconnect(struct v4l2_device *v4l2_dev) { - if (v4l2_dev->dev) { + if (v4l2_dev->dev == NULL) + return; + + if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev) dev_set_drvdata(v4l2_dev->dev, NULL); - v4l2_dev->dev = NULL; - } + v4l2_dev->dev = NULL; } EXPORT_SYMBOL_GPL(v4l2_device_disconnect); diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 78b11e5a6db..0c2bd307503 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -21,6 +21,7 @@ #ifndef _V4L2_DEVICE_H #define _V4L2_DEVICE_H +#include #include /* Each instance of a V4L2 device should create the v4l2_device struct, @@ -39,6 +40,9 @@ struct v4l2_device { Note: dev might be NULL if there is no parent device as is the case with e.g. ISA devices. */ struct device *dev; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_device *mdev; +#endif /* used to keep track of the registered subdevs */ struct list_head subdevs; /* lock this struct; can be used by the driver as well if this -- cgit v1.2.3-70-g09d2 From 2c0ab67be1b4197a4effac89bb0604832e38be8d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:40:10 -0300 Subject: [media] v4l: Make video_device inherit from media_entity V4L2 devices are media entities. As such they need to inherit from (include) the media_entity structure. When registering/unregistering the device, the media entity is automatically registered/unregistered. The entity is acquired on device open and released on device close. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 38 +++++++++++++++++++-- drivers/media/video/v4l2-dev.c | 49 +++++++++++++++++++++++++--- include/media/v4l2-dev.h | 7 ++++ 3 files changed, 87 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 7de55cfae04..062708169de 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -71,6 +71,10 @@ sub-device instances, the video_device struct stores V4L2 device node data and in the future a v4l2_fh struct will keep track of filehandle instances (this is not yet implemented). +The V4L2 framework also optionally integrates with the media framework. If a +driver sets the struct v4l2_device mdev field, sub-devices and video nodes +will automatically appear in the media framework as entities. + struct v4l2_device ------------------ @@ -84,11 +88,14 @@ You must register the device instance: v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); Registration will initialize the v4l2_device struct. If the dev->driver_data -field is NULL, it will be linked to v4l2_dev. Drivers that use the media -device framework in addition to the V4L2 framework need to set +field is NULL, it will be linked to v4l2_dev. + +Drivers that want integration with the media device framework need to set dev->driver_data manually to point to the driver-specific device structure that embed the struct v4l2_device instance. This is achieved by a -dev_set_drvdata() call before registering the V4L2 device instance. +dev_set_drvdata() call before registering the V4L2 device instance. They must +also set the struct v4l2_device mdev field to point to a properly initialized +and registered media_device instance. If v4l2_dev->name is empty then it will be set to a value derived from dev (driver name followed by the bus_id, to be precise). If you set it up before @@ -530,6 +537,21 @@ If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or The v4l2_file_operations struct is a subset of file_operations. The main difference is that the inode argument is omitted since it is never used. +If integration with the media framework is needed, you must initialize the +media_entity struct embedded in the video_device struct (entity field) by +calling media_entity_init(): + + struct media_pad *pad = &my_vdev->pad; + int err; + + err = media_entity_init(&vdev->entity, 1, pad, 0); + +The pads array must have been previously initialized. There is no need to +manually set the struct media_entity type and name fields. + +A reference to the entity will be automatically acquired/released when the +video device is opened/closed. + v4l2_file_operations and locking -------------------------------- @@ -559,6 +581,9 @@ for you. return err; } +If the v4l2_device parent device has a non-NULL mdev field, the video device +entity will be automatically registered with the media device. + Which device is registered depends on the type argument. The following types exist: @@ -634,6 +659,13 @@ release, of course) will return an error as well. When the last user of the video device node exits, then the vdev->release() callback is called and you can do the final cleanup there. +Don't forget to cleanup the media entity associated with the video device if +it has been initialized: + + media_entity_cleanup(&vdev->entity); + +This can be done from the release callback. + video_device helper functions ----------------------------- diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index abe04ef3806..e405b8094b9 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -303,6 +303,9 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) static int v4l2_open(struct inode *inode, struct file *filp) { struct video_device *vdev; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity *entity = NULL; +#endif int ret = 0; /* Check if the video device is available */ @@ -316,6 +319,16 @@ static int v4l2_open(struct inode *inode, struct file *filp) /* and increase the device refcount */ video_get(vdev); mutex_unlock(&videodev_lock); +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) { + entity = media_entity_get(&vdev->entity); + if (!entity) { + ret = -EBUSY; + video_put(vdev); + return ret; + } + } +#endif if (vdev->fops->open) { if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { ret = -ERESTARTSYS; @@ -331,8 +344,13 @@ static int v4l2_open(struct inode *inode, struct file *filp) err: /* decrease the refcount in case of an error */ - if (ret) + if (ret) { +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) + media_entity_put(entity); +#endif video_put(vdev); + } return ret; } @@ -349,7 +367,10 @@ static int v4l2_release(struct inode *inode, struct file *filp) if (vdev->lock) mutex_unlock(vdev->lock); } - +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) + media_entity_put(&vdev->entity); +#endif /* decrease the refcount unconditionally since the release() return value is ignored. */ video_put(vdev); @@ -585,12 +606,27 @@ int __video_register_device(struct video_device *vdev, int type, int nr, if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__, name_base, nr, video_device_node_name(vdev)); - - /* Part 5: Activate this minor. The char device can now be used. */ +#if defined(CONFIG_MEDIA_CONTROLLER) + /* Part 5: Register the entity. */ + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) { + vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; + vdev->entity.name = vdev->name; + vdev->entity.v4l.major = VIDEO_MAJOR; + vdev->entity.v4l.minor = vdev->minor; + ret = media_device_register_entity(vdev->v4l2_dev->mdev, + &vdev->entity); + if (ret < 0) + printk(KERN_WARNING + "%s: media_device_register_entity failed\n", + __func__); + } +#endif + /* Part 6: Activate this minor. The char device can now be used. */ set_bit(V4L2_FL_REGISTERED, &vdev->flags); mutex_lock(&videodev_lock); video_device[vdev->minor] = vdev; mutex_unlock(&videodev_lock); + return 0; cleanup: @@ -618,6 +654,11 @@ void video_unregister_device(struct video_device *vdev) if (!vdev || !video_is_registered(vdev)) return; +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) + media_device_unregister_entity(&vdev->entity); +#endif + mutex_lock(&videodev_lock); /* This must be in a critical section to prevent a race with v4l2_open. * Once this bit has been cleared video_get may never be called again. diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 4fe6831b185..51b2c515f68 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -16,6 +16,8 @@ #include #include +#include + #define VIDEO_MAJOR 81 #define VFL_TYPE_GRABBER 0 @@ -55,6 +57,9 @@ struct v4l2_file_operations { struct video_device { +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity entity; +#endif /* device ops */ const struct v4l2_file_operations *fops; @@ -100,6 +105,8 @@ struct video_device struct mutex *lock; }; +#define media_entity_to_video_device(entity) \ + container_of(entity, struct video_device, entity) /* dev to video-device */ #define to_video_device(cd) container_of(cd, struct video_device, dev) -- cgit v1.2.3-70-g09d2 From 61f5db549dde43fb91a8b337f3a4096e4076c2d9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:40:08 -0300 Subject: [media] v4l: Make v4l2_subdev inherit from media_entity V4L2 subdevices are media entities. As such they need to inherit from (include) the media_entity structure. When registering/unregistering the subdevice, the media entity is automatically registered/unregistered. The entity is acquired on device open and released on device close. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 23 ++++++++++++++++++ drivers/media/video/v4l2-device.c | 36 ++++++++++++++++++++++++---- drivers/media/video/v4l2-subdev.c | 28 ++++++++++++++++++++-- include/media/v4l2-subdev.h | 6 +++++ 4 files changed, 87 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 062708169de..77d96f4e3f5 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -268,6 +268,26 @@ A sub-device driver initializes the v4l2_subdev struct using: Afterwards you need to initialize subdev->name with a unique name and set the module owner. This is done for you if you use the i2c helper functions. +If integration with the media framework is needed, you must initialize the +media_entity struct embedded in the v4l2_subdev struct (entity field) by +calling media_entity_init(): + + struct media_pad *pads = &my_sd->pads; + int err; + + err = media_entity_init(&sd->entity, npads, pads, 0); + +The pads array must have been previously initialized. There is no need to +manually set the struct media_entity type and name fields, but the revision +field must be initialized if needed. + +A reference to the entity will be automatically acquired/released when the +subdev device node (if any) is opened/closed. + +Don't forget to cleanup the media entity before the sub-device is destroyed: + + media_entity_cleanup(&sd->entity); + A device (bridge) driver needs to register the v4l2_subdev with the v4l2_device: @@ -277,6 +297,9 @@ This can fail if the subdev module disappeared before it could be registered. After this function was called successfully the subdev->dev field points to the v4l2_device. +If the v4l2_device parent device has a non-NULL mdev field, the sub-device +entity will be automatically registered with the media device. + You can unregister a sub-device using: v4l2_device_unregister_subdev(sd); diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index cfbd8a38991..a1afda352d0 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -118,8 +118,11 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) EXPORT_SYMBOL_GPL(v4l2_device_unregister); int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, - struct v4l2_subdev *sd) + struct v4l2_subdev *sd) { +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity *entity = &sd->entity; +#endif int err; /* Check for valid input */ @@ -147,6 +150,19 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, return err; } +#if defined(CONFIG_MEDIA_CONTROLLER) + /* Register the entity. */ + if (v4l2_dev->mdev) { + err = media_device_register_entity(v4l2_dev->mdev, entity); + if (err < 0) { + if (sd->internal_ops && sd->internal_ops->unregistered) + sd->internal_ops->unregistered(sd); + module_put(sd->owner); + return err; + } + } +#endif + spin_lock(&v4l2_dev->lock); list_add_tail(&sd->list, &v4l2_dev->subdevs); spin_unlock(&v4l2_dev->lock); @@ -177,25 +193,37 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) sd->owner); if (err < 0) return err; +#if defined(CONFIG_MEDIA_CONTROLLER) + sd->entity.v4l.major = VIDEO_MAJOR; + sd->entity.v4l.minor = vdev->minor; +#endif } - return 0; } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes); void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) { + struct v4l2_device *v4l2_dev; + /* return if it isn't registered */ if (sd == NULL || sd->v4l2_dev == NULL) return; - spin_lock(&sd->v4l2_dev->lock); + v4l2_dev = sd->v4l2_dev; + + spin_lock(&v4l2_dev->lock); list_del(&sd->list); - spin_unlock(&sd->v4l2_dev->lock); + spin_unlock(&v4l2_dev->lock); + if (sd->internal_ops && sd->internal_ops->unregistered) sd->internal_ops->unregistered(sd); sd->v4l2_dev = NULL; +#if defined(CONFIG_MEDIA_CONTROLLER) + if (v4l2_dev->mdev) + media_device_unregister_entity(&sd->entity); +#endif video_unregister_device(&sd->devnode); module_put(sd->owner); } diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 0c67f5a278f..85573638aa1 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -35,7 +35,10 @@ static int subdev_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - struct v4l2_fh *vfh; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity *entity; +#endif + struct v4l2_fh *vfh = NULL; int ret; if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) { @@ -58,11 +61,20 @@ static int subdev_open(struct file *file) v4l2_fh_add(vfh); file->private_data = vfh; } - +#if defined(CONFIG_MEDIA_CONTROLLER) + if (sd->v4l2_dev->mdev) { + entity = media_entity_get(&sd->entity); + if (!entity) { + ret = -EBUSY; + goto err; + } + } +#endif return 0; err: if (vfh != NULL) { + v4l2_fh_del(vfh); v4l2_fh_exit(vfh); kfree(vfh); } @@ -72,8 +84,16 @@ err: static int subdev_close(struct file *file) { +#if defined(CONFIG_MEDIA_CONTROLLER) + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); +#endif struct v4l2_fh *vfh = file->private_data; +#if defined(CONFIG_MEDIA_CONTROLLER) + if (sd->v4l2_dev->mdev) + media_entity_put(&sd->entity); +#endif if (vfh != NULL) { v4l2_fh_del(vfh); v4l2_fh_exit(vfh); @@ -172,5 +192,9 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) sd->grp_id = 0; sd->dev_priv = NULL; sd->host_priv = NULL; +#if defined(CONFIG_MEDIA_CONTROLLER) + sd->entity.name = sd->name; + sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV; +#endif } EXPORT_SYMBOL(v4l2_subdev_init); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 0f9937be53d..6f51ce4d7ee 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -21,6 +21,7 @@ #ifndef _V4L2_SUBDEV_H #define _V4L2_SUBDEV_H +#include #include #include #include @@ -450,6 +451,9 @@ struct v4l2_subdev_internal_ops { stand-alone or embedded in a larger struct. */ struct v4l2_subdev { +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity entity; +#endif struct list_head list; struct module *owner; u32 flags; @@ -472,6 +476,8 @@ struct v4l2_subdev { unsigned int nevents; }; +#define media_entity_to_v4l2_subdev(ent) \ + container_of(ent, struct v4l2_subdev, entity) #define vdev_to_v4l2_subdev(vdev) \ container_of(vdev, struct v4l2_subdev, devnode) -- cgit v1.2.3-70-g09d2 From d3a7ed99759b18e4fd19b8ddd226f8085b8bd975 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 16 Mar 2010 00:26:04 +0100 Subject: [media] v4l: v4l2_subdev userspace format API - documentation binary files Add images used by the V4L2 subdev userspace format API documentation. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/bayer.pdf | Bin 0 -> 12116 bytes Documentation/DocBook/v4l/bayer.png | Bin 0 -> 9725 bytes Documentation/DocBook/v4l/pipeline.pdf | Bin 0 -> 20276 bytes Documentation/DocBook/v4l/pipeline.png | Bin 0 -> 12130 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Documentation/DocBook/v4l/bayer.pdf create mode 100644 Documentation/DocBook/v4l/bayer.png create mode 100644 Documentation/DocBook/v4l/pipeline.pdf create mode 100644 Documentation/DocBook/v4l/pipeline.png (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/bayer.pdf b/Documentation/DocBook/v4l/bayer.pdf new file mode 100644 index 00000000000..905e60e6cd4 Binary files /dev/null and b/Documentation/DocBook/v4l/bayer.pdf differ diff --git a/Documentation/DocBook/v4l/bayer.png b/Documentation/DocBook/v4l/bayer.png new file mode 100644 index 00000000000..9b15fb22e81 Binary files /dev/null and b/Documentation/DocBook/v4l/bayer.png differ diff --git a/Documentation/DocBook/v4l/pipeline.pdf b/Documentation/DocBook/v4l/pipeline.pdf new file mode 100644 index 00000000000..ee3e37f04b6 Binary files /dev/null and b/Documentation/DocBook/v4l/pipeline.pdf differ diff --git a/Documentation/DocBook/v4l/pipeline.png b/Documentation/DocBook/v4l/pipeline.png new file mode 100644 index 00000000000..f19b86c2c24 Binary files /dev/null and b/Documentation/DocBook/v4l/pipeline.png differ -- cgit v1.2.3-70-g09d2 From 333c8b97785d5afd5085ba3720b4d259623290f6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 15 Mar 2010 20:26:04 -0300 Subject: [media] v4l: v4l2_subdev userspace format API Add a userspace API to get, set and enumerate the media format on a subdev pad. The format at the output of a subdev usually depends on the format at its input(s). The try format operation is thus not suitable for probing format at individual pads, as it can't modify the device state and thus can't remember the format tried at the input to compute the output format. To fix the problem, pass an extra argument to the get/set format operations to select the 'try' or 'active' format. The try format is used when probing the subdev. Setting the try format must not change the device configuration but can store data for later reuse. Data storage is provided at the file-handle level so applications probing the subdev concurently won't interfere with each other. The active format is used when configuring the subdev. It's identical to the format handled by the usual get/set operations. Signed-off-by: Laurent Pinchart Signed-off-by: Stanimir Varbanov Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/Makefile | 5 +- Documentation/DocBook/media-entities.tmpl | 16 + Documentation/DocBook/v4l/dev-subdev.xml | 280 +++ Documentation/DocBook/v4l/subdev-formats.xml | 2416 ++++++++++++++++++++ Documentation/DocBook/v4l/v4l2.xml | 4 + Documentation/DocBook/v4l/vidioc-streamon.xml | 9 + .../DocBook/v4l/vidioc-subdev-enum-frame-size.xml | 154 ++ .../DocBook/v4l/vidioc-subdev-enum-mbus-code.xml | 119 + Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml | 180 ++ drivers/media/video/v4l2-subdev.c | 49 + include/linux/Kbuild | 1 + include/linux/v4l2-subdev.h | 90 + include/media/v4l2-subdev.h | 10 + 13 files changed, 3332 insertions(+), 1 deletion(-) create mode 100644 Documentation/DocBook/v4l/dev-subdev.xml create mode 100644 Documentation/DocBook/v4l/subdev-formats.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml create mode 100644 include/linux/v4l2-subdev.h (limited to 'Documentation') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 8b6e00a7103..2deb069aedf 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -53,7 +53,10 @@ MAN := $(patsubst %.xml, %.9, $(BOOKS)) mandocs: $(MAN) build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \ - cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/ + cp $(srctree)/Documentation/DocBook/dvb/*.png \ + $(srctree)/Documentation/DocBook/v4l/*.gif \ + $(srctree)/Documentation/DocBook/v4l/*.png \ + $(objtree)/Documentation/DocBook/media/ xmldoclinks: ifneq ($(objtree),$(srctree)) diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index 121db154924..dbb9cb2e1ec 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -86,6 +86,10 @@ VIDIOC_S_PRIORITY"> VIDIOC_S_STD"> VIDIOC_S_TUNER"> +VIDIOC_SUBDEV_ENUM_FRAME_SIZE"> +VIDIOC_SUBDEV_ENUM_MBUS_CODE"> +VIDIOC_SUBDEV_G_FMT"> +VIDIOC_SUBDEV_S_FMT"> VIDIOC_TRY_ENCODER_CMD"> VIDIOC_TRY_EXT_CTRLS"> VIDIOC_TRY_FMT"> @@ -107,6 +111,7 @@ v4l2_field"> v4l2_frmivaltypes"> v4l2_frmsizetypes"> +v4l2_mbus_pixelcode"> v4l2_memory"> v4l2_mpeg_audio_ac3_bitrate"> v4l2_mpeg_audio_crc"> @@ -130,6 +135,7 @@ v4l2_mpeg_video_encoding"> v4l2_power_line_frequency"> v4l2_priority"> +v4l2_subdev_format_whence"> v4l2_tuner_type"> v4l2_preemphasis"> @@ -172,6 +178,7 @@ v4l2_hw_freq_seek"> v4l2_input"> v4l2_jpegcompression"> +v4l2_mbus_framefmt"> v4l2_modulator"> v4l2_mpeg_vbi_fmt_ivtv"> v4l2_output"> @@ -186,6 +193,9 @@ v4l2_sliced_vbi_cap"> v4l2_sliced_vbi_data"> v4l2_sliced_vbi_format"> +v4l2_subdev_frame_size_enum"> +v4l2_subdev_format"> +v4l2_subdev_mbus_code_enum"> v4l2_standard"> v4l2_streamparm"> v4l2_timecode"> @@ -215,6 +225,7 @@ ENXIO error code"> EMFILE error code"> EPERM error code"> +EPIPE error code"> ERANGE error code"> @@ -234,6 +245,7 @@ + @@ -319,6 +331,10 @@ + + + + diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml new file mode 100644 index 00000000000..fc62e65f45e --- /dev/null +++ b/Documentation/DocBook/v4l/dev-subdev.xml @@ -0,0 +1,280 @@ + Sub-device Interface + + + Experimental + This is an experimental + interface and may change in the future. + + + The complex nature of V4L2 devices, where hardware is often made of + several integrated circuits that need to interact with each other in a + controlled way, leads to complex V4L2 drivers. The drivers usually reflect + the hardware model in software, and model the different hardware components + as software blocks called sub-devices. + + V4L2 sub-devices are usually kernel-only objects. If the V4L2 driver + implements the media device API, they will automatically inherit from media + entities. Applications will be able to enumerate the sub-devices and discover + the hardware topology using the media entities, pads and links enumeration + API. + + In addition to make sub-devices discoverable, drivers can also choose + to make them directly configurable by applications. When both the sub-device + driver and the V4L2 device driver support this, sub-devices will feature a + character device node on which ioctls can be called to + + query, read and write sub-devices controls + subscribe and unsubscribe to events and retrieve them + negotiate image formats on individual pads + + + + Sub-device character device nodes, conventionally named + /dev/v4l-subdev*, use major number 81. + +
+ Controls + Most V4L2 controls are implemented by sub-device hardware. Drivers + usually merge all controls and expose them through video device nodes. + Applications can control all sub-devices through a single interface. + + Complex devices sometimes implement the same control in different + pieces of hardware. This situation is common in embedded platforms, where + both sensors and image processing hardware implement identical functions, + such as contrast adjustment, white balance or faulty pixels correction. As + the V4L2 controls API doesn't support several identical controls in a single + device, all but one of the identical controls are hidden. + + Applications can access those hidden controls through the sub-device + node with the V4L2 control API described in . The + ioctls behave identically as when issued on V4L2 device nodes, with the + exception that they deal only with controls implemented in the sub-device. + + + Depending on the driver, those controls might also be exposed through + one (or several) V4L2 device nodes. +
+ +
+ Events + V4L2 sub-devices can notify applications of events as described in + . The API behaves identically as when used on V4L2 + device nodes, with the exception that it only deals with events generated by + the sub-device. Depending on the driver, those events might also be reported + on one (or several) V4L2 device nodes. +
+ +
+ Pad-level Formats + + Pad-level formats are only applicable to very complex device that + need to expose low-level format configuration to user space. Generic V4L2 + applications do not need to use the API described in + this section. + + For the purpose of this section, the term + format means the combination of media bus data + format, frame width and frame height. + + Image formats are typically negotiated on video capture and output + devices using the cropping and scaling ioctls. + The driver is responsible for configuring every block in the video pipeline + according to the requested format at the pipeline input and/or + output. + + For complex devices, such as often found in embedded systems, + identical image sizes at the output of a pipeline can be achieved using + different hardware configurations. One such exemple is shown on + , where + image scaling can be performed on both the video sensor and the host image + processing hardware. + +
+ Image Format Negotation on Pipelines + + + + + + + + + High quality and high speed pipeline configuration + + +
+ + The sensor scaler is usually of less quality than the host scaler, but + scaling on the sensor is required to achieve higher frame rates. Depending + on the use case (quality vs. speed), the pipeline must be configured + differently. Applications need to configure the formats at every point in + the pipeline explicitly. + + Drivers that implement the media + API can expose pad-level image format configuration to applications. + When they do, applications can use the &VIDIOC-SUBDEV-G-FMT; and + &VIDIOC-SUBDEV-S-FMT; ioctls. to negotiate formats on a per-pad basis. + + Applications are responsible for configuring coherent parameters on + the whole pipeline and making sure that connected pads have compatible + formats. The pipeline is checked for formats mismatch at &VIDIOC-STREAMON; + time, and an &EPIPE; is then returned if the configuration is + invalid. + + Pad-level image format configuration support can be tested by calling + the &VIDIOC-SUBDEV-G-FMT; ioctl on pad 0. If the driver returns an &EINVAL; + pad-level format configuration is not supported by the sub-device. + +
+ Format Negotiation + + Acceptable formats on pads can (and usually do) depend on a number + of external parameters, such as formats on other pads, active links, or + even controls. Finding a combination of formats on all pads in a video + pipeline, acceptable to both application and driver, can't rely on formats + enumeration only. A format negotiation mechanism is required. + + Central to the format negotiation mechanism are the get/set format + operations. When called with the which argument + set to V4L2_SUBDEV_FORMAT_TRY, the + &VIDIOC-SUBDEV-G-FMT; and &VIDIOC-SUBDEV-S-FMT; ioctls operate on a set of + formats parameters that are not connected to the hardware configuration. + Modifying those 'try' formats leaves the device state untouched (this + applies to both the software state stored in the driver and the hardware + state stored in the device itself). + + While not kept as part of the device state, try formats are stored + in the sub-device file handles. A &VIDIOC-SUBDEV-G-FMT; call will return + the last try format set on the same sub-device file + handle. Several applications querying the same sub-device at + the same time will thus not interact with each other. + + To find out whether a particular format is supported by the device, + applications use the &VIDIOC-SUBDEV-S-FMT; ioctl. Drivers verify and, if + needed, change the requested format based on + device requirements and return the possibly modified value. Applications + can then choose to try a different format or accept the returned value and + continue. + + Formats returned by the driver during a negotiation iteration are + guaranteed to be supported by the device. In particular, drivers guarantee + that a returned format will not be further changed if passed to an + &VIDIOC-SUBDEV-S-FMT; call as-is (as long as external parameters, such as + formats on other pads or links' configuration are not changed). + + Drivers automatically propagate formats inside sub-devices. When a + try or active format is set on a pad, corresponding formats on other pads + of the same sub-device can be modified by the driver. Drivers are free to + modify formats as required by the device. However, they should comply with + the following rules when possible: + + Formats should be propagated from sink pads to source pads. + Modifying a format on a source pad should not modify the format on any + sink pad. + Sub-devices that scale frames using variable scaling factors + should reset the scale factors to default values when sink pads formats + are modified. If the 1:1 scaling ratio is supported, this means that + source pads formats should be reset to the sink pads formats. + + + + Formats are not propagated across links, as that would involve + propagating them from one sub-device file handle to another. Applications + must then take care to configure both ends of every link explicitly with + compatible formats. Identical formats on the two ends of a link are + guaranteed to be compatible. Drivers are free to accept different formats + matching device requirements as being compatible. + + + shows a sample configuration sequence for the pipeline described in + (table + columns list entity names and pad numbers). + + + Sample Pipeline Configuration + + + + + + + + + + + Sensor/0 + Frontend/0 + Frontend/1 + Scaler/0 + Scaler/1 + + + + + Initial state + 2048x1536 + - + - + - + - + + + Configure frontend input + 2048x1536 + 2048x1536 + 2046x1534 + - + - + + + Configure scaler input + 2048x1536 + 2048x1536 + 2046x1534 + 2046x1534 + 2046x1534 + + + Configure scaler output + 2048x1536 + 2048x1536 + 2046x1534 + 2046x1534 + 1280x960 + + + +
+ + + + Initial state. The sensor output is set to its native 3MP + resolution. Resolutions on the host frontend and scaler input and output + pads are undefined. + The application configures the frontend input pad resolution to + 2048x1536. The driver propagates the format to the frontend output pad. + Note that the propagated output format can be different, as in this case, + than the input format, as the hardware might need to crop pixels (for + instance when converting a Bayer filter pattern to RGB or YUV). + The application configures the scaler input pad resolution to + 2046x1534 to match the frontend output resolution. The driver propagates + the format to the scaler output pad. + The application configures the scaler output pad resolution to + 1280x960. + + + + When satisfied with the try results, applications can set the active + formats by setting the which argument to + V4L2_SUBDEV_FORMAT_TRY. Active formats are changed + exactly as try formats by drivers. To avoid modifying the hardware state + during format negotiation, applications should negotiate try formats first + and then modify the active settings using the try formats returned during + the last negotiation iteration. This guarantees that the active format + will be applied as-is by the driver without being modified. + +
+ +
+ + &sub-subdev-formats; diff --git a/Documentation/DocBook/v4l/subdev-formats.xml b/Documentation/DocBook/v4l/subdev-formats.xml new file mode 100644 index 00000000000..0cae5720700 --- /dev/null +++ b/Documentation/DocBook/v4l/subdev-formats.xml @@ -0,0 +1,2416 @@ +
+ Media Bus Formats + + + struct <structname>v4l2_mbus_framefmt</structname> + + &cs-str; + + + __u32 + width + Image width, in pixels. + + + __u32 + height + Image height, in pixels. + + + __u32 + code + Format code, from &v4l2-mbus-pixelcode;. + + + __u32 + field + Field order, from &v4l2-field;. See + for details. + + + __u32 + colorspace + Image colorspace, from &v4l2-colorspace;. See + for details. + + + __u32 + reserved[7] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+ +
+ Media Bus Pixel Codes + + The media bus pixel codes describe image formats as flowing over + physical busses (both between separate physical components and inside SoC + devices). This should not be confused with the V4L2 pixel formats that + describe, using four character codes, image formats as stored in memory. + + + While there is a relationship between image formats on busses and + image formats in memory (a raw Bayer image won't be magically converted to + JPEG just by storing it to memory), there is no one-to-one correspondance + between them. + +
+ Packed RGB Formats + + Those formats transfer pixel data as red, green and blue components. + The format code is made of the following information. + + The red, green and blue components order code, as encoded in a + pixel sample. Possible values are RGB and BGR. + The number of bits per component, for each component. The values + can be different for all components. Common values are 555 and 565. + + The number of bus samples per pixel. Pixels that are wider than + the bus width must be transferred in multiple samples. Common values are + 1 and 2. + The bus width. + For formats where the total number of bits per pixel is smaller + than the number of bus samples per pixel times the bus width, a padding + value stating if the bytes are padded in their most high order bits + (PADHI) or low order bits (PADLO). + For formats where the number of bus samples per pixel is larger + than 1, an endianness value stating if the pixel is transferred MSB first + (BE) or LSB first (LE). + + + + For instance, a format where pixels are encoded as 5-bits red, 5-bits + green and 5-bit blue values padded on the high bit, transferred as 2 8-bit + samples per pixel with the most significant bits (padding, red and half of + the green value) transferred first will be named + V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE. + + + The following tables list existing packet RGB formats. + + + RGB formats + + + + + + + + + + + + + + + + Identifier + Code + + Data organization + + + + + Bit + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + + V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE + 0x1001 + + 0 + 0 + 0 + 0 + r3 + r2 + r1 + r0 + + + + + + g3 + g2 + g1 + g0 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE + 0x1002 + + g3 + g2 + g1 + g0 + b3 + b2 + b1 + b0 + + + + + + 0 + 0 + 0 + 0 + r3 + r2 + r1 + r0 + + + V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE + 0x1003 + + 0 + r4 + r3 + r2 + r1 + r0 + g4 + g3 + + + + + + g2 + g1 + g0 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE + 0x1004 + + g2 + g1 + g0 + b4 + b3 + b2 + b1 + b0 + + + + + + 0 + r4 + r3 + r2 + r1 + r0 + g4 + g3 + + + V4L2_MBUS_FMT_BGR565_2X8_BE + 0x1005 + + b4 + b3 + b2 + b1 + b0 + g5 + g4 + g3 + + + + + + g2 + g1 + g0 + r4 + r3 + r2 + r1 + r0 + + + V4L2_MBUS_FMT_BGR565_2X8_LE + 0x1006 + + g2 + g1 + g0 + r4 + r3 + r2 + r1 + r0 + + + + + + b4 + b3 + b2 + b1 + b0 + g5 + g4 + g3 + + + V4L2_MBUS_FMT_RGB565_2X8_BE + 0x1007 + + r4 + r3 + r2 + r1 + r0 + g5 + g4 + g3 + + + + + + g2 + g1 + g0 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_RGB565_2X8_LE + 0x1008 + + g2 + g1 + g0 + b4 + b3 + b2 + b1 + b0 + + + + + + r4 + r3 + r2 + r1 + r0 + g5 + g4 + g3 + + + +
+
+ +
+ Bayer Formats + + Those formats transfer pixel data as red, green and blue components. + The format code is made of the following information. + + The red, green and blue components order code, as encoded in a + pixel sample. The possible values are shown in . + The number of bits per pixel component. All components are + transferred on the same number of bits. Common values are 8, 10 and 12. + + If the pixel components are DPCM-compressed, a mention of the + DPCM compression and the number of bits per compressed pixel component. + + The number of bus samples per pixel. Pixels that are wider than + the bus width must be transferred in multiple samples. Common values are + 1 and 2. + The bus width. + For formats where the total number of bits per pixel is smaller + than the number of bus samples per pixel times the bus width, a padding + value stating if the bytes are padded in their most high order bits + (PADHI) or low order bits (PADLO). + For formats where the number of bus samples per pixel is larger + than 1, an endianness value stating if the pixel is transferred MSB first + (BE) or LSB first (LE). + + + + For instance, a format with uncompressed 10-bit Bayer components + arranged in a red, green, green, blue pattern transferred as 2 8-bit + samples per pixel with the least significant bits transferred first will + be named V4L2_MBUS_FMT_SRGGB10_2X8_PADHI_LE. + + +
+ Bayer Patterns + + + + + + + + + Bayer filter color patterns + + +
+ + The following table lists existing packet Bayer formats. The data + organization is given as an example for the first pixel only. + + + Bayer Formats + + + + + + + + + + + + + + + + + + + + Identifier + Code + + Data organization + + + + + Bit + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + + V4L2_MBUS_FMT_SBGGR8_1X8 + 0x3001 + + - + - + - + - + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_SGRBG8_1X8 + 0x3002 + + - + - + - + - + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 + 0x300b + + - + - + - + - + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 + 0x300c + + - + - + - + - + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 + 0x3009 + + - + - + - + - + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 + 0x300d + + - + - + - + - + r7 + r6 + r5 + r4 + r3 + r2 + r1 + r0 + + + V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE + 0x3003 + + - + - + - + - + 0 + 0 + 0 + 0 + 0 + 0 + b9 + b8 + + + + + + - + - + - + - + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE + 0x3004 + + - + - + - + - + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + + + + - + - + - + - + 0 + 0 + 0 + 0 + 0 + 0 + b9 + b8 + + + V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE + 0x3005 + + - + - + - + - + b9 + b8 + b7 + b6 + b5 + b4 + b3 + b2 + + + + + + - + - + - + - + b1 + b0 + 0 + 0 + 0 + 0 + 0 + 0 + + + V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE + 0x3006 + + - + - + - + - + b1 + b0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + - + - + - + - + b9 + b8 + b7 + b6 + b5 + b4 + b3 + b2 + + + V4L2_MBUS_FMT_SBGGR10_1X10 + 0x3007 + + - + - + b9 + b8 + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_SGBRG10_1X10 + 0x300e + + - + - + g9 + g8 + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SGRBG10_1X10 + 0x300a + + - + - + g9 + g8 + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SRGGB10_1X10 + 0x300f + + - + - + r9 + r8 + r7 + r6 + r5 + r4 + r3 + r2 + r1 + r0 + + + V4L2_MBUS_FMT_SBGGR12_1X12 + 0x3008 + + b11 + b10 + b9 + b8 + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + +
+
+ +
+ Packed YUV Formats + + Those data formats transfer pixel data as (possibly downsampled) Y, U + and V components. The format code is made of the following information. + + The Y, U and V components order code, as transferred on the + bus. Possible values are YUYV, UYVY, YVYU and VYUY. + The number of bits per pixel component. All components are + transferred on the same number of bits. Common values are 8, 10 and 12. + + The number of bus samples per pixel. Pixels that are wider than + the bus width must be transferred in multiple samples. Common values are + 1, 1.5 (encoded as 1_5) and 2. + The bus width. When the bus width is larger than the number of + bits per pixel component, several components are packed in a single bus + sample. The components are ordered as specified by the order code, with + components on the left of the code transferred in the high order bits. + Common values are 8 and 16. + + + + + For instance, a format where pixels are encoded as 8-bit YUV values + downsampled to 4:2:2 and transferred as 2 8-bit bus samples per pixel in the + U, Y, V, Y order will be named V4L2_MBUS_FMT_UYVY8_2X8. + + + The following table lisst existing packet YUV formats. + + + YUV Formats + + + + + + + + + + + + + + + + + + + + + + + + + + + + Identifier + Code + + Data organization + + + + + Bit + 19 + 18 + 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + + V4L2_MBUS_FMT_Y8_1X8 + 0x2001 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_UYVY8_1_5X8 + 0x2002 + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_VYUY8_1_5X8 + 0x2003 + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_YUYV8_1_5X8 + 0x2004 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU8_1_5X8 + 0x2005 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + V4L2_MBUS_FMT_UYVY8_2X8 + 0x2006 + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_VYUY8_2X8 + 0x2007 + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_YUYV8_2X8 + 0x2008 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU8_2X8 + 0x2009 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + V4L2_MBUS_FMT_Y10_1X10 + 0x200a + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_YUYV10_2X10 + 0x200b + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + v9 + v8 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU10_2X10 + 0x200c + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + v9 + v8 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + V4L2_MBUS_FMT_UYVY8_1X16 + 0x200f + + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_VYUY8_1X16 + 0x2010 + + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_YUYV8_1X16 + 0x2011 + + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU8_1X16 + 0x2012 + + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + V4L2_MBUS_FMT_YUYV10_1X20 + 0x200d + + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + v9 + v8 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU10_1X20 + 0x200e + + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + v9 + v8 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + +
+
+
+
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 7859d7d9da3..2ada2f86bb5 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -439,6 +439,7 @@ and discussions on the V4L mailing list.
&sub-dev-radio;
&sub-dev-rds;
&sub-dev-event;
+
&sub-dev-subdev;
@@ -506,6 +507,9 @@ and discussions on the V4L mailing list. &sub-reqbufs; &sub-s-hw-freq-seek; &sub-streamon; + &sub-subdev-enum-frame-size; + &sub-subdev-enum-mbus-code; + &sub-subdev-g-fmt; &sub-subscribe-event; &sub-mmap; diff --git a/Documentation/DocBook/v4l/vidioc-streamon.xml b/Documentation/DocBook/v4l/vidioc-streamon.xml index e42bff1f2c0..75ed39bf4d2 100644 --- a/Documentation/DocBook/v4l/vidioc-streamon.xml +++ b/Documentation/DocBook/v4l/vidioc-streamon.xml @@ -93,6 +93,15 @@ synchronize with other events. been allocated (memory mapping) or enqueued (output) yet.
+ + EPIPE + + The driver implements pad-level format configuration and + the pipeline configuration is invalid. + + + diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml new file mode 100644 index 00000000000..79ce42b7c60 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml @@ -0,0 +1,154 @@ + + + ioctl VIDIOC_SUBDEV_ENUM_FRAME_SIZE + &manvol; + + + + VIDIOC_SUBDEV_ENUM_FRAME_SIZE + Enumerate media bus frame sizes + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_frame_size_enum * + argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_ENUM_FRAME_SIZE + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + This ioctl allows applications to enumerate all frame sizes + supported by a sub-device on the given pad for the given media bus format. + Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE; + ioctl. + + To enumerate frame sizes applications initialize the + pad, code and + index fields of the + &v4l2-subdev-mbus-code-enum; and call the + VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl with a pointer to + the structure. Drivers fill the minimum and maximum frame sizes or return + an &EINVAL; if one of the input parameters is invalid. + + Sub-devices that only support discrete frame sizes (such as most + sensors) will return one or more frame sizes with identical minimum and + maximum values. + + Not all possible sizes in given [minimum, maximum] ranges need to be + supported. For instance, a scaler that uses a fixed-point scaling ratio + might not be able to produce every frame size between the minimum and + maximum values. Applications must use the &VIDIOC-SUBDEV-S-FMT; ioctl to + try the sub-device for an exact supported frame size. + + Available frame sizes may depend on the current 'try' formats at other + pads of the sub-device, as well as on the current active links and the + current values of V4L2 controls. See &VIDIOC-SUBDEV-G-FMT; for more + information about try formats. + + + struct <structname>v4l2_subdev_frame_size_enum</structname> + + &cs-str; + + + __u32 + index + Number of the format in the enumeration, set by the + application. + + + __u32 + pad + Pad number as reported by the media controller API. + + + __u32 + code + The media bus format code, as defined in + . + + + __u32 + min_width + Minimum frame width, in pixels. + + + __u32 + max_width + Maximum frame width, in pixels. + + + __u32 + min_height + Minimum frame height, in pixels. + + + __u32 + max_height + Maximum frame height, in pixels. + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EINVAL + + The &v4l2-subdev-frame-size-enum; pad + references a non-existing pad, the code is + invalid for the given pad or the index + field is out of bounds. + + + + +
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml new file mode 100644 index 00000000000..a6b3432449f --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml @@ -0,0 +1,119 @@ + + + ioctl VIDIOC_SUBDEV_ENUM_MBUS_CODE + &manvol; + + + + VIDIOC_SUBDEV_ENUM_MBUS_CODE + Enumerate media bus formats + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_mbus_code_enum * + argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_ENUM_MBUS_CODE + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + To enumerate media bus formats available at a given sub-device pad + applications initialize the pad and + index fields of &v4l2-subdev-mbus-code-enum; and + call the VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl with a + pointer to this structure. Drivers fill the rest of the structure or return + an &EINVAL; if either the pad or + index are invalid. All media bus formats are + enumerable by beginning at index zero and incrementing by one until + EINVAL is returned. + + Available media bus formats may depend on the current 'try' formats + at other pads of the sub-device, as well as on the current active links. See + &VIDIOC-SUBDEV-G-FMT; for more information about the try formats. + + + struct <structname>v4l2_subdev_mbus_code_enum</structname> + + &cs-str; + + + __u32 + pad + Pad number as reported by the media controller API. + + + __u32 + index + Number of the format in the enumeration, set by the + application. + + + __u32 + code + The media bus format code, as defined in + . + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EINVAL + + The &v4l2-subdev-mbus-code-enum; pad + references a non-existing pad, or the index + field is out of bounds. + + + + +
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml new file mode 100644 index 00000000000..f367c570c53 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml @@ -0,0 +1,180 @@ + + + ioctl VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT + &manvol; + + + + VIDIOC_SUBDEV_G_FMT + VIDIOC_SUBDEV_S_FMT + Get or set the data format on a subdev pad + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_format *argp + + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + These ioctls are used to negotiate the frame format at specific + subdev pads in the image pipeline. + + To retrieve the current format applications set the + pad field of a &v4l2-subdev-format; to the + desired pad number as reported by the media API and the + which field to + V4L2_SUBDEV_FORMAT_ACTIVE. When they call the + VIDIOC_SUBDEV_G_FMT ioctl with a pointer to this + structure the driver fills the members of the format + field. + + To change the current format applications set both the + pad and which fields + and all members of the format field. When they + call the VIDIOC_SUBDEV_S_FMT ioctl with a pointer to this + structure the driver verifies the requested format, adjusts it based on the + hardware capabilities and configures the device. Upon return the + &v4l2-subdev-format; contains the current format as would be returned by a + VIDIOC_SUBDEV_G_FMT call. + + Applications can query the device capabilities by setting the + which to + V4L2_SUBDEV_FORMAT_TRY. When set, 'try' formats are not + applied to the device by the driver, but are changed exactly as active + formats and stored in the sub-device file handle. Two applications querying + the same sub-device would thus not interact with each other. + + For instance, to try a format at the output pad of a sub-device, + applications would first set the try format at the sub-device input with the + VIDIOC_SUBDEV_S_FMT ioctl. They would then either + retrieve the default format at the output pad with the + VIDIOC_SUBDEV_G_FMT ioctl, or set the desired output + pad format with the VIDIOC_SUBDEV_S_FMT ioctl and check + the returned value. + + Try formats do not depend on active formats, but can depend on the + current links configuration or sub-device controls value. For instance, a + low-pass noise filter might crop pixels at the frame boundaries, modifying + its output frame size. + + Drivers must not return an error solely because the requested format + doesn't match the device capabilities. They must instead modify the format + to match what the hardware can provide. The modified format should be as + close as possible to the original request. + + + struct <structname>v4l2_subdev_format</structname> + + &cs-str; + + + __u32 + pad + Pad number as reported by the media controller API. + + + __u32 + which + Format to modified, from &v4l2-subdev-format-whence;. + + + &v4l2-mbus-framefmt; + format + Definition of an image format, see for details. + + + __u32 + reserved[8] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+ + + enum <structname>v4l2_subdev_format_whence</structname> + + &cs-def; + + + V4L2_SUBDEV_FORMAT_TRY + 0 + Try formats, used for querying device capabilities. + + + V4L2_SUBDEV_FORMAT_ACTIVE + 1 + Active formats, applied to the hardware. + + + +
+
+ + + &return-value; + + + + EBUSY + + The format can't be changed because the pad is currently busy. + This can be caused, for instance, by an active video stream on the + pad. The ioctl must not be retried without performing another action + to fix the problem first. Only returned by + VIDIOC_SUBDEV_S_FMT + + + + EINVAL + + The &v4l2-subdev-format; pad + references a non-existing pad, or the which + field references a non-existing format. + + + + +
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index bc763db385d..207cc5cceb2 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -149,6 +149,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); struct v4l2_fh *vfh = file->private_data; +#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); +#endif switch (cmd) { case VIDIOC_QUERYCTRL: @@ -183,7 +186,53 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_UNSUBSCRIBE_EVENT: return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg); +#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + case VIDIOC_SUBDEV_G_FMT: { + struct v4l2_subdev_format *format = arg; + + if (format->which != V4L2_SUBDEV_FORMAT_TRY && + format->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (format->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format); + } + + case VIDIOC_SUBDEV_S_FMT: { + struct v4l2_subdev_format *format = arg; + + if (format->which != V4L2_SUBDEV_FORMAT_TRY && + format->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (format->pad >= sd->entity.num_pads) + return -EINVAL; + return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format); + } + + case VIDIOC_SUBDEV_ENUM_MBUS_CODE: { + struct v4l2_subdev_mbus_code_enum *code = arg; + + if (code->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh, + code); + } + + case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: { + struct v4l2_subdev_frame_size_enum *fse = arg; + + if (fse->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh, + fse); + } +#endif default: return -ENOIOCTLCMD; } diff --git a/include/linux/Kbuild b/include/linux/Kbuild index c33f22a6a40..43918a34db9 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -372,6 +372,7 @@ header-y += usbdevice_fs.h header-y += utime.h header-y += utsname.h header-y += v4l2-mediabus.h +header-y += v4l2-subdev.h header-y += veth.h header-y += vhost.h header-y += videodev2.h diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h new file mode 100644 index 00000000000..8dbb4487382 --- /dev/null +++ b/include/linux/v4l2-subdev.h @@ -0,0 +1,90 @@ +/* + * V4L2 subdev userspace API + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_V4L2_SUBDEV_H +#define __LINUX_V4L2_SUBDEV_H + +#include +#include +#include + +/** + * enum v4l2_subdev_format_whence - Media bus format type + * @V4L2_SUBDEV_FORMAT_TRY: try format, for negotiation only + * @V4L2_SUBDEV_FORMAT_ACTIVE: active format, applied to the device + */ +enum v4l2_subdev_format_whence { + V4L2_SUBDEV_FORMAT_TRY = 0, + V4L2_SUBDEV_FORMAT_ACTIVE = 1, +}; + +/** + * struct v4l2_subdev_format - Pad-level media bus format + * @which: format type (from enum v4l2_subdev_format_whence) + * @pad: pad number, as reported by the media API + * @format: media bus format (format code and frame size) + */ +struct v4l2_subdev_format { + __u32 which; + __u32 pad; + struct v4l2_mbus_framefmt format; + __u32 reserved[8]; +}; + +/** + * struct v4l2_subdev_mbus_code_enum - Media bus format enumeration + * @pad: pad number, as reported by the media API + * @index: format index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + */ +struct v4l2_subdev_mbus_code_enum { + __u32 pad; + __u32 index; + __u32 code; + __u32 reserved[9]; +}; + +/** + * struct v4l2_subdev_frame_size_enum - Media bus format enumeration + * @pad: pad number, as reported by the media API + * @index: format index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + */ +struct v4l2_subdev_frame_size_enum { + __u32 index; + __u32 pad; + __u32 code; + __u32 min_width; + __u32 max_width; + __u32 min_height; + __u32 max_height; + __u32 reserved[9]; +}; + +#define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_ENUM_MBUS_CODE \ + _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum) +#define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \ + _IOWR('V', 74, struct v4l2_subdev_frame_size_enum) + +#endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index d4d3653426a..4215650151b 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -21,6 +21,7 @@ #ifndef _V4L2_SUBDEV_H #define _V4L2_SUBDEV_H +#include #include #include #include @@ -414,6 +415,15 @@ struct v4l2_subdev_ir_ops { }; struct v4l2_subdev_pad_ops { + int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code); + int (*enum_frame_size)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse); + int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *format); + int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *format); }; struct v4l2_subdev_ops { -- cgit v1.2.3-70-g09d2 From 35c3017a29d278c4405a7f3ab30b814999d156d3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 5 May 2010 11:38:35 -0300 Subject: [media] v4l: v4l2_subdev userspace frame interval API The three new ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, VIDIOC_SUBDEV_G_FRAME_INTERVAL and VIDIOC_SUBDEV_S_FRAME_INTERVAL can be used to enumerate and configure a subdev's frame rate from userspace. Two new video::g/s_frame_interval subdev operations are introduced to support those ioctls. The existing video::g/s_parm operations are deprecated and shouldn't be used anymore. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 6 + Documentation/DocBook/v4l/v4l2.xml | 2 + .../v4l/vidioc-subdev-enum-frame-interval.xml | 152 +++++++++++++++++++++ .../DocBook/v4l/vidioc-subdev-g-frame-interval.xml | 141 +++++++++++++++++++ drivers/media/video/v4l2-subdev.c | 16 +++ include/linux/v4l2-subdev.h | 36 +++++ include/media/v4l2-subdev.h | 7 + 7 files changed, 360 insertions(+) create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml (limited to 'Documentation') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index dbb9cb2e1ec..a95eb578376 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -89,7 +89,9 @@ VIDIOC_SUBDEV_ENUM_FRAME_SIZE"> VIDIOC_SUBDEV_ENUM_MBUS_CODE"> VIDIOC_SUBDEV_G_FMT"> +VIDIOC_SUBDEV_G_FRAME_INTERVAL"> VIDIOC_SUBDEV_S_FMT"> +VIDIOC_SUBDEV_S_FRAME_INTERVAL"> VIDIOC_TRY_ENCODER_CMD"> VIDIOC_TRY_EXT_CTRLS"> VIDIOC_TRY_FMT"> @@ -193,6 +195,8 @@ v4l2_sliced_vbi_cap"> v4l2_sliced_vbi_data"> v4l2_sliced_vbi_format"> +v4l2_subdev_frame_interval"> +v4l2_subdev_frame_interval_enum"> v4l2_subdev_frame_size_enum"> v4l2_subdev_format"> v4l2_subdev_mbus_code_enum"> @@ -331,10 +335,12 @@ + + diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 2ada2f86bb5..a436716ef3b 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -507,9 +507,11 @@ and discussions on the V4L mailing list. &sub-reqbufs; &sub-s-hw-freq-seek; &sub-streamon; + &sub-subdev-enum-frame-interval; &sub-subdev-enum-frame-size; &sub-subdev-enum-mbus-code; &sub-subdev-g-fmt; + &sub-subdev-g-frame-interval; &sub-subscribe-event; &sub-mmap; diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml new file mode 100644 index 00000000000..2f8f4f0a023 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml @@ -0,0 +1,152 @@ + + + ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL + &manvol; + + + + VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL + Enumerate frame intervals + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_frame_interval_enum * + argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + This ioctl lets applications enumerate available frame intervals on a + given sub-device pad. Frame intervals only makes sense for sub-devices that + can control the frame period on their own. This includes, for instance, + image sensors and TV tuners. + + For the common use case of image sensors, the frame intervals + available on the sub-device output pad depend on the frame format and size + on the same pad. Applications must thus specify the desired format and size + when enumerating frame intervals. + + To enumerate frame intervals applications initialize the + index, pad, + code, width and + height fields of + &v4l2-subdev-frame-interval-enum; and call the + VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL ioctl with a pointer + to this structure. Drivers fill the rest of the structure or return + an &EINVAL; if one of the input fields is invalid. All frame intervals are + enumerable by beginning at index zero and incrementing by one until + EINVAL is returned. + + Available frame intervals may depend on the current 'try' formats + at other pads of the sub-device, as well as on the current active links. See + &VIDIOC-SUBDEV-G-FMT; for more information about the try formats. + + Sub-devices that support the frame interval enumeration ioctl should + implemented it on a single pad only. Its behaviour when supported on + multiple pads of the same sub-device is not defined. + + + struct <structname>v4l2_subdev_frame_interval_enum</structname> + + &cs-str; + + + __u32 + index + Number of the format in the enumeration, set by the + application. + + + __u32 + pad + Pad number as reported by the media controller API. + + + __u32 + code + The media bus format code, as defined in + . + + + __u32 + width + Frame width, in pixels. + + + __u32 + height + Frame height, in pixels. + + + &v4l2-fract; + interval + Period, in seconds, between consecutive video frames. + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EINVAL + + The &v4l2-subdev-frame-interval-enum; + pad references a non-existing pad, one of + the code, width + or height fields are invalid for the given + pad or the index field is out of bounds. + + + + + +
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml new file mode 100644 index 00000000000..0bc3ea22d31 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml @@ -0,0 +1,141 @@ + + + ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL + &manvol; + + + + VIDIOC_SUBDEV_G_FRAME_INTERVAL + VIDIOC_SUBDEV_S_FRAME_INTERVAL + Get or set the frame interval on a subdev pad + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_frame_interval *argp + + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + These ioctls are used to get and set the frame interval at specific + subdev pads in the image pipeline. The frame interval only makes sense for + sub-devices that can control the frame period on their own. This includes, + for instance, image sensors and TV tuners. Sub-devices that don't support + frame intervals must not implement these ioctls. + + To retrieve the current frame interval applications set the + pad field of a &v4l2-subdev-frame-interval; to + the desired pad number as reported by the media controller API. When they + call the VIDIOC_SUBDEV_G_FRAME_INTERVAL ioctl with a + pointer to this structure the driver fills the members of the + interval field. + + To change the current frame interval applications set both the + pad field and all members of the + interval field. When they call the + VIDIOC_SUBDEV_S_FRAME_INTERVAL ioctl with a pointer to + this structure the driver verifies the requested interval, adjusts it based + on the hardware capabilities and configures the device. Upon return the + &v4l2-subdev-frame-interval; contains the current frame interval as would be + returned by a VIDIOC_SUBDEV_G_FRAME_INTERVAL call. + + + Drivers must not return an error solely because the requested interval + doesn't match the device capabilities. They must instead modify the interval + to match what the hardware can provide. The modified interval should be as + close as possible to the original request. + + Sub-devices that support the frame interval ioctls should implement + them on a single pad only. Their behaviour when supported on multiple pads + of the same sub-device is not defined. + + + struct <structname>v4l2_subdev_frame_interval</structname> + + &cs-str; + + + __u32 + pad + Pad number as reported by the media controller API. + + + &v4l2-fract; + interval + Period, in seconds, between consecutive video frames. + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EBUSY + + The frame interval can't be changed because the pad is currently + busy. This can be caused, for instance, by an active video stream on + the pad. The ioctl must not be retried without performing another + action to fix the problem first. Only returned by + VIDIOC_SUBDEV_S_FRAME_INTERVAL + + + + EINVAL + + The &v4l2-subdev-frame-interval; pad + references a non-existing pad, or the pad doesn't support frame + intervals. + + + + +
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 207cc5cceb2..a4a12563ec3 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -232,6 +232,22 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh, fse); } + + case VIDIOC_SUBDEV_G_FRAME_INTERVAL: + return v4l2_subdev_call(sd, video, g_frame_interval, arg); + + case VIDIOC_SUBDEV_S_FRAME_INTERVAL: + return v4l2_subdev_call(sd, video, s_frame_interval, arg); + + case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: { + struct v4l2_subdev_frame_interval_enum *fie = arg; + + if (fie->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh, + fie); + } #endif default: return -ENOIOCTLCMD; diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index 8dbb4487382..c55f9e9e1dd 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -80,11 +80,47 @@ struct v4l2_subdev_frame_size_enum { __u32 reserved[9]; }; +/** + * struct v4l2_subdev_frame_interval - Pad-level frame rate + * @pad: pad number, as reported by the media API + * @interval: frame interval in seconds + */ +struct v4l2_subdev_frame_interval { + __u32 pad; + struct v4l2_fract interval; + __u32 reserved[9]; +}; + +/** + * struct v4l2_subdev_frame_interval_enum - Frame interval enumeration + * @pad: pad number, as reported by the media API + * @index: frame interval index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + * @width: frame width in pixels + * @height: frame height in pixels + * @interval: frame interval in seconds + */ +struct v4l2_subdev_frame_interval_enum { + __u32 index; + __u32 pad; + __u32 code; + __u32 width; + __u32 height; + struct v4l2_fract interval; + __u32 reserved[9]; +}; + #define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format) #define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_G_FRAME_INTERVAL \ + _IOWR('V', 21, struct v4l2_subdev_frame_interval) +#define VIDIOC_SUBDEV_S_FRAME_INTERVAL \ + _IOWR('V', 22, struct v4l2_subdev_frame_interval) #define VIDIOC_SUBDEV_ENUM_MBUS_CODE \ _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum) #define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \ _IOWR('V', 74, struct v4l2_subdev_frame_size_enum) +#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \ + _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum) #endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 4215650151b..8b7a78a013c 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -268,6 +268,10 @@ struct v4l2_subdev_video_ops { int (*s_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop); int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); + int (*g_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval); + int (*s_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval); int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival); int (*enum_dv_presets) (struct v4l2_subdev *sd, @@ -420,6 +424,9 @@ struct v4l2_subdev_pad_ops { int (*enum_frame_size)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_frame_size_enum *fse); + int (*enum_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_interval_enum *fie); int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format); int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, -- cgit v1.2.3-70-g09d2 From f6a5cb1be894468cdc69ec557d47f40c28f64642 Mon Sep 17 00:00:00 2001 From: Antti Koskipaa Date: Wed, 23 Jun 2010 05:03:42 -0300 Subject: [media] v4l: v4l2_subdev userspace crop API This patch adds the VIDIOC_SUBDEV_S_CROP and G_CROP ioctls to the userland API. CROPCAP is not implemented because it's redundant. Signed-off-by: Antti Koskipaa Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 4 + Documentation/DocBook/v4l/dev-subdev.xml | 33 +++++ Documentation/DocBook/v4l/v4l2.xml | 1 + Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml | 155 +++++++++++++++++++++ drivers/media/video/v4l2-subdev.c | 26 ++++ include/linux/v4l2-subdev.h | 15 ++ include/media/v4l2-subdev.h | 4 + 7 files changed, 238 insertions(+) create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml (limited to 'Documentation') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index a95eb578376..40158ee3d36 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -88,8 +88,10 @@ VIDIOC_S_TUNER"> VIDIOC_SUBDEV_ENUM_FRAME_SIZE"> VIDIOC_SUBDEV_ENUM_MBUS_CODE"> +VIDIOC_SUBDEV_G_CROP"> VIDIOC_SUBDEV_G_FMT"> VIDIOC_SUBDEV_G_FRAME_INTERVAL"> +VIDIOC_SUBDEV_S_CROP"> VIDIOC_SUBDEV_S_FMT"> VIDIOC_SUBDEV_S_FRAME_INTERVAL"> VIDIOC_TRY_ENCODER_CMD"> @@ -198,6 +200,7 @@ v4l2_subdev_frame_interval"> v4l2_subdev_frame_interval_enum"> v4l2_subdev_frame_size_enum"> +v4l2_subdev_crop"> v4l2_subdev_format"> v4l2_subdev_mbus_code_enum"> v4l2_standard"> @@ -339,6 +342,7 @@ + diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml index fc62e65f45e..e9eb8af0f30 100644 --- a/Documentation/DocBook/v4l/dev-subdev.xml +++ b/Documentation/DocBook/v4l/dev-subdev.xml @@ -275,6 +275,39 @@ +
+ Cropping and scaling + + Many sub-devices support cropping frames on their input or output + pads (or possible even on both). Cropping is used to select the area of + interest in an image, typically on a video sensor or video decoder. It can + also be used as part of digital zoom implementations to select the area of + the image that will be scaled up. + + Crop settings are defined by a crop rectangle and represented in a + &v4l2-rect; by the coordinates of the top left corner and the rectangle + size. Both the coordinates and sizes are expressed in pixels. + + The crop rectangle is retrieved and set using the + &VIDIOC-SUBDEV-G-CROP; and &VIDIOC-SUBDEV-S-CROP; ioctls. Like for pad + formats, drivers store try and active crop rectangles. The format + negotiation mechanism applies to crop settings as well. + + On input pads, cropping is applied relatively to the current pad + format. The pad format represents the image size as received by the + sub-device from the previous block in the pipeline, and the crop rectangle + represents the sub-image that will be transmitted further inside the + sub-device for processing. The crop rectangle be entirely containted + inside the input image size. + + Input crop rectangle are reset to their default value when the input + image format is modified. Drivers should use the input image size as the + crop rectangle default value, but hardware requirements may prevent this. + + + Cropping behaviour on output pads is not defined. + +
&sub-subdev-formats; diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index a436716ef3b..3a6e3b5c094 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -510,6 +510,7 @@ and discussions on the V4L mailing list. &sub-subdev-enum-frame-interval; &sub-subdev-enum-frame-size; &sub-subdev-enum-mbus-code; + &sub-subdev-g-crop; &sub-subdev-g-fmt; &sub-subdev-g-frame-interval; &sub-subscribe-event; diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml new file mode 100644 index 00000000000..06197323a8c --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml @@ -0,0 +1,155 @@ + + + ioctl VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP + &manvol; + + + + VIDIOC_SUBDEV_G_CROP + VIDIOC_SUBDEV_S_CROP + Get or set the crop rectangle on a subdev pad + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_crop *argp + + + + + int ioctl + int fd + int request + const struct v4l2_subdev_crop *argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + To retrieve the current crop rectangle applications set the + pad field of a &v4l2-subdev-crop; to the + desired pad number as reported by the media API and the + which field to + V4L2_SUBDEV_FORMAT_ACTIVE. They then call the + VIDIOC_SUBDEV_G_CROP ioctl with a pointer to this + structure. The driver fills the members of the rect + field or returns &EINVAL; if the input arguments are invalid, or if cropping + is not supported on the given pad. + + To change the current crop rectangle applications set both the + pad and which fields + and all members of the rect field. They then call + the VIDIOC_SUBDEV_S_CROP ioctl with a pointer to this + structure. The driver verifies the requested crop rectangle, adjusts it + based on the hardware capabilities and configures the device. Upon return + the &v4l2-subdev-crop; contains the current format as would be returned + by a VIDIOC_SUBDEV_G_CROP call. + + Applications can query the device capabilities by setting the + which to + V4L2_SUBDEV_FORMAT_TRY. When set, 'try' crop + rectangles are not applied to the device by the driver, but are mangled + exactly as active crop rectangles and stored in the sub-device file handle. + Two applications querying the same sub-device would thus not interact with + each other. + + Drivers must not return an error solely because the requested crop + rectangle doesn't match the device capabilities. They must instead modify + the rectangle to match what the hardware can provide. The modified format + should be as close as possible to the original request. + + + struct <structname>v4l2_subdev_crop</structname> + + &cs-str; + + + __u32 + pad + Pad number as reported by the media framework. + + + __u32 + which + Crop rectangle to get or set, from + &v4l2-subdev-format-whence;. + + + &v4l2-rect; + rect + Crop rectangle boundaries, in pixels. + + + __u32 + reserved[8] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EBUSY + + The crop rectangle can't be changed because the pad is currently + busy. This can be caused, for instance, by an active video stream on + the pad. The ioctl must not be retried without performing another + action to fix the problem first. Only returned by + VIDIOC_SUBDEV_S_CROP + + + + EINVAL + + The &v4l2-subdev-crop; pad + references a non-existing pad, the which + field references a non-existing format, or cropping is not supported + on the given subdev pad. + + + + +
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index a4a12563ec3..6e76f734c78 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -213,6 +213,32 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format); } + case VIDIOC_SUBDEV_G_CROP: { + struct v4l2_subdev_crop *crop = arg; + + if (crop->which != V4L2_SUBDEV_FORMAT_TRY && + crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (crop->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop); + } + + case VIDIOC_SUBDEV_S_CROP: { + struct v4l2_subdev_crop *crop = arg; + + if (crop->which != V4L2_SUBDEV_FORMAT_TRY && + crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (crop->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop); + } + case VIDIOC_SUBDEV_ENUM_MBUS_CODE: { struct v4l2_subdev_mbus_code_enum *code = arg; diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index c55f9e9e1dd..ed29cbbebfe 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -50,6 +50,19 @@ struct v4l2_subdev_format { __u32 reserved[8]; }; +/** + * struct v4l2_subdev_crop - Pad-level crop settings + * @which: format type (from enum v4l2_subdev_format_whence) + * @pad: pad number, as reported by the media API + * @rect: pad crop rectangle boundaries + */ +struct v4l2_subdev_crop { + __u32 which; + __u32 pad; + struct v4l2_rect rect; + __u32 reserved[8]; +}; + /** * struct v4l2_subdev_mbus_code_enum - Media bus format enumeration * @pad: pad number, as reported by the media API @@ -122,5 +135,7 @@ struct v4l2_subdev_frame_interval_enum { _IOWR('V', 74, struct v4l2_subdev_frame_size_enum) #define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \ _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum) +#define VIDIOC_SUBDEV_G_CROP _IOWR('V', 59, struct v4l2_subdev_crop) +#define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop) #endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 8b7a78a013c..edeaf398d48 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -431,6 +431,10 @@ struct v4l2_subdev_pad_ops { struct v4l2_subdev_format *format); int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format); + int (*set_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_crop *crop); + int (*get_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_crop *crop); }; struct v4l2_subdev_ops { -- cgit v1.2.3-70-g09d2 From 7140c55738561907a1f66abf533d6358bf69ed9f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 23 Dec 2010 11:14:49 -0300 Subject: [media] v4l: Add missing 12 bits bayer media bus formats Add codes and documentation for the following media bus formats: - V4L2_MBUS_FMT_SGBRG12_1X12 - V4L2_MBUS_FMT_SGRBG12_1X12 - V4L2_MBUS_FMT_SRGGB12_1X12 Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/subdev-formats.xml | 51 ++++++++++++++++++++++++++++ include/linux/v4l2-mediabus.h | 5 ++- 2 files changed, 55 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/subdev-formats.xml b/Documentation/DocBook/v4l/subdev-formats.xml index 0cae5720700..b5376e263d1 100644 --- a/Documentation/DocBook/v4l/subdev-formats.xml +++ b/Documentation/DocBook/v4l/subdev-formats.xml @@ -762,6 +762,57 @@ b1 b0 + + V4L2_MBUS_FMT_SGBRG12_1X12 + 0x3010 + + g11 + g10 + g9 + g8 + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SGRBG12_1X12 + 0x3011 + + g11 + g10 + g9 + g8 + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SRGGB12_1X12 + 0x3012 + + r11 + r10 + r9 + r8 + r7 + r6 + r5 + r4 + r3 + r2 + r1 + r0 + diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h index 5c64924371d..7054a7a8065 100644 --- a/include/linux/v4l2-mediabus.h +++ b/include/linux/v4l2-mediabus.h @@ -67,7 +67,7 @@ enum v4l2_mbus_pixelcode { V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d, V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e, - /* Bayer - next is 0x3010 */ + /* Bayer - next is 0x3013 */ V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001, V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002, V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b, @@ -83,6 +83,9 @@ enum v4l2_mbus_pixelcode { V4L2_MBUS_FMT_SGRBG10_1X10 = 0x300a, V4L2_MBUS_FMT_SRGGB10_1X10 = 0x300f, V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008, + V4L2_MBUS_FMT_SGBRG12_1X12 = 0x3010, + V4L2_MBUS_FMT_SGRBG12_1X12 = 0x3011, + V4L2_MBUS_FMT_SRGGB12_1X12 = 0x3012, }; /** -- cgit v1.2.3-70-g09d2 From 39187e177dc6372a967aa17a49a79189dc4fa8de Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 23 Dec 2010 11:14:50 -0300 Subject: [media] v4l: Add 12 bits bayer pixel formats Add FCCs for the following pixel formats: - V4L2_PIX_FMT_SBGGR12 - V4L2_PIX_FMT_SGBRG12 - V4L2_PIX_FMT_SGRBG12 - V4L2_PIX_FMT_SRGGB12 Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/pixfmt-srggb12.xml | 90 ++++++++++++++++++++++++++++ include/linux/videodev2.h | 4 ++ 2 files changed, 94 insertions(+) create mode 100644 Documentation/DocBook/v4l/pixfmt-srggb12.xml (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/pixfmt-srggb12.xml b/Documentation/DocBook/v4l/pixfmt-srggb12.xml new file mode 100644 index 00000000000..9ba4fb690bc --- /dev/null +++ b/Documentation/DocBook/v4l/pixfmt-srggb12.xml @@ -0,0 +1,90 @@ + + + V4L2_PIX_FMT_SRGGB12 ('RG12'), + V4L2_PIX_FMT_SGRBG12 ('BA12'), + V4L2_PIX_FMT_SGBRG12 ('GB12'), + V4L2_PIX_FMT_SBGGR12 ('BG12'), + + &manvol; + + + V4L2_PIX_FMT_SRGGB12 + V4L2_PIX_FMT_SGRBG12 + V4L2_PIX_FMT_SGBRG12 + V4L2_PIX_FMT_SBGGR12 + 12-bit Bayer formats expanded to 16 bits + + + Description + + The following four pixel formats are raw sRGB / Bayer formats with +12 bits per colour. Each colour component is stored in a 16-bit word, with 6 +unused high bits filled with zeros. Each n-pixel row contains n/2 green samples +and n/2 blue or red samples, with alternating red and blue rows. Bytes are +stored in memory in little endian order. They are conventionally described +as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of one of these +formats + + + <constant>V4L2_PIX_FMT_SBGGR12</constant> 4 × 4 +pixel image + + + Byte Order. + Each cell is one byte, high 6 bits in high bytes are 0. + + + + + + start + 0: + B00low + B00high + G01low + G01high + B02low + B02high + G03low + G03high + + + start + 8: + G10low + G10high + R11low + R11high + G12low + G12high + R13low + R13high + + + start + 16: + B20low + B20high + G21low + G21high + B22low + B22high + G23low + G23high + + + start + 24: + G30low + G30high + R31low + R31high + G32low + G32high + R33low + R33high + + + + + + + + + diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a94c4d5ac34..8c80fd36da0 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -355,6 +355,10 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */ #define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */ #define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */ +#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12 RGRG.. GBGB.. */ /* 10bit raw bayer DPCM compressed to 8 bits */ #define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0') /* -- cgit v1.2.3-70-g09d2 From c30b46e58b31a0fc420049e21117444862fc7cb7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 26 Feb 2010 12:23:10 -0300 Subject: [media] v4l: subdev: Generic ioctl support Instead of returning an error when receiving an ioctl call with an unsupported command, forward the call to the subdev core::ioctl handler. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 5 +++++ drivers/media/video/v4l2-subdev.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 77d96f4e3f5..f2df31b088c 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -405,6 +405,11 @@ VIDIOC_UNSUBSCRIBE_EVENT To properly support events, the poll() file operation is also implemented. +Private ioctls + + All ioctls not in the above list are passed directly to the sub-device + driver through the core::ioctl operation. + I2C sub-device drivers ---------------------- diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 6e76f734c78..0b806449067 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -276,7 +276,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) } #endif default: - return -ENOIOCTLCMD; + return v4l2_subdev_call(sd, core, ioctl, cmd, arg); } return 0; -- cgit v1.2.3-70-g09d2 From 474966ee01cc877e28abed3ada5b48a963c58695 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 5 Mar 2011 17:14:33 -0300 Subject: [media] media: Pick a free ioctls range Pick an unused range of ioctls in Documentation/ioctl/ioctl-number.txt and use it for the MEDIA_IOC_* ioctls. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/ioctl/ioctl-number.txt | 1 + include/linux/media.h | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index ac293e95530..2b8c0592b51 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -272,6 +272,7 @@ Code Seq#(hex) Include File Comments 'z' 40-7F CAN bus card conflict! 'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict! +'|' 00-7F linux/media.h 0x80 00-1F linux/fb.h 0x89 00-06 arch/x86/include/asm/sockios.h 0x89 0B-DF linux/sockios.h diff --git a/include/linux/media.h b/include/linux/media.h index 7ed23b43f43..0ef883327de 100644 --- a/include/linux/media.h +++ b/include/linux/media.h @@ -124,9 +124,9 @@ struct media_links_enum { __u32 reserved[4]; }; -#define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info) -#define MEDIA_IOC_ENUM_ENTITIES _IOWR('M', 2, struct media_entity_desc) -#define MEDIA_IOC_ENUM_LINKS _IOWR('M', 3, struct media_links_enum) -#define MEDIA_IOC_SETUP_LINK _IOWR('M', 4, struct media_link_desc) +#define MEDIA_IOC_DEVICE_INFO _IOWR('|', 0x00, struct media_device_info) +#define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc) +#define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum) +#define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc) #endif /* __LINUX_MEDIA_H */ -- cgit v1.2.3-70-g09d2 From e83dd485ed04b21215c1283042e8d4712ab1a675 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 7 Mar 2011 14:20:52 -0300 Subject: [media] omap3isp: Add documentation Add documentation on the OMAP 3 ISP driver. Document the subdevs, V4L2 events and private IOCTLs the driver implements Signed-off-by: Sakari Ailus Signed-off-by: David Cohen Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/omap3isp.txt | 278 +++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 Documentation/video4linux/omap3isp.txt (limited to 'Documentation') diff --git a/Documentation/video4linux/omap3isp.txt b/Documentation/video4linux/omap3isp.txt new file mode 100644 index 00000000000..69be2c782b9 --- /dev/null +++ b/Documentation/video4linux/omap3isp.txt @@ -0,0 +1,278 @@ +OMAP 3 Image Signal Processor (ISP) driver + +Copyright (C) 2010 Nokia Corporation +Copyright (C) 2009 Texas Instruments, Inc. + +Contacts: Laurent Pinchart + Sakari Ailus + David Cohen + + +Introduction +============ + +This file documents the Texas Instruments OMAP 3 Image Signal Processor (ISP) +driver located under drivers/media/video/omap3isp. The original driver was +written by Texas Instruments but since that it has been rewritten (twice) at +Nokia. + +The driver has been successfully used on the following versions of OMAP 3: + + 3430 + 3530 + 3630 + +The driver implements V4L2, Media controller and v4l2_subdev interfaces. +Sensor, lens and flash drivers using the v4l2_subdev interface in the kernel +are supported. + + +Split to subdevs +================ + +The OMAP 3 ISP is split into V4L2 subdevs, each of the blocks inside the ISP +having one subdev to represent it. Each of the subdevs provide a V4L2 subdev +interface to userspace. + + OMAP3 ISP CCP2 + OMAP3 ISP CSI2a + OMAP3 ISP CCDC + OMAP3 ISP preview + OMAP3 ISP resizer + OMAP3 ISP AEWB + OMAP3 ISP AF + OMAP3 ISP histogram + +Each possible link in the ISP is modelled by a link in the Media controller +interface. For an example program see [2]. + + +Controlling the OMAP 3 ISP +========================== + +In general, the settings given to the OMAP 3 ISP take effect at the beginning +of the following frame. This is done when the module becomes idle during the +vertical blanking period on the sensor. In memory-to-memory operation the pipe +is run one frame at a time. Applying the settings is done between the frames. + +All the blocks in the ISP, excluding the CSI-2 and possibly the CCP2 receiver, +insist on receiving complete frames. Sensors must thus never send the ISP +partial frames. + +Autoidle does have issues with some ISP blocks on the 3430, at least. +Autoidle is only enabled on 3630 when the omap3isp module parameter autoidle +is non-zero. + + +Events +====== + +The OMAP 3 ISP driver does support the V4L2 event interface on CCDC and +statistics (AEWB, AF and histogram) subdevs. + +The CCDC subdev produces V4L2_EVENT_OMAP3ISP_HS_VS type event on HS_VS +interrupt which is used to signal frame start. The event is triggered exactly +when the reception of the first line of the frame starts in the CCDC module. +The event can be subscribed on the CCDC subdev. + +(When using parallel interface one must pay account to correct configuration +of the VS signal polarity. This is automatically correct when using the serial +receivers.) + +Each of the statistics subdevs is able to produce events. An event is +generated whenever a statistics buffer can be dequeued by a user space +application using the VIDIOC_OMAP3ISP_STAT_REQ IOCTL. The events available +are: + + V4L2_EVENT_OMAP3ISP_AEWB + V4L2_EVENT_OMAP3ISP_AF + V4L2_EVENT_OMAP3ISP_HIST + +The type of the event data is struct omap3isp_stat_event_status for these +ioctls. If there is an error calculating the statistics, there will be an +event as usual, but no related statistics buffer. In this case +omap3isp_stat_event_status.buf_err is set to non-zero. + + +Private IOCTLs +============== + +The OMAP 3 ISP driver supports standard V4L2 IOCTLs and controls where +possible and practical. Much of the functions provided by the ISP, however, +does not fall under the standard IOCTLs --- gamma tables and configuration of +statistics collection are examples of such. + +In general, there is a private ioctl for configuring each of the blocks +containing hardware-dependent functions. + +The following private IOCTLs are supported: + + VIDIOC_OMAP3ISP_CCDC_CFG + VIDIOC_OMAP3ISP_PRV_CFG + VIDIOC_OMAP3ISP_AEWB_CFG + VIDIOC_OMAP3ISP_HIST_CFG + VIDIOC_OMAP3ISP_AF_CFG + VIDIOC_OMAP3ISP_STAT_REQ + VIDIOC_OMAP3ISP_STAT_EN + +The parameter structures used by these ioctls are described in +include/linux/omap3isp.h. The detailed functions of the ISP itself related to +a given ISP block is described in the Technical Reference Manuals (TRMs) --- +see the end of the document for those. + +While it is possible to use the ISP driver without any use of these private +IOCTLs it is not possible to obtain optimal image quality this way. The AEWB, +AF and histogram modules cannot be used without configuring them using the +appropriate private IOCTLs. + + +CCDC and preview block IOCTLs +============================= + +The VIDIOC_OMAP3ISP_CCDC_CFG and VIDIOC_OMAP3ISP_PRV_CFG IOCTLs are used to +configure, enable and disable functions in the CCDC and preview blocks, +respectively. Both IOCTLs control several functions in the blocks they +control. VIDIOC_OMAP3ISP_CCDC_CFG IOCTL accepts a pointer to struct +omap3isp_ccdc_update_config as its argument. Similarly VIDIOC_OMAP3ISP_PRV_CFG +accepts a pointer to struct omap3isp_prev_update_config. The definition of +both structures is available in [1]. + +The update field in the structures tells whether to update the configuration +for the specific function and the flag tells whether to enable or disable the +function. + +The update and flag bit masks accept the following values. Each separate +functions in the CCDC and preview blocks is associated with a flag (either +disable or enable; part of the flag field in the structure) and a pointer to +configuration data for the function. + +Valid values for the update and flag fields are listed here for +VIDIOC_OMAP3ISP_CCDC_CFG. Values may be or'ed to configure more than one +function in the same IOCTL call. + + OMAP3ISP_CCDC_ALAW + OMAP3ISP_CCDC_LPF + OMAP3ISP_CCDC_BLCLAMP + OMAP3ISP_CCDC_BCOMP + OMAP3ISP_CCDC_FPC + OMAP3ISP_CCDC_CULL + OMAP3ISP_CCDC_CONFIG_LSC + OMAP3ISP_CCDC_TBL_LSC + +The corresponding values for the VIDIOC_OMAP3ISP_PRV_CFG are here: + + OMAP3ISP_PREV_LUMAENH + OMAP3ISP_PREV_INVALAW + OMAP3ISP_PREV_HRZ_MED + OMAP3ISP_PREV_CFA + OMAP3ISP_PREV_CHROMA_SUPP + OMAP3ISP_PREV_WB + OMAP3ISP_PREV_BLKADJ + OMAP3ISP_PREV_RGB2RGB + OMAP3ISP_PREV_COLOR_CONV + OMAP3ISP_PREV_YC_LIMIT + OMAP3ISP_PREV_DEFECT_COR + OMAP3ISP_PREV_GAMMABYPASS + OMAP3ISP_PREV_DRK_FRM_CAPTURE + OMAP3ISP_PREV_DRK_FRM_SUBTRACT + OMAP3ISP_PREV_LENS_SHADING + OMAP3ISP_PREV_NF + OMAP3ISP_PREV_GAMMA + +The associated configuration pointer for the function may not be NULL when +enabling the function. When disabling a function the configuration pointer is +ignored. + + +Statistic blocks IOCTLs +======================= + +The statistics subdevs do offer more dynamic configuration options than the +other subdevs. They can be enabled, disable and reconfigured when the pipeline +is in streaming state. + +The statistics blocks always get the input image data from the CCDC (as the +histogram memory read isn't implemented). The statistics are dequeueable by +the user from the statistics subdev nodes using private IOCTLs. + +The private IOCTLs offered by the AEWB, AF and histogram subdevs are heavily +reflected by the register level interface offered by the ISP hardware. There +are aspects that are purely related to the driver implementation and these are +discussed next. + +VIDIOC_OMAP3ISP_STAT_EN +----------------------- + +This private IOCTL enables/disables a statistic module. If this request is +done before streaming, it will take effect as soon as the pipeline starts to +stream. If the pipeline is already streaming, it will take effect as soon as +the CCDC becomes idle. + +VIDIOC_OMAP3ISP_AEWB_CFG, VIDIOC_OMAP3ISP_HIST_CFG and VIDIOC_OMAP3ISP_AF_CFG +----------------------------------------------------------------------------- + +Those IOCTLs are used to configure the modules. They require user applications +to have an in-depth knowledge of the hardware. Most of the fields explanation +can be found on OMAP's TRMs. The two following fields common to all the above +configure private IOCTLs require explanation for better understanding as they +are not part of the TRM. + +omap3isp_[h3a_af/h3a_aewb/hist]_config.buf_size: + +The modules handle their buffers internally. The necessary buffer size for the +module's data output depends on the requested configuration. Although the +driver supports reconfiguration while streaming, it does not support a +reconfiguration which requires bigger buffer size than what is already +internally allocated if the module is enabled. It will return -EBUSY on this +case. In order to avoid such condition, either disable/reconfigure/enable the +module or request the necessary buffer size during the first configuration +while the module is disabled. + +The internal buffer size allocation considers the requested configuration's +minimum buffer size and the value set on buf_size field. If buf_size field is +out of [minimum, maximum] buffer size range, it's clamped to fit in there. +The driver then selects the biggest value. The corrected buf_size value is +written back to user application. + +omap3isp_[h3a_af/h3a_aewb/hist]_config.config_counter: + +As the configuration doesn't take effect synchronously to the request, the +driver must provide a way to track this information to provide more accurate +data. After a configuration is requested, the config_counter returned to user +space application will be an unique value associated to that request. When +user application receives an event for buffer availability or when a new +buffer is requested, this config_counter is used to match a buffer data and a +configuration. + +VIDIOC_OMAP3ISP_STAT_REQ +------------------------ + +Send to user space the oldest data available in the internal buffer queue and +discards such buffer afterwards. The field omap3isp_stat_data.frame_number +matches with the video buffer's field_count. + + +Technical reference manuals (TRMs) and other documentation +========================================================== + +OMAP 3430 TRM: + +Referenced 2011-03-05. + +OMAP 35xx TRM: + Referenced 2011-03-05. + +OMAP 3630 TRM: + +Referenced 2011-03-05. + +DM 3730 TRM: + Referenced 2011-03-06. + + +References +========== + +[1] include/linux/omap3isp.h + +[2] http://git.ideasonboard.org/?p=media-ctl.git;a=summary -- cgit v1.2.3-70-g09d2 From bd08a0cd5f546916a9454ae2c35756ed77957458 Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Fri, 11 Mar 2011 06:16:22 -0300 Subject: [media] v4l: Documentation for the NV12MT format Added documentation for V4L2_PIX_FMT_NV12MT format. This is a YUV 4:2:0 format with macro block size of 64x32 and specific order of macro blocks in the memory. Signed-off-by: Kamil Debski Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 1 + Documentation/DocBook/v4l/nv12mt.gif | Bin 0 -> 2108 bytes Documentation/DocBook/v4l/nv12mt_example.gif | Bin 0 -> 6858 bytes Documentation/DocBook/v4l/pixfmt-nv12mt.xml | 74 +++++++++++++++++++++++++++ Documentation/DocBook/v4l/pixfmt.xml | 1 + 5 files changed, 76 insertions(+) create mode 100644 Documentation/DocBook/v4l/nv12mt.gif create mode 100644 Documentation/DocBook/v4l/nv12mt_example.gif create mode 100644 Documentation/DocBook/v4l/pixfmt-nv12mt.xml (limited to 'Documentation') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index 40158ee3d36..5d259c632cd 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -272,6 +272,7 @@ + diff --git a/Documentation/DocBook/v4l/nv12mt.gif b/Documentation/DocBook/v4l/nv12mt.gif new file mode 100644 index 00000000000..ef2d4cf8367 Binary files /dev/null and b/Documentation/DocBook/v4l/nv12mt.gif differ diff --git a/Documentation/DocBook/v4l/nv12mt_example.gif b/Documentation/DocBook/v4l/nv12mt_example.gif new file mode 100644 index 00000000000..df81d68108e Binary files /dev/null and b/Documentation/DocBook/v4l/nv12mt_example.gif differ diff --git a/Documentation/DocBook/v4l/pixfmt-nv12mt.xml b/Documentation/DocBook/v4l/pixfmt-nv12mt.xml new file mode 100644 index 00000000000..5cb5bec8b65 --- /dev/null +++ b/Documentation/DocBook/v4l/pixfmt-nv12mt.xml @@ -0,0 +1,74 @@ + + + V4L2_PIX_FMT_NV12MT ('TM12') + &manvol; + + + V4L2_PIX_FMT_NV12MT + + Formats with ½ horizontal and vertical +chroma resolution. This format has two planes - one for luminance and one for +chrominance. Chroma samples are interleaved. The difference to +V4L2_PIX_FMT_NV12 is the memory layout. Pixels are +grouped in macroblocks of 64x32 size. The order of macroblocks in memory is +also not standard. + + + + Description + + This is the two-plane versions of the YUV 4:2:0 format where data +is grouped into 64x32 macroblocks. The three components are separated into two +sub-images or planes. The Y plane has one byte per pixel and pixels are grouped +into 64x32 macroblocks. The CbCr plane has the same width, in bytes, as the Y +plane (and the image), but is half as tall in pixels. The chroma plane is also +grouped into 64x32 macroblocks. + Width of the buffer has to be aligned to the multiple of 128, and +height alignment is 32. Every four adjactent buffers - two horizontally and two +vertically are grouped together and are located in memory in Z or flipped Z +order. + Layout of macroblocks in memory is presented in the following +figure. +
+ <constant>V4L2_PIX_FMT_NV12MT</constant> macroblock Z shape +memory layout + + + + + +
+ The requirement that width is multiple of 128 is implemented because, +the Z shape cannot be cut in half horizontally. In case the vertical resolution +of macroblocks is odd then the last row of macroblocks is arranged in a linear +order.
+ In case of chroma the layout is identical. Cb and Cr samples are +interleaved. Height of the buffer is aligned to 32. + + + Memory layout of macroblocks in <constant>V4L2_PIX_FMT_NV12 +</constant> format pixel image - extreme case + +
+ Example <constant>V4L2_PIX_FMT_NV12MT</constant> memory +layout of macroblocks + + + + + +
+ Memory layout of macroblocks of V4L2_PIX_FMT_NV12MT + format in most extreme case. +
+
+
+
+ + diff --git a/Documentation/DocBook/v4l/pixfmt.xml b/Documentation/DocBook/v4l/pixfmt.xml index f8436dcb741..c6fdcbbd1b4 100644 --- a/Documentation/DocBook/v4l/pixfmt.xml +++ b/Documentation/DocBook/v4l/pixfmt.xml @@ -709,6 +709,7 @@ information. &sub-yuv411p; &sub-nv12; &sub-nv12m; + &sub-nv12mt; &sub-nv16; -- cgit v1.2.3-70-g09d2 From 665bf368fdc1e7afc9616eda128fe83d6053d5bc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 Mar 2011 16:22:21 -0300 Subject: [media] V4L doc fixes The xmlto validation produced a number of errors that are now fixed. Sadly, the DocBook/Makefile still adds --skip-validation to xmlto, so these errors are missed during a normal compile. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/dev-subdev.xml | 46 ++++++++-------- .../DocBook/v4l/media-ioc-enum-entities.xml | 6 +- Documentation/DocBook/v4l/subdev-formats.xml | 64 +++++++++++----------- 3 files changed, 58 insertions(+), 58 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml index e9eb8af0f30..21caff6d159 100644 --- a/Documentation/DocBook/v4l/dev-subdev.xml +++ b/Documentation/DocBook/v4l/dev-subdev.xml @@ -23,9 +23,9 @@ driver and the V4L2 device driver support this, sub-devices will feature a character device node on which ioctls can be called to - query, read and write sub-devices controls - subscribe and unsubscribe to events and retrieve them - negotiate image formats on individual pads + query, read and write sub-devices controls + subscribe and unsubscribe to events and retrieve them + negotiate image formats on individual pads @@ -67,14 +67,14 @@
Pad-level Formats - Pad-level formats are only applicable to very complex device that + Pad-level formats are only applicable to very complex device that need to expose low-level format configuration to user space. Generic V4L2 applications do not need to use the API described in - this section. + this section. - For the purpose of this section, the term + For the purpose of this section, the term format means the combination of media bus data - format, frame width and frame height. + format, frame width and frame height. Image formats are typically negotiated on video capture and output devices using the cropping and scaling ioctls. @@ -84,8 +84,8 @@ For complex devices, such as often found in embedded systems, identical image sizes at the output of a pipeline can be achieved using - different hardware configurations. One such exemple is shown on - , where + different hardware configurations. One such example is shown on + , where image scaling can be performed on both the video sensor and the host image processing hardware. @@ -168,13 +168,13 @@ modify formats as required by the device. However, they should comply with the following rules when possible: - Formats should be propagated from sink pads to source pads. + Formats should be propagated from sink pads to source pads. Modifying a format on a source pad should not modify the format on any - sink pad. - Sub-devices that scale frames using variable scaling factors + sink pad. + Sub-devices that scale frames using variable scaling factors should reset the scale factors to default values when sink pads formats are modified. If the 1:1 scaling ratio is supported, this means that - source pads formats should be reset to the sink pads formats. + source pads formats should be reset to the sink pads formats. @@ -185,9 +185,9 @@ guaranteed to be compatible. Drivers are free to accept different formats matching device requirements as being compatible. - + shows a sample configuration sequence for the pipeline described in - (table + (table columns list entity names and pad numbers). @@ -248,19 +248,19 @@ - Initial state. The sensor output is set to its native 3MP + Initial state. The sensor output is set to its native 3MP resolution. Resolutions on the host frontend and scaler input and output - pads are undefined. - The application configures the frontend input pad resolution to + pads are undefined. + The application configures the frontend input pad resolution to 2048x1536. The driver propagates the format to the frontend output pad. Note that the propagated output format can be different, as in this case, than the input format, as the hardware might need to crop pixels (for - instance when converting a Bayer filter pattern to RGB or YUV). - The application configures the scaler input pad resolution to + instance when converting a Bayer filter pattern to RGB or YUV). + The application configures the scaler input pad resolution to 2046x1534 to match the frontend output resolution. The driver propagates - the format to the scaler output pad. - The application configures the scaler output pad resolution to - 1280x960. + the format to the scaler output pad. + The application configures the scaler output pad resolution to + 1280x960. diff --git a/Documentation/DocBook/v4l/media-ioc-enum-entities.xml b/Documentation/DocBook/v4l/media-ioc-enum-entities.xml index 13d0cc44865..576b68b33f2 100644 --- a/Documentation/DocBook/v4l/media-ioc-enum-entities.xml +++ b/Documentation/DocBook/v4l/media-ioc-enum-entities.xml @@ -63,9 +63,9 @@ group_id value are considered as logically grouped. Groups are used to report - ALSA, VBI and video nodes that carry the same media - stream - lens and flash controllers associated with a sensor + ALSA, VBI and video nodes that carry the same media + stream + lens and flash controllers associated with a sensor diff --git a/Documentation/DocBook/v4l/subdev-formats.xml b/Documentation/DocBook/v4l/subdev-formats.xml index b5376e263d1..7041127d6df 100644 --- a/Documentation/DocBook/v4l/subdev-formats.xml +++ b/Documentation/DocBook/v4l/subdev-formats.xml @@ -63,22 +63,22 @@ Those formats transfer pixel data as red, green and blue components. The format code is made of the following information. - The red, green and blue components order code, as encoded in a - pixel sample. Possible values are RGB and BGR. - The number of bits per component, for each component. The values - can be different for all components. Common values are 555 and 565. + The red, green and blue components order code, as encoded in a + pixel sample. Possible values are RGB and BGR. + The number of bits per component, for each component. The values + can be different for all components. Common values are 555 and 565. - The number of bus samples per pixel. Pixels that are wider than + The number of bus samples per pixel. Pixels that are wider than the bus width must be transferred in multiple samples. Common values are - 1 and 2. - The bus width. - For formats where the total number of bits per pixel is smaller + 1 and 2. + The bus width. + For formats where the total number of bits per pixel is smaller than the number of bus samples per pixel times the bus width, a padding value stating if the bytes are padded in their most high order bits - (PADHI) or low order bits (PADLO). - For formats where the number of bus samples per pixel is larger + (PADHI) or low order bits (PADLO). + For formats where the number of bus samples per pixel is larger than 1, an endianness value stating if the pixel is transferred MSB first - (BE) or LSB first (LE). + (BE) or LSB first (LE). @@ -347,26 +347,26 @@ Those formats transfer pixel data as red, green and blue components. The format code is made of the following information. - The red, green and blue components order code, as encoded in a + The red, green and blue components order code, as encoded in a pixel sample. The possible values are shown in . - The number of bits per pixel component. All components are - transferred on the same number of bits. Common values are 8, 10 and 12. + linkend="bayer-patterns" />. + The number of bits per pixel component. All components are + transferred on the same number of bits. Common values are 8, 10 and 12. - If the pixel components are DPCM-compressed, a mention of the - DPCM compression and the number of bits per compressed pixel component. + If the pixel components are DPCM-compressed, a mention of the + DPCM compression and the number of bits per compressed pixel component. - The number of bus samples per pixel. Pixels that are wider than + The number of bus samples per pixel. Pixels that are wider than the bus width must be transferred in multiple samples. Common values are - 1 and 2. - The bus width. - For formats where the total number of bits per pixel is smaller + 1 and 2. + The bus width. + For formats where the total number of bits per pixel is smaller than the number of bus samples per pixel times the bus width, a padding value stating if the bytes are padded in their most high order bits - (PADHI) or low order bits (PADLO). - For formats where the number of bus samples per pixel is larger + (PADHI) or low order bits (PADLO). + For formats where the number of bus samples per pixel is larger than 1, an endianness value stating if the pixel is transferred MSB first - (BE) or LSB first (LE). + (BE) or LSB first (LE). @@ -824,19 +824,19 @@ Those data formats transfer pixel data as (possibly downsampled) Y, U and V components. The format code is made of the following information. - The Y, U and V components order code, as transferred on the - bus. Possible values are YUYV, UYVY, YVYU and VYUY. - The number of bits per pixel component. All components are - transferred on the same number of bits. Common values are 8, 10 and 12. + The Y, U and V components order code, as transferred on the + bus. Possible values are YUYV, UYVY, YVYU and VYUY. + The number of bits per pixel component. All components are + transferred on the same number of bits. Common values are 8, 10 and 12. - The number of bus samples per pixel. Pixels that are wider than + The number of bus samples per pixel. Pixels that are wider than the bus width must be transferred in multiple samples. Common values are - 1, 1.5 (encoded as 1_5) and 2. - The bus width. When the bus width is larger than the number of + 1, 1.5 (encoded as 1_5) and 2. + The bus width. When the bus width is larger than the number of bits per pixel component, several components are packed in a single bus sample. The components are ordered as specified by the order code, with components on the left of the code transferred in the high order bits. - Common values are 8 and 16. + Common values are 8 and 16. -- cgit v1.2.3-70-g09d2 From 6e5b55fbdab3845bfb328f986f58e85d43cee59e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 Mar 2011 16:25:23 -0300 Subject: [media] V4L DocBook: update V4L2 version Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/v4l2.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 3a6e3b5c094..ae7a069d61d 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -410,7 +410,7 @@ and discussions on the V4L mailing list. Video for Linux Two API Specification - Revision 2.6.38 + Revision 2.6.39 &sub-common; -- cgit v1.2.3-70-g09d2 From 34fd68bc03c8d656f991bd4f1646ec773179521b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 11 Mar 2011 18:18:54 -0300 Subject: [media] Fix 'ID nv12mt already defined' error DocBook validation fix. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/pixfmt-nv12mt.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/pixfmt-nv12mt.xml b/Documentation/DocBook/v4l/pixfmt-nv12mt.xml index 5cb5bec8b65..7a2855a526c 100644 --- a/Documentation/DocBook/v4l/pixfmt-nv12mt.xml +++ b/Documentation/DocBook/v4l/pixfmt-nv12mt.xml @@ -49,7 +49,7 @@ interleaved. Height of the buffer is aligned to 32. Memory layout of macroblocks in <constant>V4L2_PIX_FMT_NV12 </constant> format pixel image - extreme case -
+
Example <constant>V4L2_PIX_FMT_NV12MT</constant> memory layout of macroblocks -- cgit v1.2.3-70-g09d2 From ce5b2acce60405b938d1f1f994024cde4e2cdd7e Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Mon, 14 Mar 2011 08:49:28 -0300 Subject: [media] gspca - nw80x: New subdriver for Divio based webcams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [mchehab@redhat.com: Fix a few CodingStyle issues] Tested-by: Kjell Claesson Tested-by: Hans de Goede Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 9 + drivers/media/video/gspca/Kconfig | 9 + drivers/media/video/gspca/Makefile | 2 + drivers/media/video/gspca/nw80x.c | 2443 +++++++++++++++++++++++++++++++++++ include/linux/videodev2.h | 1 + 5 files changed, 2464 insertions(+) create mode 100644 drivers/media/video/gspca/nw80x.c (limited to 'Documentation') diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index dc72fff2eb1..5c542e60f51 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -103,6 +103,7 @@ spca561 046d:092d Logitech QC Elch2 spca561 046d:092e Logitech QC Elch2 spca561 046d:092f Logitech QuickCam Express Plus sunplus 046d:0960 Logitech ClickSmart 420 +nw80x 046d:d001 Logitech QuickCam Pro (dark focus ring) sunplus 0471:0322 Philips DMVC1300K zc3xx 0471:0325 Philips SPC 200 NC zc3xx 0471:0326 Philips SPC 300 NC @@ -150,10 +151,12 @@ sunplus 04fc:5330 Digitrex 2110 sunplus 04fc:5360 Sunplus Generic spca500 04fc:7333 PalmPixDC85 sunplus 04fc:ffff Pure DigitalDakota +nw80x 0502:d001 DVC V6 spca501 0506:00df 3Com HomeConnect Lite sunplus 052b:1507 Megapixel 5 Pretec DC-1007 sunplus 052b:1513 Megapix V4 sunplus 052b:1803 MegaImage VI +nw80x 052b:d001 EZCam Pro p35u tv8532 0545:808b Veo Stingray tv8532 0545:8333 Veo Stingray sunplus 0546:3155 Polaroid PDC3070 @@ -177,6 +180,7 @@ sunplus 055f:c530 Mustek Gsmart LCD 3 sunplus 055f:c540 Gsmart D30 sunplus 055f:c630 Mustek MDC4000 sunplus 055f:c650 Mustek MDC5500Z +nw80x 055f:d001 Mustek Wcam 300 mini zc3xx 055f:d003 Mustek WCam300A zc3xx 055f:d004 Mustek WCam300 AN conex 0572:0041 Creative Notebook cx11646 @@ -195,8 +199,12 @@ gl860 05e3:0503 Genesys Logic PC Camera gl860 05e3:f191 Genesys Logic PC Camera spca561 060b:a001 Maxell Compact Pc PM3 zc3xx 0698:2003 CTX M730V built in +nw80x 06a5:0000 Typhoon Webcam 100 USB +nw80x 06a5:d001 Divio based webcams +nw80x 06a5:d800 Divio Chicony TwinkleCam, Trust SpaceCam spca500 06bd:0404 Agfa CL20 spca500 06be:0800 Optimedia +nw80x 06be:d001 EZCam Pro p35u sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom spca506 06e1:a190 ADS Instant VCD ov534 06f8:3002 Hercules Blog Webcam @@ -204,6 +212,7 @@ ov534_9 06f8:3003 Hercules Dualpix HD Weblog sonixj 06f8:3004 Hercules Classic Silver sonixj 06f8:3008 Hercules Deluxe Optical Glass pac7302 06f8:3009 Hercules Classic Link +nw80x 0728:d001 AVerMedia Camguard spca508 0733:0110 ViewQuest VQ110 spca501 0733:0401 Intel Create and Share spca501 0733:0402 ViewQuest M318B diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index a20f6ae8825..eb04e8b5998 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -104,6 +104,15 @@ config USB_GSPCA_MR97310A To compile this driver as a module, choose M here: the module will be called gspca_mr97310a. +config USB_GSPCA_NW80X + tristate "Divio based (NW80x) USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the NW80x chips. + + To compile this driver as a module, choose M here: the + module will be called gspca_nw80x. + config USB_GSPCA_OV519 tristate "OV51x / OVFX2 / W996xCF USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index a0dbcfbab29..855fbc8c9c4 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o +obj-$(CONFIG_USB_GSPCA_NW80X) += gspca_nw80x.o obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o @@ -48,6 +49,7 @@ gspca_jeilinj-objs := jeilinj.o gspca_konica-objs := konica.o gspca_mars-objs := mars.o gspca_mr97310a-objs := mr97310a.o +gspca_nw80x-objs := nw80x.o gspca_ov519-objs := ov519.o gspca_ov534-objs := ov534.o gspca_ov534_9-objs := ov534_9.o diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c new file mode 100644 index 00000000000..1c9d3c2f667 --- /dev/null +++ b/drivers/media/video/gspca/nw80x.c @@ -0,0 +1,2443 @@ +/* + * DivIO nw80x subdriver + * + * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr) + * Copyright (C) 2003 Sylvain Munaut + * Kjell Claesson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define MODULE_NAME "nw80x" + +#include "gspca.h" + +MODULE_AUTHOR("Jean-Francois Moine "); +MODULE_DESCRIPTION("NW80x USB Camera Driver"); +MODULE_LICENSE("GPL"); + +static int webcam; + +/* controls */ +enum e_ctrl { + GAIN, + EXPOSURE, + AUTOGAIN, + NCTRLS /* number of controls */ +}; + +/* specific webcam descriptor */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + + struct gspca_ctrl ctrls[NCTRLS]; + + u32 ae_res; + s8 ag_cnt; +#define AG_CNT_START 13 + + u8 bridge; + u8 webcam; +}; + +enum bridges { + BRIDGE_NW800, /* et31x110 */ + BRIDGE_NW801, + BRIDGE_NW802, +}; +enum webcams { + Generic800, + SpaceCam, /* Trust 120 SpaceCam */ + SpaceCam2, /* other Trust 120 SpaceCam */ + Cvideopro, /* Conceptronic Video Pro */ + Dlink350c, + DS3303u, + Kr651us, + Kritter, + Mustek300, + Proscope, + Twinkle, + DsbC110, + DvcV6, + P35u, + Generic802, + NWEBCAMS /* number of webcams */ +}; + +/* + - webcams: + - Typhoon Webcam 100 USB (06a5:0000) + nw800 + - Trust SpaceCam120 or SpaceCam100 PORTABLE (06a5:d800) + nw801 SpaceCam.init + or trust_space.init if no LED (?) + - Divio Chicony TwinkleCam (06a5:d800) ? + nw800 Twinkle.init + - Plustek Opticam 500U or ProLink DS3303u + nw801 DS3303u.init + - Logitech QuickCam Pro (dark focus ring) (046d:d001) + nw801 + - EZCam Pro p35u (052b:d001, 06a5:d001 and 06be:d001) + nw801 - sensor Sharp IR3Y38M + - AVerMedia Camguard (0728:d001) + nw801 + - Panasonic GP-KR651US (06a5:d001) + nw802 kr651us.init + - iRez Kritter cam + nw802 kritter.init + - D-link dru-350c cam + nw802 d-link-350c.init + - The Scope USB Microscope M2 (ProScope) + = Divio ProLink DS3303u WebCam (06a5:d001) + = Scalar USB Microscope M2 (Proscope) + nw802 proscope.init + - Conceptronic Video Pro 'CVIDEOPRO USB Webcam CCD' (06a5:d001) + nw802 cvideopro.init + - Mustek Wcam 300 mini + nw802 mustek_300_mini.init + - D-Link NetQam Pro 250plus (06a5:d001) + - Showcam NGS webcam (065a:d800) + - sceptre svc300 + - DSB-C110 (06a5:d800) + et31x110 + - DVC V6 (0502:d001) + nw802 + - registers + nw800/et31x110 nw801 nw802 + 0000..009e 0000..00a1 0000..009e + 0200..0211 id id + 0300..0302 id id + 0400..0406 (inex) 0400..0406 + 0500..0505 0500..0506 (inex) + 0600..061a 0600..0601 0600..0601 + 0800..0814 id id + 1000..109c 1000..10a1 1000..109a + + 080c: luma (nw800/nw802) + 080d: luma (nw801) + 1004: LUT (?) + 100b: R gain (0..63) + 100c: B gain + 100d: G gain + 100e: Y gain + 100f: U gain + 1010: V gain + 1019: clock (nw801 - bit 0x08: indoor/outdoor) + 101b: shutter 1 (0..255) + 101c: shutter 2 + 1026: BP = gain (nw801) + 1041, 1052, 1063, 1074: LUT base (nw802) + 1048, 1059, 106a, 107b: LUT base (nw801) + - resolutions + nw800 352x288 + nw801/nw802 320x240 - 640x480 +*/ + +static const struct v4l2_pix_format sif_mode[] = { + {352, 288, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE, + .bytesperline = 352, + .sizeimage = 352 * 288 * 4 / 8, + .colorspace = V4L2_COLORSPACE_JPEG} +}; +static const struct v4l2_pix_format vga_mode[] = { + {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 4 / 8, + .colorspace = V4L2_COLORSPACE_JPEG}, + {640, 480, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8, + .colorspace = V4L2_COLORSPACE_JPEG}, +}; + +/* + * The sequences below contain: + * - 1st and 2nd bytes: either + * - register number (BE) + * - I2C0 + i2c address + * - 3rd byte: data length (=0 for end of sequence) + * - n bytes: data + */ +#define I2C0 0xff +static const u8 nw800_init[] = { + 0x05, 0x00, 0x01, 0x55, + 0x10, 0x9b, 0x01, 0xaa, + 0x05, 0x02, 0x01, 0x02, + 0x06, 0x00, 0x02, 0x04, 0xd9, + 0x05, 0x05, 0x01, 0x00, + 0x05, 0x05, 0x01, 0x01, + 0x04, 0x06, 0x01, 0x04, + + 0x04, 0x06, 0x01, 0xc0, + 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f, + 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24, + 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08, + 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, + 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0, + 0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20, + 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62, + 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, + 0x01, 0x60, 0x01, 0x00, 0x00, + + 0x04, 0x04, 0x01, 0xff, + 0x04, 0x06, 0x01, 0xc4, + + 0x04, 0x06, 0x01, 0xc0, + 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f, + 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24, + 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08, + 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, + 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0, + 0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20, + 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62, + 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, + 0x01, 0x60, 0x01, 0x00, 0x00, + + 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65, + 0x40, + 0x00, 0x80, 0x01, 0xa0, + 0x10, 0x1a, 0x01, 0x00, + 0x00, 0x91, 0x02, 0x6c, 0x01, + 0x00, 0x03, 0x02, 0xc8, 0x01, + 0x10, 0x1a, 0x01, 0x00, + 0x10, 0x00, 0x01, 0x83, + 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, + 0x20, 0x01, 0x60, 0x01, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, + 0x10, 0x1b, 0x02, 0x69, 0x00, + 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, + 0x05, 0x02, 0x01, 0x02, + 0x06, 0x00, 0x02, 0x04, 0xd9, + 0x05, 0x05, 0x01, 0x20, + 0x05, 0x05, 0x01, 0x21, + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83, + 0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0, + 0xea, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x13, 0x13, + 0x10, 0x03, 0x01, 0x14, + 0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83, + 0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0, + 0xea, + 0x10, 0x0b, 0x01, 0x14, + 0x10, 0x0d, 0x01, 0x20, + 0x10, 0x0c, 0x01, 0x34, + 0x04, 0x06, 0x01, 0xc3, + 0x04, 0x04, 0x01, 0x00, + 0x05, 0x02, 0x01, 0x02, + 0x06, 0x00, 0x02, 0x00, 0x48, + 0x05, 0x05, 0x01, 0x20, + 0x05, 0x05, 0x01, 0x21, + 0, 0, 0 +}; + +/* 06a5:d001 - nw801 - p35u */ +static const u8 nw801_init_1[] = { + 0x05, 0x06, 0x01, 0x04, + 0x00, 0x00, 0x40, 0x0e, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e, + 0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, + 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x69, 0xa8, 0x1f, 0x00, + 0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00, + 0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00, + 0x36, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0x22, 0x02, 0x80, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x15, 0x08, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x35, 0xfd, 0x07, 0x3d, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x02, + 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7, + 0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80, + 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, 0xa4, + 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, 0xcf, + 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, + 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, + 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x82, 0x02, + 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01, + 0xf0, 0x00, + 0, 0, 0, +}; +static const u8 nw801_init_qvga[] = { + 0x02, 0x00, 0x10, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x18, 0x0b, 0x06, 0xa2, 0x86, 0x78, + 0x02, 0x0f, 0x01, 0x6b, + 0x10, 0x1a, 0x01, 0x15, + 0x00, 0x00, 0x01, 0x1e, + 0x10, 0x00, 0x01, 0x2f, + 0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00, + /* AE window */ + 0, 0, 0, +}; +static const u8 nw801_init_vga[] = { + 0x02, 0x00, 0x10, 0x78, 0xa0, 0x97, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xf0, + 0x02, 0x0f, 0x01, 0xd5, + 0x10, 0x1a, 0x01, 0x15, + 0x00, 0x00, 0x01, 0x0e, + 0x10, 0x00, 0x01, 0x22, + 0x10, 0x8c, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01, + 0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01, + 0, 0, 0, +}; +static const u8 nw801_init_2[] = { + 0x10, 0x04, 0x01, 0x1a, + 0x10, 0x19, 0x01, 0x09, /* clock */ + 0x10, 0x24, 0x06, 0xc0, 0x00, 0x3f, 0x02, 0x00, 0x01, + /* .. gain .. */ + 0x00, 0x03, 0x02, 0x92, 0x03, + 0x00, 0x1d, 0x04, 0xf2, 0x00, 0x24, 0x07, + 0x00, 0x7b, 0x01, 0xcf, + 0x10, 0x94, 0x01, 0x07, + 0x05, 0x05, 0x01, 0x01, + 0x05, 0x04, 0x01, 0x01, + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8, + 0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0, + 0xf0, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x0c, 0x0c, + 0x10, 0x03, 0x01, 0x08, + 0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8, + 0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0, + 0xf0, + 0x10, 0x0b, 0x01, 0x0b, + 0x10, 0x0d, 0x01, 0x0b, + 0x10, 0x0c, 0x01, 0x1f, + 0x05, 0x06, 0x01, 0x03, + 0, 0, 0 +}; + +/* nw802 (sharp IR3Y38M?) */ +static const u8 nw802_init[] = { + 0x04, 0x06, 0x01, 0x04, + 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x4d, + 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, + 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, + 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94, + 0x00, 0x10, 0x06, 0x08, 0x00, 0x18, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0xff, 0x01, 0xc0, 0x00, 0x14, + 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x05, 0x82, + 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, + 0x01, 0xf0, 0x00, + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, + 0x40, + 0x10, 0x1a, 0x01, 0x00, + 0x10, 0x00, 0x01, 0xad, + 0x00, 0x00, 0x01, 0x08, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x00, 0x00, + 0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00, + 0x10, 0x1d, 0x08, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, + 0x10, 0x0e, 0x01, 0x27, + 0x10, 0x41, 0x11, 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b, + 0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2, + 0xd8, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x14, 0x14, + 0x10, 0x03, 0x01, 0x0c, + 0x10, 0x41, 0x11, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, 0xf1, + 0xff, +/* 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b, + * 0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2, + * 0xd8, */ + 0x10, 0x0b, 0x01, 0x10, + 0x10, 0x0d, 0x01, 0x11, + 0x10, 0x0c, 0x01, 0x1c, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x04, 0x01, 0x00, + 0, 0, 0 +}; +/* et31x110 - Trust 120 SpaceCam */ +static const u8 spacecam_init[] = { +/*fixme: at connection time*/ + 0x04, 0x05, 0x01, 0x01, + 0x04, 0x04, 0x01, 0x01, + 0x04, 0x06, 0x01, 0x04, + 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, + 0x05, 0x05, 0x01, 0x00, +/*fixme: add 300ms delay?*/ +/*fixme: at capture start time*/ + 0x04, 0x06, 0x01, 0x44, + 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f, + 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24, + 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08, + 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, + 0x00, 0x4b, 0x00, 0x7c, 0x00, 0x80, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62, + 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, + 0x01, 0x60, 0x01, 0x00, 0x00, + 0x04, 0x06, 0x01, 0xc0, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, + 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65, + 0x40, + 0x00, 0x80, 0x01, 0xa0, + 0x10, 0x1a, 0x01, 0x00, + 0x00, 0x91, 0x02, 0x32, 0x01, + 0x00, 0x03, 0x02, 0x08, 0x02, + 0x10, 0x00, 0x01, 0x83, + 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, + 0x20, 0x01, 0x60, 0x01, + 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x13, 0x13, + 0x10, 0x03, 0x01, 0x06, + 0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, + 0x10, 0x0b, 0x01, 0x08, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x1f, + 0x04, 0x06, 0x01, 0xc3, + 0x04, 0x05, 0x01, 0x40, + 0x04, 0x04, 0x01, 0x40, + 0, 0, 0 +}; +/* et31x110 - other Trust SpaceCam120 */ +static const u8 spacecam2_init[] = { + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x01, + 0x04, 0x06, 0x01, 0x04, + 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, + 0x05, 0x05, 0x01, 0x00, + 0x04, 0x06, 0x01, 0x44, + 0x04, 0x06, 0x01, 0x00, + 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f, + 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc, + 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03, + 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, + 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00, + 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, + 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, + 0x01, 0x60, 0x01, 0x00, 0x00, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, + 0x04, 0x04, 0x01, 0x40, + 0x04, 0x04, 0x01, 0x00, +#if 1 + I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x05, 0x05, + I2C0, 0x40, 0x02, 0x11, 0x06, + I2C0, 0x40, 0x02, 0x14, 0x00, + I2C0, 0x40, 0x02, 0x13, 0x01, +#else + 0x06, 0x00, 0x0b, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x05, 0x05, + 0x06, 0x00, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x05, 0x05, + 0x05, 0x02, 0x02, 0x0c, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x06, + 0x06, 0x00, 0x02, 0x11, 0x06, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x14, 0x00, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65, + 0x40, +#if 1 + I2C0, 0x40, 0x02, 0x02, 0x0c, + I2C0, 0x40, 0x02, 0x0f, 0x00, + I2C0, 0x40, 0x02, 0x13, 0x01, +#else + 0x06, 0x00, 0x01, 0x0c, + 0x06, 0x00, 0x02, 0x02, 0x0c, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x0f, 0x00, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, + 0x20, 0x01, 0x60, 0x01, +#if 1 + I2C0, 0x40, 0x02, 0x05, 0x0f, + I2C0, 0x40, 0x02, 0x13, 0x01, + I2C0, 0x40, 0x07, 0x09, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00, + I2C0, 0x40, 0x03, 0x12, 0x04, 0x01, +#else + 0x06, 0x00, 0x01, 0x0f, + 0x06, 0x00, 0x02, 0x05, 0x0f, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x06, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00, + 0x06, 0x00, 0x07, 0x09, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00, + 0x05, 0x02, 0x02, 0x07, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x04, 0x01, + 0x06, 0x00, 0x03, 0x12, 0x04, 0x01, + 0x05, 0x02, 0x02, 0x03, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, + 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, + 0xf9, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x13, 0x13, + 0x10, 0x03, 0x01, 0x06, + 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, + 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, + 0xf9, + 0x10, 0x0b, 0x01, 0x11, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x14, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x00, + 0, 0, 0 +}; + +/* nw802 - Conceptronic Video Pro */ +static const u8 cvideopro_init[] = { + 0x04, 0x06, 0x01, 0x04, + 0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c, + 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4, + 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54, + 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, + 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30, + 0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f, + 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, + 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94, + 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c, + 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82, + 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, + 0x01, 0xf0, 0x00, + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0, + 0x40, + 0x10, 0x1a, 0x01, 0x03, + 0x10, 0x00, 0x01, 0xac, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x3b, 0x01, + 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00, + 0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, + 0x10, 0x1d, 0x02, 0x40, 0x06, + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0, + 0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc, + 0xdc, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x12, 0x12, + 0x10, 0x03, 0x01, 0x0c, + 0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0, + 0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc, + 0xdc, + 0x10, 0x0b, 0x01, 0x09, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x2f, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x04, 0x01, 0x00, + 0, 0, 0 +}; + +/* nw802 - D-link dru-350c cam */ +static const u8 dlink_init[] = { + 0x04, 0x06, 0x01, 0x04, + 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d, +/* 0xf9, 0x02, = nb pixels per line */ + 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, + 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, + 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94, +/* 0x19, v index of clamping pulse */ + 0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14, + 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x82, + 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, + 0x01, 0xf0, 0x00, +/* 0x00, 0x03, 0x02, 0x92, 0x03, = nb of pixels per line */ + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, + 0x40, + 0x10, 0x1a, 0x01, 0x00, + 0x10, 0x00, 0x01, 0xad, + 0x00, 0x00, 0x01, 0x08, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x00, 0x00, + 0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00, + 0x10, 0x1d, 0x08, 0x40, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, + 0x10, 0x0e, 0x01, 0x20, + 0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f, + 0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf, + 0xea, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x11, 0x11, + 0x10, 0x03, 0x01, 0x10, + 0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f, + 0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf, + 0xea, + 0x10, 0x0b, 0x01, 0x19, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x1e, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x04, 0x01, 0x00, + 0, 0, 0 +}; + +/* nw801 - Plustek Opticam 500U or ProLink DS3303u (Hitachi HD49322BF) */ +static const u8 ds330_init[] = { + 0x05, 0x06, 0x01, 0x04, + 0x00, 0x00, 0x40, 0x16, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e, + 0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, + 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x1f, 0x00, + 0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00, + 0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00, + 0x36, 0x00, + 0x02, 0x00, 0x12, 0x03, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0x50, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0x2f, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a, + 0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4, + 0x00, 0x01, 0x15, 0xfd, 0x07, 0x3d, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8c, 0x04, 0x01, 0x20, + 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7, + 0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80, + 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, 0x88, + 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, 0xcb, + 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, + 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, + 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, 0x01, + 0x00, 0x00, 0xef, 0x00, 0x02, 0x0a, 0x82, 0x02, + 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01, + 0xf0, 0x00, + + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x3f, 0x00, 0xf2, 0x8f, 0x81, + 0x40, + 0x10, 0x1a, 0x01, 0x15, + 0x10, 0x00, 0x01, 0x2f, + 0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x00, 0x00, + 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00, + 0x10, 0x26, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, + 0x10, 0x24, 0x02, 0x40, 0x06, + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6, + 0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x16, 0x16, + 0x10, 0x03, 0x01, 0x0c, + 0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6, + 0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, + 0x10, 0x0b, 0x01, 0x26, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x1c, + 0x05, 0x06, 0x01, 0x03, + 0x05, 0x04, 0x01, 0x00, + 0, 0, 0 +}; + +/* 06a5:d001 - nw802 - Panasonic GP-KR651US (Philips TDA8786) */ +static const u8 kr651_init_1[] = { + 0x04, 0x06, 0x01, 0x04, + 0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x48, + 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4, + 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54, + 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, + 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30, + 0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f, + 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, + 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94, + 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c, + 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82, + 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, + 0x01, 0xf0, 0x00, + 0, 0, 0 +}; +static const u8 kr651_init_qvga[] = { + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, + 0x40, + 0x10, 0x1a, 0x01, 0x03, + 0x10, 0x00, 0x01, 0xac, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x00, 0x00, + 0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00, + 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00, + 0x10, 0x1d, 0x02, 0x28, 0x01, + 0, 0, 0 +}; +static const u8 kr651_init_vga[] = { + 0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x30, 0x03, 0x01, 0x82, 0x82, 0x98, + 0x80, + 0x10, 0x1a, 0x01, 0x03, + 0x10, 0x00, 0x01, 0xa0, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01, + + 0x10, 0x1b, 0x02, 0x00, 0x00, + 0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01, + + 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00, + 0x10, 0x1d, 0x02, 0x68, 0x00, +}; +static const u8 kr651_init_2[] = { + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8, + 0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, + 0xdc, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x0c, 0x0c, + 0x10, 0x03, 0x01, 0x0c, + 0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8, + 0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, + 0xdc, + 0x10, 0x0b, 0x01, 0x10, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x2d, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x04, 0x01, 0x00, + 0, 0, 0 +}; + +/* nw802 - iRez Kritter cam */ +static const u8 kritter_init[] = { + 0x04, 0x06, 0x01, 0x06, + 0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0x94, 0x03, 0x18, 0x00, 0x48, + 0x0f, 0x1e, 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x0a, 0x01, 0x28, + 0x07, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54, + 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, + 0x00, 0x5d, 0x00, 0x0e, 0x00, 0x7e, 0x00, 0x30, + 0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f, + 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, + 0x00, 0x0b, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94, + 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c, + 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x82, + 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, + 0x01, 0xf0, 0x00, + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0, + 0x40, + 0x10, 0x1a, 0x01, 0x03, + 0x10, 0x00, 0x01, 0xaf, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x3b, 0x01, + 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00, + 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00, + 0x10, 0x1d, 0x02, 0x00, 0x00, + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86, + 0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4, + 0xcb, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x0d, 0x0d, + 0x10, 0x03, 0x01, 0x02, + 0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86, + 0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4, + 0xcb, + 0x10, 0x0b, 0x01, 0x17, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x1e, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x04, 0x01, 0x00, + 0, 0, 0 +}; + +/* nw802 - Mustek Wcam 300 mini */ +static const u8 mustek_init[] = { + 0x04, 0x06, 0x01, 0x04, + 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d, + 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, + 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, + 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94, + 0x00, 0x10, 0x06, 0xfc, 0x05, 0x0c, 0x06, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14, + 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x82, + 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, + 0x01, 0xf0, 0x00, + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, + 0x40, + 0x10, 0x1a, 0x01, 0x00, + 0x10, 0x00, 0x01, 0xad, + 0x00, 0x00, 0x01, 0x08, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x00, 0x00, + 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1d, 0x08, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x10, 0x0e, 0x01, 0x0f, + 0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e, + 0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9, + 0xff, + 0x10, 0x0f, 0x02, 0x11, 0x11, + 0x10, 0x03, 0x01, 0x0c, + 0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e, + 0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9, + 0xff, + 0x10, 0x0b, 0x01, 0x1c, + 0x10, 0x0d, 0x01, 0x1a, + 0x10, 0x0c, 0x01, 0x34, + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x40, + 0x04, 0x06, 0x01, 0x03, + 0, 0, 0 +}; + +/* nw802 - Scope USB Microscope M2 (ProScope) (Hitachi HD49322BF) */ +static const u8 proscope_init_1[] = { + 0x04, 0x05, 0x01, 0x21, + 0x04, 0x04, 0x01, 0x01, + 0x04, 0x06, 0x01, 0x04, + 0x00, 0x00, 0x40, 0x10, 0x01, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x04, + 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x08, 0x00, 0x17, 0x00, 0xce, 0x00, 0xf4, + 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0xce, 0x00, 0xf8, 0x03, 0x3e, 0x00, 0x86, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0xb6, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xf6, 0x03, 0x34, 0x04, 0xf6, 0x03, 0x34, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xe8, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x1f, 0x0f, 0x08, 0x20, 0xa8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, + 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, 0x00, 0x94, + 0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0xad, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a, + 0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4, + 0x00, 0x49, 0x13, 0x00, 0x00, 0x8c, 0x04, 0x01, + 0x20, 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, + 0x88, 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, + 0xcb, 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, + 0x01, 0x00, 0x00, 0xef, 0x00, 0x09, 0x05, 0x82, + 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, + 0x01, 0xf0, 0x00, + 0, 0, 0 +}; +static const u8 proscope_init_qvga[] = { + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, + 0x40, + 0x10, 0x1a, 0x01, 0x06, + 0x00, 0x03, 0x02, 0xf9, 0x02, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x00, 0x00, + 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, + 0x10, 0x0e, 0x01, 0x10, + 0, 0, 0 +}; +static const u8 proscope_init_vga[] = { + 0x00, 0x03, 0x02, 0xf9, 0x02, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01, + 0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x16, 0x00, 0x00, 0x82, 0x84, 0x00, + 0x80, + 0x10, 0x1a, 0x01, 0x06, + 0x10, 0x00, 0x01, 0xa1, + 0x10, 0x1b, 0x02, 0x00, 0x00, + 0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, + 0x10, 0x11, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01, + 0x10, 0x0e, 0x01, 0x10, + 0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae, + 0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2, + 0xf9, + 0x10, 0x03, 0x01, 0x00, + 0, 0, 0 +}; +static const u8 proscope_init_2[] = { + 0x10, 0x0f, 0x02, 0x0c, 0x0c, + 0x10, 0x03, 0x01, 0x0c, + 0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae, + 0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2, + 0xf9, + 0x10, 0x0b, 0x01, 0x0b, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x1b, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x05, 0x01, 0x21, + 0x04, 0x04, 0x01, 0x00, + 0, 0, 0 +}; + +/* nw800 - Divio Chicony TwinkleCam */ +static const u8 twinkle_init[] = { + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x01, + 0x04, 0x06, 0x01, 0x04, + 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, + 0x05, 0x05, 0x01, 0x00, + + 0x04, 0x06, 0x01, 0x44, + 0x04, 0x06, 0x01, 0x00, + 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f, + 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc, + 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03, + 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, + 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00, + 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x08, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x10, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x00, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, + 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, + 0x01, 0x60, 0x01, 0x00, 0x00, + + 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, +/*320 3f ef, 0x00 */ + 0x04, 0x04, 0x01, 0x10, + 0x04, 0x04, 0x01, 0x00, + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x01, +#if 1 + I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, + I2C0, 0x40, 0x02, 0x11, 0x06, + I2C0, 0x40, 0x02, 0x14, 0x00, + I2C0, 0x40, 0x02, 0x13, 0x01, + I2C0, 0x40, 0x02, 0x07, 0x01, +#else + 0x06, 0x00, 0x0b, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, + 0x06, 0x00, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, + 0x05, 0x02, 0x02, 0x0c, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x06, + 0x06, 0x00, 0x02, 0x11, 0x06, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x14, 0x00, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x07, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00, +/* 320 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, */ + 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65, +/* 320 0x00, 0x78, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x5c, */ + 0x40, +#if 1 + I2C0, 0x40, 0x02, 0x02, 0x0c, + I2C0, 0x40, 0x02, 0x13, 0x01, +#else + 0x06, 0x00, 0x01, 0x0c, + 0x06, 0x00, 0x02, 0x02, 0x0c, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, + 0x20, 0x01, 0x60, 0x01, +/* 320 0xf0, 0x00, 0x40, 0x01, */ +#if 1 + I2C0, 0x40, 0x02, 0x05, 0x0f, + I2C0, 0x40, 0x02, 0x13, 0x01, + I2C0, 0x40, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17, + I2C0, 0x40, 0x03, 0x12, 0x00, 0x01, +#else + 0x06, 0x00, 0x01, 0x0f, + 0x06, 0x00, 0x02, 0x05, 0x0f, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x07, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17, + 0x06, 0x00, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17, + 0x05, 0x02, 0x02, 0x08, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x00, 0x01, + 0x06, 0x00, 0x03, 0x12, 0x00, 0x01, + 0x05, 0x02, 0x02, 0x03, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, +/* 320 3f ef */ +#if 1 + I2C0, 0x40, 0x02, 0x12, 0x00, + I2C0, 0x40, 0x02, 0x0e, 0x00, + I2C0, 0x40, 0x02, 0x11, 0x06, +#else + 0x06, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x12, 0x00, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x0e, 0x00, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x06, + 0x06, 0x00, 0x02, 0x11, 0x06, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, + 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, + 0xf9, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x0c, 0x0c, + 0x10, 0x03, 0x01, 0x06, + 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, + 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, + 0xf9, + 0x10, 0x0b, 0x01, 0x19, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x0d, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x41, + 0, 0, 0 +}; + +/* et31x110 DSB-C110 */ +static const u8 dsbc110_init[] = { + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x01, + 0x04, 0x06, 0x01, 0x04, + 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, + 0x05, 0x05, 0x01, 0x00, + + 0x04, 0x06, 0x01, 0x44, + 0x04, 0x06, 0x01, 0x00, + 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f, + 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc, + 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, + 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, + 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, + 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, + 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, + 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, + 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03, + 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, + 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00, + 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x08, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x10, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x00, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, + 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, + 0x01, 0x60, 0x01, 0x00, 0x00, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x04, 0x04, 0x01, 0x10, + 0x04, 0x04, 0x01, 0x00, + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x01, +#if 1 + I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, + I2C0, 0x40, 0x02, 0x11, 0x06, + I2C0, 0x40, 0x02, 0x14, 0x00, + I2C0, 0x40, 0x02, 0x13, 0x01, + I2C0, 0x40, 0x02, 0x07, 0x01, +#else + 0x06, 0x00, 0x0b, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, + 0x06, 0x00, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, + 0x05, 0x02, 0x02, 0x0c, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x06, + 0x06, 0x00, 0x02, 0x11, 0x06, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x14, 0x00, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x07, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xe4, + 0x40, +#if 1 + I2C0, 0x40, 0x02, 0x02, 0x0c, + I2C0, 0x40, 0x02, 0x13, 0x01, +#else + 0x06, 0x00, 0x01, 0x1c, + 0x06, 0x00, 0x02, 0x02, 0x1c, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, + 0xf0, 0x00, 0x40, 0x01, +#if 1 + I2C0, 0x40, 0x02, 0x05, 0x23, + I2C0, 0x40, 0x02, 0x13, 0x01, + I2C0, 0x40, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x00, + I2C0, 0x40, 0x03, 0x12, 0x00, 0x01, +#else + 0x06, 0x00, 0x01, 0x24, + 0x06, 0x00, 0x02, 0x05, 0x24, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x13, 0x01, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x07, 0x06, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x00, + 0x06, 0x00, 0x08, 0x08, 0x06, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x00, + 0x05, 0x02, 0x02, 0x08, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x02, 0x00, 0x01, + 0x06, 0x00, 0x03, 0x12, 0x00, 0x01, + 0x05, 0x02, 0x02, 0x03, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, +#if 1 + I2C0, 0x40, 0x02, 0x12, 0x00, + I2C0, 0x40, 0x02, 0x0e, 0x00, + I2C0, 0x40, 0x02, 0x11, 0x06, +#else + 0x06, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x12, 0x00, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x0e, 0x00, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, + 0x06, 0x00, 0x01, 0x06, + 0x06, 0x00, 0x02, 0x11, 0x06, + 0x05, 0x02, 0x02, 0x02, 0x40, + 0x05, 0x05, 0x01, 0x01, +#endif + 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, + 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, + 0xf9, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x0c, 0x0c, + 0x10, 0x03, 0x01, 0x06, + 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, + 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, + 0xf9, + 0x10, 0x0b, 0x01, 0x14, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x1d, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x05, 0x01, 0x61, + 0x04, 0x04, 0x01, 0x41, +}; + +/* nw802 dvc-v6 */ +static const u8 dvcv6_init[] = { + 0x04, 0x06, 0x01, 0x06, + 0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c, + 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, + 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, + 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4, + 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54, + 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, + 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30, + 0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f, + 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, + 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94, + 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00, + 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, + 0x40, 0x20, + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x06, 0x00, 0x02, 0x09, 0x99, + 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c, + 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, + 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, + 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, + 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, + 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, + 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, + 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, + 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, + 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, + 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, + 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82, + 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, + 0x01, 0xf0, 0x00, + 0x00, 0x03, 0x02, 0x94, 0x03, + 0x00, 0x1d, 0x04, 0x0a, 0x01, 0x28, 0x07, + 0x00, 0x7b, 0x02, 0xe0, 0x00, + 0x10, 0x8d, 0x01, 0x00, + 0x00, 0x09, 0x04, 0x1e, 0x00, 0x0c, 0x02, + 0x00, 0x91, 0x02, 0x0b, 0x02, + 0x10, 0x00, 0x01, 0xaf, + 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8f, 0x3c, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0, + 0x40, + 0x10, 0x1a, 0x01, 0x02, + 0x10, 0x00, 0x01, 0xaf, + 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, + 0x10, 0x1b, 0x02, 0x07, 0x01, + 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00, + 0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, + 0x10, 0x1d, 0x02, 0x40, 0x06, + 0x10, 0x0e, 0x01, 0x08, + 0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa, + 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc, + 0xdc, + 0x10, 0x03, 0x01, 0x00, + 0x10, 0x0f, 0x02, 0x12, 0x12, + 0x10, 0x03, 0x01, 0x11, + 0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa, + 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc, + 0xdc, + 0x10, 0x0b, 0x01, 0x16, + 0x10, 0x0d, 0x01, 0x10, + 0x10, 0x0c, 0x01, 0x1a, + 0x04, 0x06, 0x01, 0x03, + 0x04, 0x04, 0x01, 0x00, +}; + +static const u8 *webcam_init[] = { + [Generic800] = nw800_init, + [SpaceCam] = spacecam_init, + [SpaceCam2] = spacecam2_init, + [Cvideopro] = cvideopro_init, + [Dlink350c] = dlink_init, + [DS3303u] = ds330_init, + [Kr651us] = kr651_init_1, + [Kritter] = kritter_init, + [Mustek300] = mustek_init, + [Proscope] = proscope_init_1, + [Twinkle] = twinkle_init, + [DsbC110] = dsbc110_init, + [DvcV6] = dvcv6_init, + [P35u] = nw801_init_1, + [Generic802] = nw802_init, +}; + +/* -- write a register -- */ +static void reg_w(struct gspca_dev *gspca_dev, + u16 index, + const u8 *data, + int len) +{ + struct usb_device *dev = gspca_dev->dev; + int ret; + + if (gspca_dev->usb_err < 0) + return; + if (len == 1) + PDEBUG(D_USBO, "SET 00 0000 %04x %02x", index, *data); + else + PDEBUG(D_USBO, "SET 00 0000 %04x %02x %02x ...", + index, *data, data[1]); + memcpy(gspca_dev->usb_buf, data, len); + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x00, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x00, /* value */ + index, + gspca_dev->usb_buf, + len, + 500); + if (ret < 0) { + err("reg_w err %d", ret); + gspca_dev->usb_err = ret; + } +} + +/* -- read registers in usb_buf -- */ +static void reg_r(struct gspca_dev *gspca_dev, + u16 index, + int len) +{ + struct usb_device *dev = gspca_dev->dev; + int ret; + + if (gspca_dev->usb_err < 0) + return; + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + 0x00, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x00, index, + gspca_dev->usb_buf, len, 500); + if (ret < 0) { + err("reg_r err %d", ret); + gspca_dev->usb_err = ret; + return; + } + if (len == 1) + PDEBUG(D_USBI, "GET 00 0000 %04x %02x", + index, gspca_dev->usb_buf[0]); + else + PDEBUG(D_USBI, "GET 00 0000 %04x %02x %02x ..", + index, gspca_dev->usb_buf[0], + gspca_dev->usb_buf[1]); +} + +static void i2c_w(struct gspca_dev *gspca_dev, + u8 i2c_addr, + const u8 *data, + int len) +{ + u8 val[2]; + int i; + + reg_w(gspca_dev, 0x0600, data + 1, len - 1); + reg_w(gspca_dev, 0x0600, data, len); + val[0] = len; + val[1] = i2c_addr; + reg_w(gspca_dev, 0x0502, val, 2); + val[0] = 0x01; + reg_w(gspca_dev, 0x0501, val, 1); + for (i = 5; --i >= 0; ) { + msleep(4); + reg_r(gspca_dev, 0x0505, 1); + if (gspca_dev->usb_err < 0) + return; + if (gspca_dev->usb_buf[0] == 0) + return; + } + gspca_dev->usb_err = -ETIME; +} + +static void reg_w_buf(struct gspca_dev *gspca_dev, + const u8 *cmd) +{ + u16 reg; + int len; + + for (;;) { + reg = *cmd++ << 8; + reg += *cmd++; + len = *cmd++; + if (len == 0) + break; + if (cmd[-3] != I2C0) + reg_w(gspca_dev, reg, cmd, len); + else + i2c_w(gspca_dev, reg & 0xff, cmd, len); + cmd += len; + } +} + +static int swap_6bits(int v) +{ + int r, i; + + r = 0; + for (i = 0; i < 6; i++) { + r <<= 1; + if (v & 1) + r++; + v >>= 1; + } + return r; +} + +static void setgain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val, v[2]; + + val = sd->ctrls[GAIN].val >> 1; /* 0 - 63 -> 0 - 31 */ + reg_w(gspca_dev, 0x100e, &val, 1); /* AE Y gain */ + + switch (sd->webcam) { + case P35u: + /* Note the control goes from 0-255 not 0-127, but anything + above 127 just means amplifying noise */ + val = sd->ctrls[GAIN].val << 1; /* 0 - 63 -> 0 - 127 */ + reg_w(gspca_dev, 0x1026, &val, 1); + break; + case Kr651us: + /* 0 - 63 -> 0 - 0x37 */ + val = (sd->ctrls[GAIN].val * 0x37) / 63; + val = swap_6bits(val); + v[0] = val << 3; + v[1] = val >> 5; + reg_w(gspca_dev, 0x101d, v, 2); /* SIF reg0/1 (AGC) */ + break; + } +} + +static void setexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 v[2]; + + switch (sd->webcam) { + case P35u: + v[0] = (sd->ctrls[EXPOSURE].val << 3) | 0x01; + reg_w(gspca_dev, 0x1019, v, 1); + break; + case Kr651us: + v[0] = sd->ctrls[EXPOSURE].val; + v[1] = sd->ctrls[EXPOSURE].val >> 8; + reg_w(gspca_dev, 0x101b, v, 2); + break; + } +} + +static void setautogain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int w, h; + + if (gspca_dev->ctrl_dis & (1 << AUTOGAIN)) + return; + if (!sd->ctrls[AUTOGAIN].val) { + sd->ag_cnt = -1; + return; + } + sd->ag_cnt = AG_CNT_START; + + reg_r(gspca_dev, 0x1004, 1); + if (gspca_dev->usb_buf[0] & 0x04) { /* if AE_FULL_FRM */ + sd->ae_res = gspca_dev->width * gspca_dev->height; + } else { /* get the AE window size */ + reg_r(gspca_dev, 0x1011, 8); + w = (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0] + - (gspca_dev->usb_buf[3] << 8) - gspca_dev->usb_buf[2]; + h = (gspca_dev->usb_buf[5] << 8) + gspca_dev->usb_buf[4] + - (gspca_dev->usb_buf[7] << 8) - gspca_dev->usb_buf[6]; + sd->ae_res = h * w; + if (sd->ae_res == 0) + sd->ae_res = gspca_dev->width * gspca_dev->height; + } +} + +/* this function is called at probe time */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if ((unsigned) webcam >= NWEBCAMS) + webcam = 0; + sd->webcam = webcam; + gspca_dev->cam.reverse_alts = 1; + gspca_dev->cam.ctrls = sd->ctrls; + sd->ag_cnt = -1; + return 0; +} + +static int nw802_test_reg(struct gspca_dev *gspca_dev, + u16 index, + u8 value) +{ + /* write the value */ + reg_w(gspca_dev, index, &value, 1); + + /* read it */ + reg_r(gspca_dev, index, 1); + + return gspca_dev->usb_buf[0] == value; +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + /* + * Autodetect sequence inspired from some log. + * We try to detect what registers exist or not. + * If 0x0500 does not exist => NW802 + * If it does, test 0x109b. If it doesn't exist, + * then it's a NW801. Else, a NW800 + */ + if (!nw802_test_reg(gspca_dev, 0x0500, 0x55)) { + sd->bridge = BRIDGE_NW802; + if (sd->webcam == Generic800) + sd->webcam = Generic802; + } else if (!nw802_test_reg(gspca_dev, 0x109b, 0xaa)) { + sd->bridge = BRIDGE_NW801; + if (sd->webcam == Generic800) + sd->webcam = P35u; + } + PDEBUG(D_PROBE, "Bridge nw80%d", sd->bridge); + + if (sd->bridge == BRIDGE_NW800) { + gspca_dev->cam.cam_mode = sif_mode; + gspca_dev->cam.nmodes = ARRAY_SIZE(sif_mode); + } else { + gspca_dev->cam.cam_mode = vga_mode; + switch (sd->webcam) { + case Generic802: + case Kr651us: + case Proscope: + case P35u: + gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); + break; + default: + gspca_dev->cam.nmodes = 1; /* qvga only */ + break; + } + } + switch (sd->webcam) { + case P35u: +/* sd->ctrls[EXPOSURE].min = 0; + * sd->ctrls[EXPOSURE].max = 9; + * sd->ctrls[EXPOSURE].def = 1; */ + break; + case Kr651us: +/* sd->ctrls[EXPOSURE].min = 0; */ + sd->ctrls[EXPOSURE].max = 315; + sd->ctrls[EXPOSURE].def = 150; + break; + default: + gspca_dev->ctrl_dis = ~(1 << GAIN); + break; + } + + return gspca_dev->usb_err; +} + +/* -- start the camera -- */ +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + const u8 *cmd; + + cmd = webcam_init[sd->webcam]; + reg_w_buf(gspca_dev, cmd); + switch (sd->webcam) { + case P35u: + if (gspca_dev->width == 320) + reg_w_buf(gspca_dev, nw801_init_qvga); + else + reg_w_buf(gspca_dev, nw801_init_vga); + reg_w_buf(gspca_dev, nw801_init_2); + break; + case Kr651us: + if (gspca_dev->width == 320) + reg_w_buf(gspca_dev, kr651_init_qvga); + else + reg_w_buf(gspca_dev, kr651_init_vga); + reg_w_buf(gspca_dev, kr651_init_2); + break; + case Proscope: + if (gspca_dev->width == 320) + reg_w_buf(gspca_dev, proscope_init_qvga); + else + reg_w_buf(gspca_dev, proscope_init_vga); + reg_w_buf(gspca_dev, proscope_init_2); + break; + } + + setgain(gspca_dev); + setexposure(gspca_dev); + setautogain(gspca_dev); + return gspca_dev->usb_err; +} + +static void sd_stopN(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 value; + + /* 'go' off */ + if (sd->bridge != BRIDGE_NW801) { + value = 0x02; + reg_w(gspca_dev, 0x0406, &value, 1); + } + + /* LED off */ + switch (sd->webcam) { + case Cvideopro: + case Kr651us: + case DvcV6: + case Kritter: + value = 0xff; + break; + case Dlink350c: + value = 0x21; + break; + case SpaceCam: + case SpaceCam2: + case Proscope: + case Twinkle: + value = 0x01; + break; + default: + return; + } + reg_w(gspca_dev, 0x0404, &value, 1); +} + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + /* + * frame header = '00 00 hh ww ss xx ff ff' + * with: + * - 'hh': height / 4 + * - 'ww': width / 4 + * - 'ss': frame sequence number c0..dd + */ + if (data[0] == 0x00 && data[1] == 0x00 + && data[6] == 0xff && data[7] == 0xff) { + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); + gspca_frame_add(gspca_dev, FIRST_PACKET, data + 8, len - 8); + } else { + gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + } +} + +static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->ctrls[AUTOGAIN].val = val; + if (val) + gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE); + else + gspca_dev->ctrl_inac = 0; + if (gspca_dev->streaming) + setautogain(gspca_dev); + return gspca_dev->usb_err; +} + +static void do_autogain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int luma; + int gain, shutter; + + if (sd->ag_cnt < 0) + return; + if (--sd->ag_cnt >= 0) + return; + sd->ag_cnt = AG_CNT_START; + + /* get the average luma */ + reg_r(gspca_dev, sd->bridge == BRIDGE_NW801 ? 0x080d : 0x080c, 4); + luma = (gspca_dev->usb_buf[3] << 24) + (gspca_dev->usb_buf[2] << 16) + + (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; + luma /= sd->ae_res; + + if (sd->webcam == P35u) { + u8 clock; + + if (luma > 92 && luma < 108) + return; /* fine */ + clock = sd->ctrls[EXPOSURE].val; + gain = sd->ctrls[GAIN].val; + if (luma < 100) { + if (luma < 70 && clock > 0) + clock--; + if (gain > 98 && clock > 0) + clock--; + if (gain <= 50) + gain += 3; + } else { + if (luma > 150 && clock < 9) + clock++; + if (gain < 12 && clock < 9) + clock++; + if (gain >= 5) + gain -= 3; + } + if (gain != sd->ctrls[GAIN].val) { + sd->ctrls[GAIN].val = gain; + setgain(gspca_dev); + } + if (clock != sd->ctrls[EXPOSURE].val) { + sd->ctrls[EXPOSURE].val = clock; + setexposure(gspca_dev); + } + return; + } + + /* kr651us */ + if (luma > 95 && luma < 105) + return; /* fine */ + gain = sd->ctrls[GAIN].val; + shutter = sd->ctrls[EXPOSURE].val; + if (luma < 100) { + if (shutter > 0) { + if (luma < 85 && shutter > 50) + shutter -= 50; + else + shutter--; + } else if (gain < 63) { + if (luma < 85 && gain < 53) + gain += 10; + else + gain++; + } + } else { + if (gain > 0) { + if (luma > 115 && gain > 10) + gain -= 10; + else + gain--; + } else if (shutter < 316) { /* max 0x13b */ + if (luma > 115 && shutter < 266) + shutter += 50; + else + shutter++; + } + } + if (gain != sd->ctrls[GAIN].val) { + sd->ctrls[GAIN].val = gain; + setgain(gspca_dev); + } + if (shutter != sd->ctrls[EXPOSURE].val) { + sd->ctrls[EXPOSURE].val = shutter; + setexposure(gspca_dev); + } +} + +/* V4L2 controls supported by the driver */ +static const struct ctrl sd_ctrls[NCTRLS] = { +[GAIN] = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 63, + .step = 1, + .default_value = 16 + }, + .set_control = setgain + }, +[EXPOSURE] = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 9, + .step = 1, + .default_value = 1 + }, + .set_control = setexposure + }, +[AUTOGAIN] = { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Gain", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = V4L2_CTRL_FLAG_UPDATE + }, + .set = sd_setautogain + }, +}; + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stopN = sd_stopN, + .pkt_scan = sd_pkt_scan, + .dq_callback = do_autogain, +}; + +/* -- module initialisation -- */ +static const struct usb_device_id device_table[] = { + {USB_DEVICE(0x046d, 0xd001)}, + {USB_DEVICE(0x0502, 0xd001)}, + {USB_DEVICE(0x052b, 0xd001)}, + {USB_DEVICE(0x055f, 0xd001)}, + {USB_DEVICE(0x06a5, 0x0000)}, + {USB_DEVICE(0x06a5, 0xd001)}, + {USB_DEVICE(0x06a5, 0xd800)}, + {USB_DEVICE(0x06be, 0xd001)}, + {USB_DEVICE(0x0728, 0xd001)}, + {} +}; +MODULE_DEVICE_TABLE(usb, device_table); + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + return usb_register(&sd_driver); +} +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); + +module_param(webcam, int, 0644); +MODULE_PARM_DESC(webcam, + "Webcam type\n" + "0: generic\n" + "1: Trust 120 SpaceCam\n" + "2: other Trust 120 SpaceCam\n" + "3: Conceptronic Video Pro\n" + "4: D-link dru-350c\n" + "5: Plustek Opticam 500U\n" + "6: Panasonic GP-KR651US\n" + "7: iRez Kritter\n" + "8: Mustek Wcam 300 mini\n" + "9: Scalar USB Microscope M2 (Proscope)\n" + "10: Divio Chicony TwinkleCam\n" + "11: DSB-C110\n" + "12: DVC-V6\n"); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 8c80fd36da0..aa6c393b7ae 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -396,6 +396,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_TM6000 v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */ #define V4L2_PIX_FMT_CIT_YYVYUY v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */ #define V4L2_PIX_FMT_KONICA420 v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */ +#define V4L2_PIX_FMT_JPGL v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */ /* * F O R M A T E N U M E R A T I O N -- cgit v1.2.3-70-g09d2 From f0e3b646ccce66c9e878966227ce8415d3c11c2a Mon Sep 17 00:00:00 2001 From: Pawel Osciak Date: Sun, 13 Mar 2011 15:20:22 -0300 Subject: [media] Make 2.6.39 not 2.6.38 the version when Multi-planar API was added Multi-planar API was added to 2.6.39 version of Video for Linux 2 API. Signed-off-by: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/compat.xml | 13 ++++--------- Documentation/DocBook/v4l/v4l2.xml | 13 ++----------- 2 files changed, 6 insertions(+), 20 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/compat.xml b/Documentation/DocBook/v4l/compat.xml index 4d74bf24e11..9f7cd4f2579 100644 --- a/Documentation/DocBook/v4l/compat.xml +++ b/Documentation/DocBook/v4l/compat.xml @@ -2354,8 +2354,11 @@ that used it. It was originally scheduled for removal in 2.6.35.
- V4L2 in Linux 2.6.38 + V4L2 in Linux 2.6.39 + + The old VIDIOC_*_OLD symbols and V4L1 support were removed. + Multi-planar API added. Does not affect the compatibility of current drivers and applications. See @@ -2364,14 +2367,6 @@ that used it. It was originally scheduled for removal in 2.6.35.
-
- V4L2 in Linux 2.6.39 - - - The old VIDIOC_*_OLD symbols and V4L1 support were removed. - - -
Relation of V4L2 to other Linux multimedia APIs diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index ae7a069d61d..a7fd76d0dac 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -130,17 +130,8 @@ applications. --> 2.6.39 2011-03-01 - mcc - Removed VIDIOC_*_OLD from videodev2.h header and update it to reflect latest changes. - - - - - 2.6.38 - 2011-01-16 - po - Added the multi-planar API. - + mcc, po + Removed VIDIOC_*_OLD from videodev2.h header and update it to reflect latest changes. Added the multi-planar API. -- cgit v1.2.3-70-g09d2 From 3286dac1ca34b85b069c409414a3e51a9217b159 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sat, 12 Feb 2011 22:38:47 -0300 Subject: [media] DM04 LME2510(C) Sharp BS2F7HZ0194 Firmware Information DM04 LME2510(C) Sharp BS2F7HZ0194 Firmware Information Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab --- Documentation/dvb/lmedm04.txt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/dvb/lmedm04.txt b/Documentation/dvb/lmedm04.txt index 64188650420..10b5f041138 100644 --- a/Documentation/dvb/lmedm04.txt +++ b/Documentation/dvb/lmedm04.txt @@ -4,7 +4,7 @@ following file(s) to this directory. for DM04+/QQBOX LME2510C (Sharp 7395 Tuner) ------------------------------------------- -The Sharp 7395 driver can be found in windows/system32/driver +The Sharp 7395 driver can be found in windows/system32/drivers US2A0D.sys (dated 17 Mar 2009) @@ -44,7 +44,7 @@ and run Other LG firmware can be extracted manually from US280D.sys -only found in windows/system32/driver. +only found in windows/system32/drivers dd if=US280D.sys ibs=1 skip=42360 count=3924 of=dvb-usb-lme2510-lg.fw @@ -55,4 +55,16 @@ dd if=US280D.sys ibs=1 skip=35200 count=3850 of=dvb-usb-lme2510c-lg.fw --------------------------------------------------------------------- +The Sharp 0194 tuner driver can be found in windows/system32/drivers + +US290D.sys (dated 09 Apr 2009) + +For LME2510 +dd if=US290D.sys ibs=1 skip=36856 count=3976 of=dvb-usb-lme2510-s0194.fw + + +For LME2510C +dd if=US290D.sys ibs=1 skip=33152 count=3697 of=dvb-usb-lme2510c-s0194.fw + + Copy the firmware file(s) to /lib/firmware -- cgit v1.2.3-70-g09d2 From 6e29ad50b4d688b1d18e2d255e31676c7ee46d3d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 24 Feb 2011 10:58:13 -0300 Subject: [media] v4l2-framework.txt: improve v4l2_fh/priority documentation Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 120 +++++++++++++++++++-------- 1 file changed, 87 insertions(+), 33 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index f2df31b088c..1c8d4492f5c 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -549,6 +549,10 @@ You should also set these fields: Otherwise you give it a pointer to a struct mutex_lock and before any of the v4l2_file_operations is called this lock will be taken by the core and released afterwards. +- prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY. + If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device. + If you want to have a separate priority state per (group of) device node(s), + then you can point it to your own struct v4l2_prio_state. - parent: you only set this if v4l2_device was registered with NULL as the parent device struct. This only happens in cases where one hardware device has multiple PCI devices that all share the same v4l2_device core. @@ -559,8 +563,10 @@ You should also set these fields: PCI device it is setup without a parent device. But when the struct video_device is setup you do know which parent PCI device to use. -If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or -.ioctl to video_ioctl2 in your v4l2_file_operations struct. +If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to video_ioctl2 +in your v4l2_file_operations struct. + +Do not use .ioctl! This is deprecated and will go away in the future. The v4l2_file_operations struct is a subset of file_operations. The main difference is that the inode argument is omitted since it is never used. @@ -753,39 +759,24 @@ struct v4l2_fh -------------- struct v4l2_fh provides a way to easily keep file handle specific data -that is used by the V4L2 framework. Using v4l2_fh is optional for -drivers. +that is used by the V4L2 framework. New drivers must use struct v4l2_fh +since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY). The users of v4l2_fh (in the V4L2 framework, not the driver) know whether a driver uses v4l2_fh as its file->private_data pointer by -testing the V4L2_FL_USES_V4L2_FH bit in video_device->flags. - -Useful functions: - -- v4l2_fh_init() - - Initialise the file handle. This *MUST* be performed in the driver's - v4l2_file_operations->open() handler. - -- v4l2_fh_add() +testing the V4L2_FL_USES_V4L2_FH bit in video_device->flags. This bit is +set whenever v4l2_fh_init() is called. - Add a v4l2_fh to video_device file handle list. May be called after - initialising the file handle. - -- v4l2_fh_del() - - Unassociate the file handle from video_device(). The file handle - exit function may now be called. +struct v4l2_fh is allocated as a part of the driver's own file handle +structure and file->private_data is set to it in the driver's open +function by the driver. -- v4l2_fh_exit() +In many cases the struct v4l2_fh will be embedded in a larger structure. +In that case you should call v4l2_fh_init+v4l2_fh_add in open() and +v4l2_fh_del+v4l2_fh_exit in release(). - Uninitialise the file handle. After uninitialisation the v4l2_fh - memory can be freed. - -struct v4l2_fh is allocated as a part of the driver's own file handle -structure and is set to file->private_data in the driver's open -function by the driver. Drivers can extract their own file handle -structure by using the container_of macro. Example: +Drivers can extract their own file handle structure by using the container_of +macro. Example: struct my_fh { int blah; @@ -802,15 +793,21 @@ int my_open(struct file *file) ... + my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL); + + ... + ret = v4l2_fh_init(&my_fh->fh, vfd); - if (ret) + if (ret) { + kfree(my_fh); return ret; + } - v4l2_fh_add(&my_fh->fh); + ... file->private_data = &my_fh->fh; - - ... + v4l2_fh_add(&my_fh->fh); + return 0; } int my_release(struct file *file) @@ -819,8 +816,65 @@ int my_release(struct file *file) struct my_fh *my_fh = container_of(fh, struct my_fh, fh); ... + v4l2_fh_del(&my_fh->fh); + v4l2_fh_exit(&my_fh->fh); + kfree(my_fh); + return 0; } +Below is a short description of the v4l2_fh functions used: + +int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) + + Initialise the file handle. This *MUST* be performed in the driver's + v4l2_file_operations->open() handler. + +void v4l2_fh_add(struct v4l2_fh *fh) + + Add a v4l2_fh to video_device file handle list. Must be called once the + file handle is completely initialized. + +void v4l2_fh_del(struct v4l2_fh *fh) + + Unassociate the file handle from video_device(). The file handle + exit function may now be called. + +void v4l2_fh_exit(struct v4l2_fh *fh) + + Uninitialise the file handle. After uninitialisation the v4l2_fh + memory can be freed. + + +If struct v4l2_fh is not embedded, then you can use these helper functions: + +int v4l2_fh_open(struct file *filp) + + This allocates a struct v4l2_fh, initializes it and adds it to the struct + video_device associated with the file struct. + +int v4l2_fh_release(struct file *filp) + + This deletes it from the struct video_device associated with the file + struct, uninitialised the v4l2_fh and frees it. + +These two functions can be plugged into the v4l2_file_operation's open() and +release() ops. + + +Several drivers need to do something when the first file handle is opened and +when the last file handle closes. Two helper functions were added to check +whether the v4l2_fh struct is the only open filehandle of the associated +device node: + +int v4l2_fh_is_singular(struct v4l2_fh *fh) + + Returns 1 if the file handle is the only open file handle, else 0. + +int v4l2_fh_is_singular_file(struct file *filp) + + Same, but it calls v4l2_fh_is_singular with filp->private_data. + + V4L2 events ----------- -- cgit v1.2.3-70-g09d2 From 2335e2b817186cf79a07311f14560ef8b30f6a9a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 24 Feb 2011 06:28:46 -0300 Subject: [media] v4l2-framework.txt: document new v4l2_device release() callback Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 1c8d4492f5c..7d09114af00 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -181,6 +181,21 @@ static int __devinit drv_probe(struct pci_dev *pdev, state->instance = atomic_inc_return(&drv_instance) - 1; } +If you have multiple device nodes then it can be difficult to know when it is +safe to unregister v4l2_device. For this purpose v4l2_device has refcounting +support. The refcount is increased whenever video_register_device is called and +it is decreased whenever that device node is released. When the refcount reaches +zero, then the v4l2_device release() callback is called. You can do your final +cleanup there. + +If other device nodes (e.g. ALSA) are created, then you can increase and +decrease the refcount manually as well by calling: + +void v4l2_device_get(struct v4l2_device *v4l2_dev); + +or: + +int v4l2_device_put(struct v4l2_device *v4l2_dev); struct v4l2_subdev ------------------ -- cgit v1.2.3-70-g09d2 From b1a873a37b6551a214ad37d1eee7654a9d65fd6e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2011 10:14:07 -0300 Subject: [media] v4l2: use new flag to enable core priority handling Rather than guess which driver supports core priority handling, require drivers that do to explicitly set the V4L2_FL_USE_FH_PRIO flag in video_device. Updated the core prio handling accordingly and set the flag in the three drivers that do. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 7 ++++++- drivers/media/video/cx18/cx18-streams.c | 1 + drivers/media/video/ivtv/ivtv-streams.c | 1 + drivers/media/video/v4l2-dev.c | 8 +++----- drivers/media/video/v4l2-fh.c | 7 ++++--- drivers/media/video/v4l2-ioctl.c | 13 ++++++++----- drivers/media/video/vivi.c | 1 + include/media/v4l2-dev.h | 3 +++ 8 files changed, 27 insertions(+), 14 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 7d09114af00..3b15608ee07 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -577,6 +577,10 @@ You should also set these fields: (cx8802). Since the v4l2_device cannot be associated with a particular PCI device it is setup without a parent device. But when the struct video_device is setup you do know which parent PCI device to use. +- flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework + handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct + v4l2_fh. Eventually this flag will disappear once all drivers use the core + priority handling. But for now it has to be set explicitly. If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to video_ioctl2 in your v4l2_file_operations struct. @@ -775,7 +779,8 @@ struct v4l2_fh struct v4l2_fh provides a way to easily keep file handle specific data that is used by the V4L2 framework. New drivers must use struct v4l2_fh -since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY). +since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY) +if the video_device flag V4L2_FL_USE_FH_PRIO is also set. The users of v4l2_fh (in the V4L2 framework, not the driver) know whether a driver uses v4l2_fh as its file->private_data pointer by diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 2d248560770..c6e2ca3b114 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -207,6 +207,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) s->video_dev->fops = &cx18_v4l2_enc_fops; s->video_dev->release = video_device_release; s->video_dev->tvnorms = V4L2_STD_ALL; + set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags); cx18_set_funcs(s->video_dev); return 0; } diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 512607e0cda..94268333655 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -214,6 +214,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) s->vdev->fops = ivtv_stream_info[type].fops; s->vdev->release = video_device_release; s->vdev->tvnorms = V4L2_STD_ALL; + set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); ivtv_set_funcs(s->vdev); return 0; } diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 1898099ec65..498e6742579 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -578,11 +578,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr, vdev->parent = vdev->v4l2_dev->dev; if (vdev->ctrl_handler == NULL) vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; - /* If the prio state pointer is NULL, and if the driver doesn't - handle priorities itself, then use the v4l2_device prio - state. */ - if (vdev->prio == NULL && vdev->ioctl_ops && - vdev->ioctl_ops->vidioc_s_priority == NULL) + /* If the prio state pointer is NULL, then use the v4l2_device + prio state. */ + if (vdev->prio == NULL) vdev->prio = &vdev->v4l2_dev->prio; } diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/video/v4l2-fh.c index 543b3fe6784..717f71e6370 100644 --- a/drivers/media/video/v4l2-fh.c +++ b/drivers/media/video/v4l2-fh.c @@ -35,7 +35,6 @@ int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) INIT_LIST_HEAD(&fh->list); set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags); fh->prio = V4L2_PRIORITY_UNSET; - BUG_ON(vdev->prio == NULL); /* * fh->events only needs to be initialized if the driver @@ -54,7 +53,8 @@ void v4l2_fh_add(struct v4l2_fh *fh) { unsigned long flags; - v4l2_prio_open(fh->vdev->prio, &fh->prio); + if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags)) + v4l2_prio_open(fh->vdev->prio, &fh->prio); spin_lock_irqsave(&fh->vdev->fh_lock, flags); list_add(&fh->list, &fh->vdev->fh_list); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); @@ -82,7 +82,8 @@ void v4l2_fh_del(struct v4l2_fh *fh) spin_lock_irqsave(&fh->vdev->fh_lock, flags); list_del_init(&fh->list); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - v4l2_prio_close(fh->vdev->prio, fh->prio); + if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags)) + v4l2_prio_close(fh->vdev->prio, fh->prio); } EXPORT_SYMBOL_GPL(v4l2_fh_del); diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 3e6b6fa5771..a01ed39e6c1 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -541,6 +541,7 @@ static long __video_do_ioctl(struct file *file, void *fh = file->private_data; struct v4l2_fh *vfh = NULL; struct v4l2_format f_copy; + int use_fh_prio = 0; long ret = -EINVAL; if (ops == NULL) { @@ -555,10 +556,12 @@ static long __video_do_ioctl(struct file *file, printk(KERN_CONT "\n"); } - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) + if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { vfh = file->private_data; + use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); + } - if (vfh && !ops->vidioc_s_priority) { + if (use_fh_prio) { switch (cmd) { case VIDIOC_S_CTRL: case VIDIOC_S_STD: @@ -620,7 +623,7 @@ static long __video_do_ioctl(struct file *file, if (ops->vidioc_g_priority) { ret = ops->vidioc_g_priority(file, fh, p); - } else if (vfh) { + } else if (use_fh_prio) { *p = v4l2_prio_max(&vfd->v4l2_dev->prio); ret = 0; } @@ -632,7 +635,7 @@ static long __video_do_ioctl(struct file *file, { enum v4l2_priority *p = arg; - if (!ops->vidioc_s_priority && vfh == NULL) + if (!ops->vidioc_s_priority && !use_fh_prio) break; dbgarg(cmd, "setting priority to %d\n", *p); if (ops->vidioc_s_priority) @@ -2187,7 +2190,7 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_default) break; - if (vfh && !ops->vidioc_s_priority) + if (use_fh_prio) valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0; ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg); break; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 42500bf03a9..2238a613d66 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1254,6 +1254,7 @@ static int __init vivi_create_instance(int inst) *vfd = vivi_template; vfd->debug = debug; vfd->v4l2_dev = &dev->v4l2_dev; + set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); /* * Provide a mutex to v4l2 core. It will be used to protect diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 3700127ba29..8266d5ade2f 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -35,7 +35,10 @@ struct v4l2_ctrl_handler; Drivers can clear this flag if they want to block all future device access. It is cleared by video_unregister_device. */ #define V4L2_FL_REGISTERED (0) +/* file->private_data points to struct v4l2_fh */ #define V4L2_FL_USES_V4L2_FH (1) +/* Use the prio field of v4l2_fh for core priority checking */ +#define V4L2_FL_USE_FH_PRIO (2) /* Priority helper functions */ -- cgit v1.2.3-70-g09d2 From fe06b11dea74d53156d4116dcd518193a2e42ba4 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 24 Jan 2011 18:22:12 -0300 Subject: [media] docs: fix typo in lirc_device_interface.xml Reported-by: Daniel Burr Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/v4l/lirc_device_interface.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/v4l/lirc_device_interface.xml b/Documentation/DocBook/v4l/lirc_device_interface.xml index 68134c0ab4d..0e0453f39e7 100644 --- a/Documentation/DocBook/v4l/lirc_device_interface.xml +++ b/Documentation/DocBook/v4l/lirc_device_interface.xml @@ -45,7 +45,7 @@ describing an IR signal are read from the chardev. The data written to the chardev is a pulse/space sequence of integer values. Pulses and spaces are only marked implicitly by their position. The data must start and end with a pulse, therefore, the data must always include -an unevent number of samples. The write function must block until the data has +an uneven number of samples. The write function must block until the data has been transmitted by the hardware.
-- cgit v1.2.3-70-g09d2