From 3e43cb33f637d77405ccddc81a6d76acd57ff71c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 1 Mar 2016 11:57:24 -0300 Subject: [media] v4l2-pci-skeleton.c: fill in device_caps in video_device With the new core support for the caps the driver no longer needs to set device_caps and capabilities in the querycap call. Signed-off-by: Hans Verkuil Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-pci-skeleton.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/v4l2-pci-skeleton.c b/Documentation/video4linux/v4l2-pci-skeleton.c index 79af0c041056..a55cf94ac907 100644 --- a/Documentation/video4linux/v4l2-pci-skeleton.c +++ b/Documentation/video4linux/v4l2-pci-skeleton.c @@ -308,9 +308,6 @@ static int skeleton_querycap(struct file *file, void *priv, strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(skel->pdev)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -872,6 +869,8 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent) vdev->release = video_device_release_empty; vdev->fops = &skel_fops, vdev->ioctl_ops = &skel_ioctl_ops, + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; /* * The main serialization lock. All ioctls are serialized by this * lock. Exception: if q->lock is set, then the streaming ioctls -- cgit v1.2.3 From bd546882ff3476718d6df872c1c95aedcc5ed37d Mon Sep 17 00:00:00 2001 From: Yoshihiro Kaneko Date: Mon, 14 Mar 2016 21:40:26 -0300 Subject: [media] soc_camera: rcar_vin: add R-Car Gen 2 and 3 fallback compatibility strings Add fallback compatibility string for R-Car Gen 1 and 2. In the case of Renesas R-Car hardware we know that there are generations of SoCs, e.g. Gen 2 and 3. But beyond that it's unclear what the relationship between IP blocks might be. For example, I believe that r8a7790 is older than r8a7791 but that doesn't imply that the latter is a descendant of the former or vice versa. We can, however, by examining the documentation and behaviour of the hardware at run-time observe that the current driver implementation appears to be compatible with the IP blocks on SoCs within a given generation. For the above reasons and convenience when enabling new SoCs a per-generation fallback compatibility string scheme being adopted for drivers for Renesas SoCs. Signed-off-by: Yoshihiro Kaneko Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rcar_vin.txt | 11 +++++++++-- drivers/media/platform/soc_camera/rcar_vin.c | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 619193ccf7ff..4266123888ed 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -5,7 +5,7 @@ The rcar_vin device provides video input capabilities for the Renesas R-Car family of devices. The current blocks are always slaves and suppot one input channel which can be either RGB, YUYV or BT656. - - compatible: Must be one of the following + - compatible: Must be one or more of the following - "renesas,vin-r8a7795" for the R8A7795 device - "renesas,vin-r8a7794" for the R8A7794 device - "renesas,vin-r8a7793" for the R8A7793 device @@ -13,6 +13,13 @@ channel which can be either RGB, YUYV or BT656. - "renesas,vin-r8a7790" for the R8A7790 device - "renesas,vin-r8a7779" for the R8A7779 device - "renesas,vin-r8a7778" for the R8A7778 device + - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 compatible device. + - "renesas,rcar-gen3-vin" for a generic R-Car Gen3 compatible device. + + When compatible with the generic version nodes must list the + SoC-specific version corresponding to the platform first + followed by the generic version. + - reg: the register base and size for the device registers - interrupts: the interrupt for the device - clocks: Reference to the parent clock @@ -37,7 +44,7 @@ Device node example }; vin0: vin@0xe6ef0000 { - compatible = "renesas,vin-r8a7790"; + compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin"; clocks = <&mstp8_clks R8A7790_CLK_VIN0>; reg = <0 0xe6ef0000 0 0x1000>; interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>; diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index 3b8edf458964..3f9c1b8456c3 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -1845,6 +1845,8 @@ static const struct of_device_id rcar_vin_of_table[] = { { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 }, { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 }, + { .compatible = "renesas,rcar-gen3-vin", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,rcar-gen2-vin", .data = (void *)RCAR_GEN2 }, { }, }; MODULE_DEVICE_TABLE(of, rcar_vin_of_table); -- cgit v1.2.3 From 1d260123cb5c88574de9b5147eddc243f83b77a8 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 14 Mar 2016 21:40:27 -0300 Subject: [media] soc_camera: rcar_vin: add device tree support for r8a7792 Simply document new compatibility string. As a previous patch adds a generic R-Car Gen2 compatibility string there appears to be no need for a driver updates. By documenting this compat string it may be used in DTSs shipped, for example as part of ROMs. It must be used in conjunction with the Gen2 fallback compat string. At this time there are no known differences between the r8a7792 IP block and that implemented by the driver for the Gen2 fallback compat string. Thus there is no need to update the driver as the use of the Gen2 fallback compat string will activate the correct code in the current driver while leaving the option for r8a7792-specific driver code to be activated in an updated driver should the need arise. Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rcar_vin.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 4266123888ed..6a4e61cbe011 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -9,6 +9,7 @@ channel which can be either RGB, YUYV or BT656. - "renesas,vin-r8a7795" for the R8A7795 device - "renesas,vin-r8a7794" for the R8A7794 device - "renesas,vin-r8a7793" for the R8A7793 device + - "renesas,vin-r8a7792" for the R8A7792 device - "renesas,vin-r8a7791" for the R8A7791 device - "renesas,vin-r8a7790" for the R8A7790 device - "renesas,vin-r8a7779" for the R8A7779 device -- cgit v1.2.3 From 0be67c40d4e8c5b3d96581680fa797f28a3025ec Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2016 07:30:27 -0300 Subject: [media] vidioc-g-edid.xml: be explicit about zeroing the reserved array The G/S_EDID documentation did not explicitly state that the reserved array should be zeroed by the application. Also add the missing VIDIOC_SUBDEV_G/S_EDID ioctl names to the header. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-g-edid.xml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/media/v4l/vidioc-g-edid.xml b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml index 2702536bbc7c..b7602d30f596 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-edid.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml @@ -1,6 +1,6 @@ - ioctl VIDIOC_G_EDID, VIDIOC_S_EDID + ioctl VIDIOC_G_EDID, VIDIOC_S_EDID, VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID &manvol; @@ -71,7 +71,8 @@ To get the EDID data the application has to fill in the pad, start_block, blocks and edid - fields and call VIDIOC_G_EDID. The current EDID from block + fields, zero the reserved array and call + VIDIOC_G_EDID. The current EDID from block start_block and of size blocks will be placed in the memory edid points to. The edid pointer must point to memory at least blocks * 128 bytes @@ -92,8 +93,9 @@ the driver will set blocks to 0 and it returns 0. To set the EDID blocks of a receiver the application has to fill in the pad, - blocks and edid fields and set - start_block to 0. It is not possible to set part of an EDID, + blocks and edid fields, set + start_block to 0 and zero the reserved array. + It is not possible to set part of an EDID, it is always all or nothing. Setting the EDID data is only valid for receivers as it makes no sense for a transmitter. -- cgit v1.2.3 From 0c53fee973a9adfa4ad21433d397adae12b2120b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2016 07:30:28 -0300 Subject: [media] vidioc-enum-dv-timings.xml: explicitly state that pad and reserved should be zeroed The ENUM_DV_TIMINGS documentation did not clearly state that the pad and reserved fields should be zeroed (pad only when used with a video device node). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml index 6e3cadd4e1f9..70ca76d1e6d2 100644 --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml @@ -61,8 +61,9 @@ of known supported timings. Call &VIDIOC-DV-TIMINGS-CAP; to check if it also sup standards or even custom timings that are not in this list. To query the available timings, applications initialize the -index field and zero the reserved array of &v4l2-enum-dv-timings; -and call the VIDIOC_ENUM_DV_TIMINGS ioctl on a video node with a +index field, set the pad field to 0, +zero the reserved array of &v4l2-enum-dv-timings; and call the +VIDIOC_ENUM_DV_TIMINGS ioctl on a video node with a pointer to this structure. Drivers fill the rest of the structure or return an &EINVAL; when the index is out of bounds. To enumerate all supported DV timings, applications shall begin at index zero, incrementing by one until the -- cgit v1.2.3 From c5c631416789004e7205a56ab1aaab2b3a011b1b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2016 07:30:29 -0300 Subject: [media] vidioc-dv-timings-cap.xml: explicitly state that pad and reserved should be zeroed The DV_TIMINGS_CAP documentation didn't state clearly that the pad and reserved fields should be zeroed by the application. For subdev pad can be other values as well. It also mistakenly said that only drivers would have to zero the reserved field, that's not correct. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml index a2017bfcaed2..b6f47a6b14d5 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml @@ -55,8 +55,9 @@ interface and may change in the future. - To query the capabilities of the DV receiver/transmitter applications -can call the VIDIOC_DV_TIMINGS_CAP ioctl on a video node + To query the capabilities of the DV receiver/transmitter applications initialize the +pad field to 0, zero the reserved array of &v4l2-dv-timings-cap; +and call the VIDIOC_DV_TIMINGS_CAP ioctl on a video node and the driver will fill in the structure. Note that drivers may return different values after switching the video input or output. @@ -65,8 +66,8 @@ queried by calling the VIDIOC_SUBDEV_DV_TIMINGS_CAP ioctl directly on a subdevice node. The capabilities are specific to inputs (for DV receivers) or outputs (for DV transmitters), applications must specify the desired pad number in the &v4l2-dv-timings-cap; pad -field. Attempts to query capabilities on a pad that doesn't support them will -return an &EINVAL;. +field and zero the reserved array. Attempts to query +capabilities on a pad that doesn't support them will return an &EINVAL;. struct <structname>v4l2_bt_timings_cap</structname> @@ -145,7 +146,8 @@ return an &EINVAL;. __u32 reserved[2] - Reserved for future extensions. Drivers must set the array to zero. + Reserved for future extensions. Drivers and applications must + set the array to zero. union -- cgit v1.2.3 From ac49de8c49d770b5ded5c717c1eaf339d7649da1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Apr 2016 16:42:42 -0300 Subject: [media] v4l2-rect.h: new header with struct v4l2_rect helper functions This makes it easier to share this code with any driver that needs to manipulate the v4l2_rect datastructure. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/device-drivers.tmpl | 1 + include/media/v4l2-rect.h | 173 ++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 include/media/v4l2-rect.h (limited to 'Documentation') diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 184f3c7b5145..893b2cabf7e4 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -233,6 +233,7 @@ X!Isound/sound_firmware.c !Iinclude/media/v4l2-mediabus.h !Iinclude/media/v4l2-mem2mem.h !Iinclude/media/v4l2-of.h +!Iinclude/media/v4l2-rect.h !Iinclude/media/v4l2-subdev.h !Iinclude/media/videobuf2-core.h !Iinclude/media/videobuf2-v4l2.h diff --git a/include/media/v4l2-rect.h b/include/media/v4l2-rect.h new file mode 100644 index 000000000000..d2125f0cc7cd --- /dev/null +++ b/include/media/v4l2-rect.h @@ -0,0 +1,173 @@ +/* + * v4l2-rect.h - v4l2_rect helper functions + * + * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _V4L2_RECT_H_ +#define _V4L2_RECT_H_ + +#include + +/** + * v4l2_rect_set_size_to() - copy the width/height values. + * @r: rect whose width and height fields will be set + * @size: rect containing the width and height fields you need. + */ +static inline void v4l2_rect_set_size_to(struct v4l2_rect *r, + const struct v4l2_rect *size) +{ + r->width = size->width; + r->height = size->height; +} + +/** + * v4l2_rect_set_min_size() - width and height of r should be >= min_size. + * @r: rect whose width and height will be modified + * @min_size: rect containing the minimal width and height + */ +static inline void v4l2_rect_set_min_size(struct v4l2_rect *r, + const struct v4l2_rect *min_size) +{ + if (r->width < min_size->width) + r->width = min_size->width; + if (r->height < min_size->height) + r->height = min_size->height; +} + +/** + * v4l2_rect_set_max_size() - width and height of r should be <= max_size + * @r: rect whose width and height will be modified + * @max_size: rect containing the maximum width and height + */ +static inline void v4l2_rect_set_max_size(struct v4l2_rect *r, + const struct v4l2_rect *max_size) +{ + if (r->width > max_size->width) + r->width = max_size->width; + if (r->height > max_size->height) + r->height = max_size->height; +} + +/** + * v4l2_rect_map_inside()- r should be inside boundary. + * @r: rect that will be modified + * @boundary: rect containing the boundary for @r + */ +static inline void v4l2_rect_map_inside(struct v4l2_rect *r, + const struct v4l2_rect *boundary) +{ + v4l2_rect_set_max_size(r, boundary); + if (r->left < boundary->left) + r->left = boundary->left; + if (r->top < boundary->top) + r->top = boundary->top; + if (r->left + r->width > boundary->width) + r->left = boundary->width - r->width; + if (r->top + r->height > boundary->height) + r->top = boundary->height - r->height; +} + +/** + * v4l2_rect_same_size() - return true if r1 has the same size as r2 + * @r1: rectangle. + * @r2: rectangle. + * + * Return true if both rectangles have the same size. + */ +static inline bool v4l2_rect_same_size(const struct v4l2_rect *r1, + const struct v4l2_rect *r2) +{ + return r1->width == r2->width && r1->height == r2->height; +} + +/** + * v4l2_rect_intersect() - calculate the intersection of two rects. + * @r: intersection of @r1 and @r2. + * @r1: rectangle. + * @r2: rectangle. + */ +static inline void v4l2_rect_intersect(struct v4l2_rect *r, + const struct v4l2_rect *r1, + const struct v4l2_rect *r2) +{ + int right, bottom; + + r->top = max(r1->top, r2->top); + r->left = max(r1->left, r2->left); + bottom = min(r1->top + r1->height, r2->top + r2->height); + right = min(r1->left + r1->width, r2->left + r2->width); + r->height = max(0, bottom - r->top); + r->width = max(0, right - r->left); +} + +/** + * v4l2_rect_scale() - scale rect r by to/from + * @r: rect to be scaled. + * @from: from rectangle. + * @to: to rectangle. + * + * This scales rectangle @r horizontally by @to->width / @from->width and + * vertically by @to->height / @from->height. + * + * Typically @r is a rectangle inside @from and you want the rectangle as + * it would appear after scaling @from to @to. So the resulting @r will + * be the scaled rectangle inside @to. + */ +static inline void v4l2_rect_scale(struct v4l2_rect *r, + const struct v4l2_rect *from, + const struct v4l2_rect *to) +{ + if (from->width == 0 || from->height == 0) { + r->left = r->top = r->width = r->height = 0; + return; + } + r->left = (((r->left - from->left) * to->width) / from->width) & ~1; + r->width = ((r->width * to->width) / from->width) & ~1; + r->top = ((r->top - from->top) * to->height) / from->height; + r->height = (r->height * to->height) / from->height; +} + +/** + * v4l2_rect_overlap() - do r1 and r2 overlap? + * @r1: rectangle. + * @r2: rectangle. + * + * Returns true if @r1 and @r2 overlap. + */ +static inline bool v4l2_rect_overlap(const struct v4l2_rect *r1, + const struct v4l2_rect *r2) +{ + /* + * IF the left side of r1 is to the right of the right side of r2 OR + * the left side of r2 is to the right of the right side of r1 THEN + * they do not overlap. + */ + if (r1->left >= r2->left + r2->width || + r2->left >= r1->left + r1->width) + return false; + /* + * IF the top side of r1 is below the bottom of r2 OR + * the top side of r2 is below the bottom of r1 THEN + * they do not overlap. + */ + if (r1->top >= r2->top + r2->height || + r2->top >= r1->top + r1->height) + return false; + return true; +} + +#endif -- cgit v1.2.3 From 079dda54fe6e43b3db919e3ac3838a1355464c78 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Apr 2016 06:06:59 -0300 Subject: [media] DocBook media: drop 'experimental' annotations Drop the 'experimental' annotations. The only remaining part of the API that is still marked 'experimental' are the debug ioctls/structs, and that is intentional. Only the v4l2-dbg application should use those. All others have been around for years, so it is time to drop the 'experimental' designation. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 38 ---------------------- Documentation/DocBook/media/v4l/controls.xml | 31 ------------------ Documentation/DocBook/media/v4l/dev-sdr.xml | 6 ---- Documentation/DocBook/media/v4l/dev-subdev.xml | 6 ---- Documentation/DocBook/media/v4l/io.xml | 6 ---- Documentation/DocBook/media/v4l/selection-api.xml | 9 +---- Documentation/DocBook/media/v4l/subdev-formats.xml | 6 ---- .../DocBook/media/v4l/vidioc-create-bufs.xml | 6 ---- .../DocBook/media/v4l/vidioc-dv-timings-cap.xml | 6 ---- .../DocBook/media/v4l/vidioc-enum-dv-timings.xml | 6 ---- .../DocBook/media/v4l/vidioc-enum-freq-bands.xml | 6 ---- Documentation/DocBook/media/v4l/vidioc-expbuf.xml | 6 ---- .../DocBook/media/v4l/vidioc-g-selection.xml | 6 ---- .../DocBook/media/v4l/vidioc-prepare-buf.xml | 6 ---- .../DocBook/media/v4l/vidioc-query-dv-timings.xml | 6 ---- .../v4l/vidioc-subdev-enum-frame-interval.xml | 6 ---- .../media/v4l/vidioc-subdev-enum-frame-size.xml | 6 ---- .../media/v4l/vidioc-subdev-enum-mbus-code.xml | 6 ---- .../DocBook/media/v4l/vidioc-subdev-g-fmt.xml | 6 ---- .../media/v4l/vidioc-subdev-g-frame-interval.xml | 6 ---- .../media/v4l/vidioc-subdev-g-selection.xml | 6 ---- 21 files changed, 1 insertion(+), 185 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 5399e8904715..82fa328abd58 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2685,10 +2685,6 @@ hardware may support both. and may change in the future. - - Video Output Overlay (OSD) Interface, . - &VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER; ioctls. @@ -2696,40 +2692,6 @@ ioctls. &VIDIOC-DBG-G-CHIP-INFO; ioctl. - - &VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and - &VIDIOC-DV-TIMINGS-CAP; ioctls. - - - Flash API. - - - &VIDIOC-CREATE-BUFS; and &VIDIOC-PREPARE-BUF; ioctls. - - - Selection API. - - - Sub-device selection API: &VIDIOC-SUBDEV-G-SELECTION; - and &VIDIOC-SUBDEV-S-SELECTION; ioctls. - - - Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl. - - - Vendor and device specific media bus pixel formats. - . - - - Importing DMABUF file descriptors as a new IO method described - in . - - - Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl. - - - Software Defined Radio (SDR) Interface, . - diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 361040e6b0f4..81efa883f67d 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -4272,13 +4272,6 @@ manually or automatically if set to zero. Unit, range and step are driver-specif
Flash Control Reference - - Experimental - - This is an experimental -interface and may change in the future. - - The V4L2 flash controls are intended to provide generic access to flash controller devices. Flash controller devices are @@ -4743,14 +4736,6 @@ interface and may change in the future.
Image Source Control Reference - - Experimental - - This is an experimental interface and may - change in the future. - - The Image Source control class is intended for low-level control of image source devices such as image sensors. The @@ -4862,14 +4847,6 @@ interface and may change in the future.
Image Process Control Reference - - Experimental - - This is an experimental interface and may - change in the future. - - The Image Process control class is intended for low-level control of image processing functions. Unlike @@ -4955,14 +4932,6 @@ interface and may change in the future.
Digital Video Control Reference - - Experimental - - This is an experimental interface and may - change in the future. - - The Digital Video control class is intended to control receivers and transmitters for VGA, diff --git a/Documentation/DocBook/media/v4l/dev-sdr.xml b/Documentation/DocBook/media/v4l/dev-sdr.xml index a659771f7b7c..6da1157fb5bd 100644 --- a/Documentation/DocBook/media/v4l/dev-sdr.xml +++ b/Documentation/DocBook/media/v4l/dev-sdr.xml @@ -1,11 +1,5 @@ Software Defined Radio Interface (SDR) - - Experimental - This is an experimental - interface and may change in the future. - - SDR is an abbreviation of Software Defined Radio, the radio device which uses application software for modulation or demodulation. This interface diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml index 4f0ba58c9bd9..f4bc27af83eb 100644 --- a/Documentation/DocBook/media/v4l/dev-subdev.xml +++ b/Documentation/DocBook/media/v4l/dev-subdev.xml @@ -1,11 +1,5 @@ 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 diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml index 144158b3a5ac..e09025db92bd 100644 --- a/Documentation/DocBook/media/v4l/io.xml +++ b/Documentation/DocBook/media/v4l/io.xml @@ -475,12 +475,6 @@ rest should be evident.
Streaming I/O (DMA buffer importing) - - Experimental - This is an experimental - interface and may change in the future. - - The DMABUF framework provides a generic method for sharing buffers between multiple devices. Device drivers that support DMABUF can export a DMA buffer to userspace as a file descriptor (known as the exporter role), import a diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml index 28cbded766c9..b764cba150d1 100644 --- a/Documentation/DocBook/media/v4l/selection-api.xml +++ b/Documentation/DocBook/media/v4l/selection-api.xml @@ -1,13 +1,6 @@
- Experimental API for cropping, composing and scaling - - - Experimental - - This is an experimental -interface and may change in the future. - + API for cropping, composing and scaling
Introduction diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml index 4e73345e3eab..199c84e3aede 100644 --- a/Documentation/DocBook/media/v4l/subdev-formats.xml +++ b/Documentation/DocBook/media/v4l/subdev-formats.xml @@ -4002,12 +4002,6 @@ see .
Vendor and Device Specific Formats - - Experimental - This is an experimental -interface and may change in the future. - - This section lists complex data formats that are either vendor or device specific. diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml index d81fa0d4016b..6528e97b8990 100644 --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - This ioctl is used to create buffers for memory mapped or user pointer or DMA buffer I/O. It can be used as an alternative or in diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml index b6f47a6b14d5..ca9ffce9b4c1 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - To query the capabilities of the DV receiver/transmitter applications initialize the pad field to 0, zero the reserved array of &v4l2-dv-timings-cap; and call the VIDIOC_DV_TIMINGS_CAP ioctl on a video node diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml index 70ca76d1e6d2..9b3d42018b69 100644 --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - While some DV receivers or transmitters support a wide range of timings, others support only a limited number of timings. With this ioctl applications can enumerate a list of known supported timings. Call &VIDIOC-DV-TIMINGS-CAP; to check if it also supports other diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml index 4e8ea65f7282..a0608abc1ab8 100644 --- a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml +++ b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - Enumerates the frequency bands that a tuner or modulator supports. To do this applications initialize the tuner, type and index fields, diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml index 0ae0b6a915d0..a6558a676ef3 100644 --- a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - This ioctl is an extension to the memory mapping I/O method, therefore it is available only for V4L2_MEMORY_MMAP buffers. It can be used to export a diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml index 7865351688da..9523bc5650f9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml @@ -50,12 +50,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - The ioctls are used to query and configure selection rectangles. To query the cropping (composing) rectangle set &v4l2-selection; diff --git a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml index fa7ad7e33228..7bde698760e4 100644 --- a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml @@ -48,12 +48,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - Applications can optionally call the VIDIOC_PREPARE_BUF ioctl to pass ownership of the buffer to the driver before actually enqueuing it, using the diff --git a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml index 0c93677d16b4..d41bf47ee5a2 100644 --- a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml @@ -50,12 +50,6 @@ input Description - - Experimental - This is an experimental - interface and may change in the future. - - The hardware may be able to detect the current DV timings automatically, similar to sensing the video standard. To do so, applications call VIDIOC_QUERY_DV_TIMINGS with a pointer to a diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml index cff59f5cbf04..9d0251a27e5f 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml @@ -49,12 +49,6 @@ 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, diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml index abd545ede67a..9b91b8332ba9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml @@ -49,12 +49,6 @@ 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; diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml index 0bcb278fd062..c67256ada87a 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml @@ -49,12 +49,6 @@ 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, which and index fields of &v4l2-subdev-mbus-code-enum; and diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml index a67cde6f8c54..781089cba453 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml @@ -50,12 +50,6 @@ 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. diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml index 0bc3ea22d31f..848ec789ddaa 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml @@ -50,12 +50,6 @@ 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, diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml index c62a7360719b..8346b2e4a703 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml @@ -49,12 +49,6 @@ Description - - Experimental - This is an experimental - interface and may change in the future. - - The selections are used to configure various image processing functionality performed by the subdevs which affect the image size. This currently includes cropping, scaling and -- cgit v1.2.3 From 511257e6ae1fb87a2d0ad59ccdd61d1d4a0b9384 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Sun, 24 Apr 2016 21:24:11 -0300 Subject: [media] Documentation: dt: media: fix spelling mistake Fix spelling mistake. Signed-off-by: Eric Engestrom Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/xilinx/video.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/xilinx/video.txt b/Documentation/devicetree/bindings/media/xilinx/video.txt index cbd46fa0988f..68ac210e688e 100644 --- a/Documentation/devicetree/bindings/media/xilinx/video.txt +++ b/Documentation/devicetree/bindings/media/xilinx/video.txt @@ -20,7 +20,7 @@ The following properties are common to all Xilinx video IP cores. - xlnx,video-format: This property represents a video format transmitted on an AXI bus between video IP cores, using its VF code as defined in "AXI4-Stream Video IP and System Design Guide" [UG934]. How the format relates to the IP - core is decribed in the IP core bindings documentation. + core is described in the IP core bindings documentation. - xlnx,video-width: This property qualifies the video format with the sample width expressed as a number of bits per pixel component. All components must -- cgit v1.2.3 From 0ba20cdcc51b1acb6ba5387ccae47ef5ef620a5b Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Sun, 24 Apr 2016 21:24:20 -0300 Subject: [media] Documentation: DocBook: fix spelling mistake Fix spelling mistake. Signed-off-by: Eric Engestrom Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/dvb/net.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/media/dvb/net.xml b/Documentation/DocBook/media/dvb/net.xml index d2e44b7e07df..da095ed0b75c 100644 --- a/Documentation/DocBook/media/dvb/net.xml +++ b/Documentation/DocBook/media/dvb/net.xml @@ -15,7 +15,7 @@ that are present on the transport stream. This is done through /dev/dvb/adapter?/net? device node. The data will be available via virtual dvb?_? - network interfaces, and will be controled/routed via the standard + network interfaces, and will be controlled/routed via the standard ip tools (like ip, route, netstat, ifconfig, etc). Data types and and ioctl definitions are defined via linux/dvb/net.h header. -- cgit v1.2.3 From 1a2b2c708c5f7187c4c33d002bed6130381a6698 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 25 Apr 2016 03:37:03 -0300 Subject: [media] Documentation: video4linux: fix spelling mistakes Fix spelling mistakes. Signed-off-by: Eric Engestrom Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/vivid.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/vivid.txt b/Documentation/video4linux/vivid.txt index e35d376b7f64..8da5d2a576bc 100644 --- a/Documentation/video4linux/vivid.txt +++ b/Documentation/video4linux/vivid.txt @@ -294,7 +294,7 @@ the result will be. These inputs support all combinations of the field setting. Special care has been taken to faithfully reproduce how fields are handled for the different -TV standards. This is particularly noticable when generating a horizontally +TV standards. This is particularly noticeable when generating a horizontally moving image so the temporal effect of using interlaced formats becomes clearly visible. For 50 Hz standards the top field is the oldest and the bottom field is the newest in time. For 60 Hz standards that is reversed: the bottom field @@ -313,7 +313,7 @@ will be SMPTE-170M. The pixel aspect ratio will depend on the TV standard. The video aspect ratio can be selected through the 'Standard Aspect Ratio' Vivid control. Choices are '4x3', '16x9' which will give letterboxed widescreen video and -'16x9 Anomorphic' which will give full screen squashed anamorphic widescreen +'16x9 Anamorphic' which will give full screen squashed anamorphic widescreen video that will need to be scaled accordingly. The TV 'tuner' supports a frequency range of 44-958 MHz. Channels are available @@ -862,7 +862,7 @@ RDS Radio Text: RDS Stereo: RDS Artificial Head: RDS Compressed: -RDS Dymanic PTY: +RDS Dynamic PTY: RDS Traffic Announcement: RDS Traffic Program: RDS Music: these are all controls that set the RDS data that is transmitted by -- cgit v1.2.3 From 1e166c77fdbc71bd237a3d1ac27abef6221e3a5e Mon Sep 17 00:00:00 2001 From: Helen Mae Koike Fornazier Date: Wed, 30 Mar 2016 12:40:58 -0300 Subject: [media] DocBook: update error code in videoc-streamon Add description of ENOLINK error Signed-off-by: Helen Mae Koike Fornazier Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-streamon.xml | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Documentation') diff --git a/Documentation/DocBook/media/v4l/vidioc-streamon.xml b/Documentation/DocBook/media/v4l/vidioc-streamon.xml index df2c63d07bac..89fd7ce964f9 100644 --- a/Documentation/DocBook/media/v4l/vidioc-streamon.xml +++ b/Documentation/DocBook/media/v4l/vidioc-streamon.xml @@ -123,6 +123,14 @@ synchronize with other events. + + ENOLINK + + The driver implements Media Controller interface and + the pipeline link configuration is invalid. + + + -- cgit v1.2.3 From b9894728c2de35bab54f0f47b92b43a927ad7b37 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 23 Feb 2016 18:11:20 -0300 Subject: [media] media: adv7180: Add device tree binding document Add device tree binding documentation for the adv7180 video decoder family. Signed-off-by: Julian Scheel Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/adv7180.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7180.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/i2c/adv7180.txt b/Documentation/devicetree/bindings/media/i2c/adv7180.txt new file mode 100644 index 000000000000..2f39f268fdb0 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/adv7180.txt @@ -0,0 +1,20 @@ +* Analog Devices ADV7180 analog video decoder family + +The adv7180 family devices are used to capture analog video to different +digital interfaces like parallel video. + +Required Properties : +- compatible : value must be "adi,adv7180" + +Example: + + i2c0@1c22000 { + ... + ... + adv7180@21 { + compatible = "adi,adv7180"; + reg = <0x21>; + }; + ... + }; + -- cgit v1.2.3 From bf14e74cef06efc18fc769cbc331c6612dca214b Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 23 Feb 2016 18:11:21 -0300 Subject: [media] media: adv7180: Add of compatible strings for full family Add entries for all supported chip variants into the of_match list, so that the matching driver_info can be selected when using dt. Signed-off-by: Julian Scheel Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/i2c/adv7180.txt | 13 +++++++++++-- drivers/media/i2c/adv7180.c | 8 ++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/i2c/adv7180.txt b/Documentation/devicetree/bindings/media/i2c/adv7180.txt index 2f39f268fdb0..0d501154dfb2 100644 --- a/Documentation/devicetree/bindings/media/i2c/adv7180.txt +++ b/Documentation/devicetree/bindings/media/i2c/adv7180.txt @@ -1,10 +1,19 @@ * Analog Devices ADV7180 analog video decoder family The adv7180 family devices are used to capture analog video to different -digital interfaces like parallel video. +digital interfaces like MIPI CSI-2 or parallel video. Required Properties : -- compatible : value must be "adi,adv7180" +- compatible : value must be one of + "adi,adv7180" + "adi,adv7182" + "adi,adv7280" + "adi,adv7280-m" + "adi,adv7281" + "adi,adv7281-m" + "adi,adv7281-ma" + "adi,adv7282" + "adi,adv7282-m" Example: diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 5a75a9154e2e..b77b0a4dbf68 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1402,6 +1402,14 @@ static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume); #ifdef CONFIG_OF static const struct of_device_id adv7180_of_id[] = { { .compatible = "adi,adv7180", }, + { .compatible = "adi,adv7182", }, + { .compatible = "adi,adv7280", }, + { .compatible = "adi,adv7280-m", }, + { .compatible = "adi,adv7281", }, + { .compatible = "adi,adv7281-m", }, + { .compatible = "adi,adv7281-ma", }, + { .compatible = "adi,adv7282", }, + { .compatible = "adi,adv7282-m", }, { }, }; -- cgit v1.2.3 From 685f11097ab21221d734a259f2ba20684ffe3f05 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 May 2016 14:06:09 -0300 Subject: [media] update cx23885 and em28xx cardlists Some new boards were added without updating those lists. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 2 ++ Documentation/video4linux/CARDLIST.em28xx | 1 + 2 files changed, 3 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 44a4cfbfdc40..85a8fdcfcdaa 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -52,3 +52,5 @@ 51 -> DVBSky T982 [4254:0982] 52 -> Hauppauge WinTV-HVR5525 [0070:f038] 53 -> Hauppauge WinTV Starburst [0070:c12a] + 54 -> ViewCast 260e [1576:0260] + 55 -> ViewCast 460e [1576:0460] diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 67209998a439..ae9d5a852305 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -96,3 +96,4 @@ 95 -> Leadtek VC100 (em2861) [0413:6f07] 96 -> Terratec Cinergy T2 Stick HD (em28178) 97 -> Elgato EyeTV Hybrid 2008 INT (em2884) [0fd9:0018] + 98 -> PLEX PX-BCUD (em28178) -- cgit v1.2.3 From 628288d08a6162aa50e4dbd5918a9867b4c40e2f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 May 2016 14:15:00 -0300 Subject: [media] em28xx: add missing USB IDs Add missing USB id's for em281xx devices. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index ae9d5a852305..82eb4e4b6f69 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -76,9 +76,9 @@ 75 -> Dikom DK300 (em2882) 76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340] 77 -> EM2874 Leadership ISDBT (em2874) - 78 -> PCTV nanoStick T2 290e (em28174) + 78 -> PCTV nanoStick T2 290e (em28174) [2013:024f] 79 -> Terratec Cinergy H5 (em2884) [eb1a:2885,0ccd:10a2,0ccd:10ad,0ccd:10b6] - 80 -> PCTV DVB-S2 Stick (460e) (em28174) + 80 -> PCTV DVB-S2 Stick (460e) (em28174) [2013:024c] 81 -> Hauppauge WinTV HVR 930C (em2884) [2040:1605] 82 -> Terratec Cinergy HTC Stick (em2884) [0ccd:00b2] 83 -> Honestech Vidbox NW03 (em2860) [eb1a:5006] @@ -90,10 +90,10 @@ 89 -> Delock 61959 (em2874) [1b80:e1cc] 90 -> KWorld USB ATSC TV Stick UB435-Q V2 (em2874) [1b80:e346] 91 -> SpeedLink Vicious And Devine Laplace webcam (em2765) [1ae7:9003,1ae7:9004] - 92 -> PCTV DVB-S2 Stick (461e) (em28178) + 92 -> PCTV DVB-S2 Stick (461e) (em28178) [2013:0258] 93 -> KWorld USB ATSC TV Stick UB435-Q V3 (em2874) [1b80:e34c] - 94 -> PCTV tripleStick (292e) (em28178) + 94 -> PCTV tripleStick (292e) (em28178) [2013:025f,2040:0264] 95 -> Leadtek VC100 (em2861) [0413:6f07] - 96 -> Terratec Cinergy T2 Stick HD (em28178) + 96 -> Terratec Cinergy T2 Stick HD (em28178) [eb1a:8179] 97 -> Elgato EyeTV Hybrid 2008 INT (em2884) [0fd9:0018] - 98 -> PLEX PX-BCUD (em28178) + 98 -> PLEX PX-BCUD (em28178) [3275:0085] -- cgit v1.2.3 From 11a2a949d05e9d2d9823f0c45fa476743d9e462b Mon Sep 17 00:00:00 2001 From: Olli Salonen Date: Mon, 4 Apr 2016 12:12:52 -0300 Subject: [media] em28xx: add support for Hauppauge WinTV-dualHD DVB tuner Hauppauge WinTV-dualHD is a USB 2.0 dual DVB-T/T2/C tuner with following components: USB bridge: Empia EM28274 (chip id is the same as EM28174) Demodulator: 2x Silicon Labs Si2168-B40 Tuner: 2x Silicon Labs Si2157-A30 This patch adds support only for the first tuner. The demodulator needs firmware, available for example here: http://palosaari.fi/linux/v4l-dvb/firmware/Si2168/Si2168-B40/4.0.11/ The demodulators sit on the same I2C bus and their addresses are 0x64 and 0x67. The tuners are behind the demodulators and their addresses are 0x60 and 0x63. Signed-off-by: Olli Salonen Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/usb/em28xx/em28xx-cards.c | 58 ++++++++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx-dvb.c | 64 +++++++++++++++++++++++++++++++ drivers/media/usb/em28xx/em28xx-reg.h | 13 +++++++ drivers/media/usb/em28xx/em28xx.h | 2 + 5 files changed, 138 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 82eb4e4b6f69..6784220c6a16 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -97,3 +97,4 @@ 96 -> Terratec Cinergy T2 Stick HD (em28178) [eb1a:8179] 97 -> Elgato EyeTV Hybrid 2008 INT (em2884) [0fd9:0018] 98 -> PLEX PX-BCUD (em28178) [3275:0085] + 99 -> Hauppauge WinTV-dualHD DVB (em28174) [2040:0265] diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 57c3b905bf0a..e397f544f108 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -506,6 +506,30 @@ static struct em28xx_reg_seq plex_px_bcud[] = { {-1, -1, -1, -1}, }; +/* + * 2040:0265 Hauppauge WinTV-dualHD DVB + * reg 0x80/0x84: + * GPIO_0: Yellow LED tuner 1, 0=on, 1=off + * GPIO_1: Green LED tuner 1, 0=on, 1=off + * GPIO_2: Yellow LED tuner 2, 0=on, 1=off + * GPIO_3: Green LED tuner 2, 0=on, 1=off + * GPIO_5: Reset #2, 0=active + * GPIO_6: Reset #1, 0=active + */ +static struct em28xx_reg_seq hauppauge_dualhd_dvb[] = { + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0}, + {0x0d, 0xff, 0xff, 200}, + {0x50, 0x04, 0xff, 300}, + {EM2874_R80_GPIO_P0_CTRL, 0xbf, 0xff, 100}, /* demod 1 reset */ + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xdf, 0xff, 100}, /* demod 2 reset */ + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100}, + {EM2874_R5F_TS_ENABLE, 0x44, 0xff, 50}, + {EM2874_R5D_TS1_PKT_SIZE, 0x05, 0xff, 50}, + {EM2874_R5E_TS2_PKT_SIZE, 0x05, 0xff, 50}, + {-1, -1, -1, -1}, +}; + /* * Button definitions */ @@ -585,6 +609,22 @@ static struct em28xx_led terratec_grabby_leds[] = { {-1, 0, 0, 0}, }; +static struct em28xx_led hauppauge_dualhd_leds[] = { + { + .role = EM28XX_LED_DIGITAL_CAPTURING, + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, + .gpio_mask = EM_GPIO_1, + .inverted = 1, + }, + { + .role = EM28XX_LED_DIGITAL_CAPTURING_TS2, + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, + .gpio_mask = EM_GPIO_3, + .inverted = 1, + }, + {-1, 0, 0, 0}, +}; + /* * Board definitions */ @@ -2334,6 +2374,21 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = plex_px_bcud, .has_dvb = 1, }, + /* + * 2040:0265 Hauppauge WinTV-dualHD (DVB version). + * Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157 + */ + [EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = { + .name = "Hauppauge WinTV-dualHD DVB", + .def_i2c_bus = 1, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + .tuner_type = TUNER_ABSENT, + .tuner_gpio = hauppauge_dualhd_dvb, + .has_dvb = 1, + .ir_codes = RC_MAP_HAUPPAUGE, + .leds = hauppauge_dualhd_leds, + }, }; EXPORT_SYMBOL_GPL(em28xx_boards); @@ -2457,6 +2512,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, { USB_DEVICE(0x2040, 0x651f), .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, + { USB_DEVICE(0x2040, 0x0265), + .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB }, { USB_DEVICE(0x0438, 0xb002), .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, { USB_DEVICE(0x2001, 0xf112), @@ -2891,6 +2948,7 @@ static void em28xx_card_setup(struct em28xx *dev) case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: + case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: { struct tveeprom tv; diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index fbc4e4b3268e..1a5c01202f73 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1883,6 +1883,70 @@ static int em28xx_dvb_init(struct em28xx *dev) px_bcud_init(dev); } break; + case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: + { + struct i2c_adapter *adapter; + struct i2c_client *client; + struct i2c_board_info info; + struct si2168_config si2168_config; + struct si2157_config si2157_config; + + /* attach demod */ + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &dvb->fe[0]; + si2168_config.ts_mode = SI2168_TS_SERIAL; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2168", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2168_config; + request_module(info.type); + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); + if (client == NULL || client->dev.driver == NULL) { + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_demod = client; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = dvb->fe[0]; + si2157_config.if_port = 1; +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + si2157_config.mdev = dev->media_dev; +#endif + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2157", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module(info.type); + client = i2c_new_device(adapter, &info); + if (client == NULL || client->dev.driver == NULL) { + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + module_put(dvb->i2c_client_demod->dev.driver->owner); + i2c_unregister_device(dvb->i2c_client_demod); + result = -ENODEV; + goto out_free; + } + + dvb->i2c_client_tuner = client; + + } + break; default: em28xx_errdev("/2: The frontend of your DVB/ATSC card" " isn't supported yet\n"); diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 13cbb7f3ea10..afe7a66d7dc8 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -193,6 +193,19 @@ /* em2874 registers */ #define EM2874_R50_IR_CONFIG 0x50 #define EM2874_R51_IR 0x51 +#define EM2874_R5D_TS1_PKT_SIZE 0x5d +#define EM2874_R5E_TS2_PKT_SIZE 0x5e + /* + * For both TS1 and TS2, In isochronous mode: + * 0x01 188 bytes + * 0x02 376 bytes + * 0x03 564 bytes + * 0x04 752 bytes + * 0x05 940 bytes + * In bulk mode: + * 0x01..0xff total packet count in 188-byte + */ + #define EM2874_R5F_TS_ENABLE 0x5f /* em2874/174/84, em25xx, em276x/7x/8x GPIO registers */ diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 9ad1240d5e22..d148463b22c1 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -146,6 +146,7 @@ #define EM28178_BOARD_TERRATEC_T2_STICK_HD 96 #define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008 97 #define EM28178_BOARD_PLEX_PX_BCUD 98 +#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB 99 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -407,6 +408,7 @@ enum em28xx_adecoder { enum em28xx_led_role { EM28XX_LED_ANALOG_CAPTURING = 0, EM28XX_LED_DIGITAL_CAPTURING, + EM28XX_LED_DIGITAL_CAPTURING_TS2, EM28XX_LED_ILLUMINATION, EM28XX_NUM_LED_ROLES, /* must be the last */ }; -- cgit v1.2.3 From 0185f850176201260e0f02c5bccca1defb8e0884 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Apr 2016 10:17:21 -0300 Subject: [media] samples: v4l: from Documentation to samples directory With the new autoksyms support, we can run into a situation where the v4l pci skeleton module is the only one using some exported symbols that get dropped because they are never referenced by the kernel otherwise, causing a build problem: ERROR: "vb2_dma_contig_memops" [Documentation/video4linux/v4l2-pci-skeleton.ko] undefined! ERROR: "vb2_dma_contig_init_ctx_attrs" [Documentation/video4linux/v4l2-pci-skeleton.ko] undefined! ERROR: "v4l2_match_dv_timings" [Documentation/video4linux/v4l2-pci-skeleton.ko] undefined! ERROR: "v4l2_find_dv_timings_cap" [Documentation/video4linux/v4l2-pci-skeleton.ko] undefined! ERROR: "v4l2_valid_dv_timings" [Documentation/video4linux/v4l2-pci-skeleton.ko] undefined! ERROR: "v4l2_enum_dv_timings_cap" [Documentation/video4linux/v4l2-pci-skeleton.ko] undefined! ERROR: "vb2_dma_contig_cleanup_ctx" [Documentation/video4linux/v4l2-pci-skeleton.ko] undefined! Specifically, we do look in the samples directory for users of symbols, but not the Documentation directory. This solves the build problem by moving the connector sample into the same directory as the other samples. Fixes: 23121ca2b56b ("kbuild: create/adjust generated/autoksyms.h") Signed-off-by: Arnd Bergmann --- Documentation/Makefile | 3 +- Documentation/video4linux/Makefile | 1 - Documentation/video4linux/v4l2-framework.txt | 2 +- Documentation/video4linux/v4l2-pci-skeleton.c | 922 -------------------------- samples/Makefile | 2 +- samples/v4l/Makefile | 1 + samples/v4l/v4l2-pci-skeleton.c | 922 ++++++++++++++++++++++++++ 7 files changed, 926 insertions(+), 927 deletions(-) delete mode 100644 Documentation/video4linux/Makefile delete mode 100644 Documentation/video4linux/v4l2-pci-skeleton.c create mode 100644 samples/v4l/Makefile create mode 100644 samples/v4l/v4l2-pci-skeleton.c (limited to 'Documentation') diff --git a/Documentation/Makefile b/Documentation/Makefile index 1207d7907650..f3b04d22957c 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -1,4 +1,3 @@ subdir-y := accounting auxdisplay blackfin connector \ filesystems filesystems ia64 laptops mic misc-devices \ - networking pcmcia prctl ptp timers vDSO video4linux \ - watchdog + networking pcmcia prctl ptp timers vDSO watchdog diff --git a/Documentation/video4linux/Makefile b/Documentation/video4linux/Makefile deleted file mode 100644 index 65a351d75c95..000000000000 --- a/Documentation/video4linux/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_VIDEO_PCI_SKELETON) := v4l2-pci-skeleton.o diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index fa41608ab2b4..cbefc7902f5f 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -35,7 +35,7 @@ need and this same framework should make it much easier to refactor common code into utility functions shared by all drivers. A good example to look at as a reference is the v4l2-pci-skeleton.c -source that is available in this directory. It is a skeleton driver for +source that is available in samples/v4l/. It is a skeleton driver for a PCI capture card, and demonstrates how to use the V4L2 driver framework. It can be used as a template for real PCI video capture driver. diff --git a/Documentation/video4linux/v4l2-pci-skeleton.c b/Documentation/video4linux/v4l2-pci-skeleton.c deleted file mode 100644 index a55cf94ac907..000000000000 --- a/Documentation/video4linux/v4l2-pci-skeleton.c +++ /dev/null @@ -1,922 +0,0 @@ -/* - * This is a V4L2 PCI Skeleton Driver. It gives an initial skeleton source - * for use with other PCI drivers. - * - * This skeleton PCI driver assumes that the card has an S-Video connector as - * input 0 and an HDMI connector as input 1. - * - * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * This program is free software; you may redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_DESCRIPTION("V4L2 PCI Skeleton Driver"); -MODULE_AUTHOR("Hans Verkuil"); -MODULE_LICENSE("GPL v2"); - -/** - * struct skeleton - All internal data for one instance of device - * @pdev: PCI device - * @v4l2_dev: top-level v4l2 device struct - * @vdev: video node structure - * @ctrl_handler: control handler structure - * @lock: ioctl serialization mutex - * @std: current SDTV standard - * @timings: current HDTV timings - * @format: current pix format - * @input: current video input (0 = SDTV, 1 = HDTV) - * @queue: vb2 video capture queue - * @alloc_ctx: vb2 contiguous DMA context - * @qlock: spinlock controlling access to buf_list and sequence - * @buf_list: list of buffers queued for DMA - * @sequence: frame sequence counter - */ -struct skeleton { - struct pci_dev *pdev; - struct v4l2_device v4l2_dev; - struct video_device vdev; - struct v4l2_ctrl_handler ctrl_handler; - struct mutex lock; - v4l2_std_id std; - struct v4l2_dv_timings timings; - struct v4l2_pix_format format; - unsigned input; - - struct vb2_queue queue; - struct vb2_alloc_ctx *alloc_ctx; - - spinlock_t qlock; - struct list_head buf_list; - unsigned field; - unsigned sequence; -}; - -struct skel_buffer { - struct vb2_buffer vb; - struct list_head list; -}; - -static inline struct skel_buffer *to_skel_buffer(struct vb2_buffer *vb2) -{ - return container_of(vb2, struct skel_buffer, vb); -} - -static const struct pci_device_id skeleton_pci_tbl[] = { - /* { PCI_DEVICE(PCI_VENDOR_ID_, PCI_DEVICE_ID_) }, */ - { 0, } -}; -MODULE_DEVICE_TABLE(pci, skeleton_pci_tbl); - -/* - * HDTV: this structure has the capabilities of the HDTV receiver. - * It is used to constrain the huge list of possible formats based - * upon the hardware capabilities. - */ -static const struct v4l2_dv_timings_cap skel_timings_cap = { - .type = V4L2_DV_BT_656_1120, - /* keep this initialization for compatibility with GCC < 4.4.6 */ - .reserved = { 0 }, - V4L2_INIT_BT_TIMINGS( - 720, 1920, /* min/max width */ - 480, 1080, /* min/max height */ - 27000000, 74250000, /* min/max pixelclock*/ - V4L2_DV_BT_STD_CEA861, /* Supported standards */ - /* capabilities */ - V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE - ) -}; - -/* - * Supported SDTV standards. This does the same job as skel_timings_cap, but - * for standard TV formats. - */ -#define SKEL_TVNORMS V4L2_STD_ALL - -/* - * Interrupt handler: typically interrupts happen after a new frame has been - * captured. It is the job of the handler to remove the new frame from the - * internal list and give it back to the vb2 framework, updating the sequence - * counter, field and timestamp at the same time. - */ -static irqreturn_t skeleton_irq(int irq, void *dev_id) -{ -#ifdef TODO - struct skeleton *skel = dev_id; - - /* handle interrupt */ - - /* Once a new frame has been captured, mark it as done like this: */ - if (captured_new_frame) { - ... - spin_lock(&skel->qlock); - list_del(&new_buf->list); - spin_unlock(&skel->qlock); - v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp); - new_buf->vb.v4l2_buf.sequence = skel->sequence++; - new_buf->vb.v4l2_buf.field = skel->field; - if (skel->format.field == V4L2_FIELD_ALTERNATE) { - if (skel->field == V4L2_FIELD_BOTTOM) - skel->field = V4L2_FIELD_TOP; - else if (skel->field == V4L2_FIELD_TOP) - skel->field = V4L2_FIELD_BOTTOM; - } - vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE); - } -#endif - return IRQ_HANDLED; -} - -/* - * Setup the constraints of the queue: besides setting the number of planes - * per buffer and the size and allocation context of each plane, it also - * checks if sufficient buffers have been allocated. Usually 3 is a good - * minimum number: many DMA engines need a minimum of 2 buffers in the - * queue and you need to have another available for userspace processing. - */ -static int queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - struct skeleton *skel = vb2_get_drv_priv(vq); - - skel->field = skel->format.field; - if (skel->field == V4L2_FIELD_ALTERNATE) { - /* - * You cannot use read() with FIELD_ALTERNATE since the field - * information (TOP/BOTTOM) cannot be passed back to the user. - */ - if (vb2_fileio_is_active(vq)) - return -EINVAL; - skel->field = V4L2_FIELD_TOP; - } - - if (vq->num_buffers + *nbuffers < 3) - *nbuffers = 3 - vq->num_buffers; - alloc_ctxs[0] = skel->alloc_ctx; - - if (*nplanes) - return sizes[0] < skel->format.sizeimage ? -EINVAL : 0; - *nplanes = 1; - sizes[0] = skel->format.sizeimage; - return 0; -} - -/* - * Prepare the buffer for queueing to the DMA engine: check and set the - * payload size. - */ -static int buffer_prepare(struct vb2_buffer *vb) -{ - struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue); - unsigned long size = skel->format.sizeimage; - - if (vb2_plane_size(vb, 0) < size) { - dev_err(&skel->pdev->dev, "buffer too small (%lu < %lu)\n", - vb2_plane_size(vb, 0), size); - return -EINVAL; - } - - vb2_set_plane_payload(vb, 0, size); - return 0; -} - -/* - * Queue this buffer to the DMA engine. - */ -static void buffer_queue(struct vb2_buffer *vb) -{ - struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue); - struct skel_buffer *buf = to_skel_buffer(vb); - unsigned long flags; - - spin_lock_irqsave(&skel->qlock, flags); - list_add_tail(&buf->list, &skel->buf_list); - - /* TODO: Update any DMA pointers if necessary */ - - spin_unlock_irqrestore(&skel->qlock, flags); -} - -static void return_all_buffers(struct skeleton *skel, - enum vb2_buffer_state state) -{ - struct skel_buffer *buf, *node; - unsigned long flags; - - spin_lock_irqsave(&skel->qlock, flags); - list_for_each_entry_safe(buf, node, &skel->buf_list, list) { - vb2_buffer_done(&buf->vb, state); - list_del(&buf->list); - } - spin_unlock_irqrestore(&skel->qlock, flags); -} - -/* - * Start streaming. First check if the minimum number of buffers have been - * queued. If not, then return -ENOBUFS and the vb2 framework will call - * this function again the next time a buffer has been queued until enough - * buffers are available to actually start the DMA engine. - */ -static int start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct skeleton *skel = vb2_get_drv_priv(vq); - int ret = 0; - - skel->sequence = 0; - - /* TODO: start DMA */ - - if (ret) { - /* - * In case of an error, return all active buffers to the - * QUEUED state - */ - return_all_buffers(skel, VB2_BUF_STATE_QUEUED); - } - return ret; -} - -/* - * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued - * and passed on to the vb2 framework marked as STATE_ERROR. - */ -static void stop_streaming(struct vb2_queue *vq) -{ - struct skeleton *skel = vb2_get_drv_priv(vq); - - /* TODO: stop DMA */ - - /* Release all active buffers */ - return_all_buffers(skel, VB2_BUF_STATE_ERROR); -} - -/* - * The vb2 queue ops. Note that since q->lock is set we can use the standard - * vb2_ops_wait_prepare/finish helper functions. If q->lock would be NULL, - * then this driver would have to provide these ops. - */ -static struct vb2_ops skel_qops = { - .queue_setup = queue_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .start_streaming = start_streaming, - .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -/* - * Required ioctl querycap. Note that the version field is prefilled with - * the version of the kernel. - */ -static int skeleton_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct skeleton *skel = video_drvdata(file); - - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", - pci_name(skel->pdev)); - return 0; -} - -/* - * Helper function to check and correct struct v4l2_pix_format. It's used - * not only in VIDIOC_TRY/S_FMT, but also elsewhere if changes to the SDTV - * standard, HDTV timings or the video input would require updating the - * current format. - */ -static void skeleton_fill_pix_format(struct skeleton *skel, - struct v4l2_pix_format *pix) -{ - pix->pixelformat = V4L2_PIX_FMT_YUYV; - if (skel->input == 0) { - /* S-Video input */ - pix->width = 720; - pix->height = (skel->std & V4L2_STD_525_60) ? 480 : 576; - pix->field = V4L2_FIELD_INTERLACED; - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - } else { - /* HDMI input */ - pix->width = skel->timings.bt.width; - pix->height = skel->timings.bt.height; - if (skel->timings.bt.interlaced) { - pix->field = V4L2_FIELD_ALTERNATE; - pix->height /= 2; - } else { - pix->field = V4L2_FIELD_NONE; - } - pix->colorspace = V4L2_COLORSPACE_REC709; - } - - /* - * The YUYV format is four bytes for every two pixels, so bytesperline - * is width * 2. - */ - pix->bytesperline = pix->width * 2; - pix->sizeimage = pix->bytesperline * pix->height; - pix->priv = 0; -} - -static int skeleton_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct skeleton *skel = video_drvdata(file); - struct v4l2_pix_format *pix = &f->fmt.pix; - - /* - * Due to historical reasons providing try_fmt with an unsupported - * pixelformat will return -EINVAL for video receivers. Webcam drivers, - * however, will silently correct the pixelformat. Some video capture - * applications rely on this behavior... - */ - if (pix->pixelformat != V4L2_PIX_FMT_YUYV) - return -EINVAL; - skeleton_fill_pix_format(skel, pix); - return 0; -} - -static int skeleton_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct skeleton *skel = video_drvdata(file); - int ret; - - ret = skeleton_try_fmt_vid_cap(file, priv, f); - if (ret) - return ret; - - /* - * It is not allowed to change the format while buffers for use with - * streaming have already been allocated. - */ - if (vb2_is_busy(&skel->queue)) - return -EBUSY; - - /* TODO: change format */ - skel->format = f->fmt.pix; - return 0; -} - -static int skeleton_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct skeleton *skel = video_drvdata(file); - - f->fmt.pix = skel->format; - return 0; -} - -static int skeleton_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (f->index != 0) - return -EINVAL; - - f->pixelformat = V4L2_PIX_FMT_YUYV; - return 0; -} - -static int skeleton_s_std(struct file *file, void *priv, v4l2_std_id std) -{ - struct skeleton *skel = video_drvdata(file); - - /* S_STD is not supported on the HDMI input */ - if (skel->input) - return -ENODATA; - - /* - * No change, so just return. Some applications call S_STD again after - * the buffers for streaming have been set up, so we have to allow for - * this behavior. - */ - if (std == skel->std) - return 0; - - /* - * Changing the standard implies a format change, which is not allowed - * while buffers for use with streaming have already been allocated. - */ - if (vb2_is_busy(&skel->queue)) - return -EBUSY; - - /* TODO: handle changing std */ - - skel->std = std; - - /* Update the internal format */ - skeleton_fill_pix_format(skel, &skel->format); - return 0; -} - -static int skeleton_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct skeleton *skel = video_drvdata(file); - - /* G_STD is not supported on the HDMI input */ - if (skel->input) - return -ENODATA; - - *std = skel->std; - return 0; -} - -/* - * Query the current standard as seen by the hardware. This function shall - * never actually change the standard, it just detects and reports. - * The framework will initially set *std to tvnorms (i.e. the set of - * supported standards by this input), and this function should just AND - * this value. If there is no signal, then *std should be set to 0. - */ -static int skeleton_querystd(struct file *file, void *priv, v4l2_std_id *std) -{ - struct skeleton *skel = video_drvdata(file); - - /* QUERY_STD is not supported on the HDMI input */ - if (skel->input) - return -ENODATA; - -#ifdef TODO - /* - * Query currently seen standard. Initial value of *std is - * V4L2_STD_ALL. This function should look something like this: - */ - get_signal_info(); - if (no_signal) { - *std = 0; - return 0; - } - /* Use signal information to reduce the number of possible standards */ - if (signal_has_525_lines) - *std &= V4L2_STD_525_60; - else - *std &= V4L2_STD_625_50; -#endif - return 0; -} - -static int skeleton_s_dv_timings(struct file *file, void *_fh, - struct v4l2_dv_timings *timings) -{ - struct skeleton *skel = video_drvdata(file); - - /* S_DV_TIMINGS is not supported on the S-Video input */ - if (skel->input == 0) - return -ENODATA; - - /* Quick sanity check */ - if (!v4l2_valid_dv_timings(timings, &skel_timings_cap, NULL, NULL)) - return -EINVAL; - - /* Check if the timings are part of the CEA-861 timings. */ - if (!v4l2_find_dv_timings_cap(timings, &skel_timings_cap, - 0, NULL, NULL)) - return -EINVAL; - - /* Return 0 if the new timings are the same as the current timings. */ - if (v4l2_match_dv_timings(timings, &skel->timings, 0, false)) - return 0; - - /* - * Changing the timings implies a format change, which is not allowed - * while buffers for use with streaming have already been allocated. - */ - if (vb2_is_busy(&skel->queue)) - return -EBUSY; - - /* TODO: Configure new timings */ - - /* Save timings */ - skel->timings = *timings; - - /* Update the internal format */ - skeleton_fill_pix_format(skel, &skel->format); - return 0; -} - -static int skeleton_g_dv_timings(struct file *file, void *_fh, - struct v4l2_dv_timings *timings) -{ - struct skeleton *skel = video_drvdata(file); - - /* G_DV_TIMINGS is not supported on the S-Video input */ - if (skel->input == 0) - return -ENODATA; - - *timings = skel->timings; - return 0; -} - -static int skeleton_enum_dv_timings(struct file *file, void *_fh, - struct v4l2_enum_dv_timings *timings) -{ - struct skeleton *skel = video_drvdata(file); - - /* ENUM_DV_TIMINGS is not supported on the S-Video input */ - if (skel->input == 0) - return -ENODATA; - - return v4l2_enum_dv_timings_cap(timings, &skel_timings_cap, - NULL, NULL); -} - -/* - * Query the current timings as seen by the hardware. This function shall - * never actually change the timings, it just detects and reports. - * If no signal is detected, then return -ENOLINK. If the hardware cannot - * lock to the signal, then return -ENOLCK. If the signal is out of range - * of the capabilities of the system (e.g., it is possible that the receiver - * can lock but that the DMA engine it is connected to cannot handle - * pixelclocks above a certain frequency), then -ERANGE is returned. - */ -static int skeleton_query_dv_timings(struct file *file, void *_fh, - struct v4l2_dv_timings *timings) -{ - struct skeleton *skel = video_drvdata(file); - - /* QUERY_DV_TIMINGS is not supported on the S-Video input */ - if (skel->input == 0) - return -ENODATA; - -#ifdef TODO - /* - * Query currently seen timings. This function should look - * something like this: - */ - detect_timings(); - if (no_signal) - return -ENOLINK; - if (cannot_lock_to_signal) - return -ENOLCK; - if (signal_out_of_range_of_capabilities) - return -ERANGE; - - /* Useful for debugging */ - v4l2_print_dv_timings(skel->v4l2_dev.name, "query_dv_timings:", - timings, true); -#endif - return 0; -} - -static int skeleton_dv_timings_cap(struct file *file, void *fh, - struct v4l2_dv_timings_cap *cap) -{ - struct skeleton *skel = video_drvdata(file); - - /* DV_TIMINGS_CAP is not supported on the S-Video input */ - if (skel->input == 0) - return -ENODATA; - *cap = skel_timings_cap; - return 0; -} - -static int skeleton_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - if (i->index > 1) - return -EINVAL; - - i->type = V4L2_INPUT_TYPE_CAMERA; - if (i->index == 0) { - i->std = SKEL_TVNORMS; - strlcpy(i->name, "S-Video", sizeof(i->name)); - i->capabilities = V4L2_IN_CAP_STD; - } else { - i->std = 0; - strlcpy(i->name, "HDMI", sizeof(i->name)); - i->capabilities = V4L2_IN_CAP_DV_TIMINGS; - } - return 0; -} - -static int skeleton_s_input(struct file *file, void *priv, unsigned int i) -{ - struct skeleton *skel = video_drvdata(file); - - if (i > 1) - return -EINVAL; - - /* - * Changing the input implies a format change, which is not allowed - * while buffers for use with streaming have already been allocated. - */ - if (vb2_is_busy(&skel->queue)) - return -EBUSY; - - skel->input = i; - /* - * Update tvnorms. The tvnorms value is used by the core to implement - * VIDIOC_ENUMSTD so it has to be correct. If tvnorms == 0, then - * ENUMSTD will return -ENODATA. - */ - skel->vdev.tvnorms = i ? 0 : SKEL_TVNORMS; - - /* Update the internal format */ - skeleton_fill_pix_format(skel, &skel->format); - return 0; -} - -static int skeleton_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct skeleton *skel = video_drvdata(file); - - *i = skel->input; - return 0; -} - -/* The control handler. */ -static int skeleton_s_ctrl(struct v4l2_ctrl *ctrl) -{ - /*struct skeleton *skel = - container_of(ctrl->handler, struct skeleton, ctrl_handler);*/ - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - /* TODO: set brightness to ctrl->val */ - break; - case V4L2_CID_CONTRAST: - /* TODO: set contrast to ctrl->val */ - break; - case V4L2_CID_SATURATION: - /* TODO: set saturation to ctrl->val */ - break; - case V4L2_CID_HUE: - /* TODO: set hue to ctrl->val */ - break; - default: - return -EINVAL; - } - return 0; -} - -/* ------------------------------------------------------------------ - File operations for the device - ------------------------------------------------------------------*/ - -static const struct v4l2_ctrl_ops skel_ctrl_ops = { - .s_ctrl = skeleton_s_ctrl, -}; - -/* - * The set of all supported ioctls. Note that all the streaming ioctls - * use the vb2 helper functions that take care of all the locking and - * that also do ownership tracking (i.e. only the filehandle that requested - * the buffers can call the streaming ioctls, all other filehandles will - * receive -EBUSY if they attempt to call the same streaming ioctls). - * - * The last three ioctls also use standard helper functions: these implement - * standard behavior for drivers with controls. - */ -static const struct v4l2_ioctl_ops skel_ioctl_ops = { - .vidioc_querycap = skeleton_querycap, - .vidioc_try_fmt_vid_cap = skeleton_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = skeleton_s_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = skeleton_g_fmt_vid_cap, - .vidioc_enum_fmt_vid_cap = skeleton_enum_fmt_vid_cap, - - .vidioc_g_std = skeleton_g_std, - .vidioc_s_std = skeleton_s_std, - .vidioc_querystd = skeleton_querystd, - - .vidioc_s_dv_timings = skeleton_s_dv_timings, - .vidioc_g_dv_timings = skeleton_g_dv_timings, - .vidioc_enum_dv_timings = skeleton_enum_dv_timings, - .vidioc_query_dv_timings = skeleton_query_dv_timings, - .vidioc_dv_timings_cap = skeleton_dv_timings_cap, - - .vidioc_enum_input = skeleton_enum_input, - .vidioc_g_input = skeleton_g_input, - .vidioc_s_input = skeleton_s_input, - - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_expbuf = vb2_ioctl_expbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -/* - * The set of file operations. Note that all these ops are standard core - * helper functions. - */ -static const struct v4l2_file_operations skel_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .unlocked_ioctl = video_ioctl2, - .read = vb2_fop_read, - .mmap = vb2_fop_mmap, - .poll = vb2_fop_poll, -}; - -/* - * The initial setup of this device instance. Note that the initial state of - * the driver should be complete. So the initial format, standard, timings - * and video input should all be initialized to some reasonable value. - */ -static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - /* The initial timings are chosen to be 720p60. */ - static const struct v4l2_dv_timings timings_def = - V4L2_DV_BT_CEA_1280X720P60; - struct skeleton *skel; - struct video_device *vdev; - struct v4l2_ctrl_handler *hdl; - struct vb2_queue *q; - int ret; - - /* Enable PCI */ - ret = pci_enable_device(pdev); - if (ret) - return ret; - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - dev_err(&pdev->dev, "no suitable DMA available.\n"); - goto disable_pci; - } - - /* Allocate a new instance */ - skel = devm_kzalloc(&pdev->dev, sizeof(struct skeleton), GFP_KERNEL); - if (!skel) - return -ENOMEM; - - /* Allocate the interrupt */ - ret = devm_request_irq(&pdev->dev, pdev->irq, - skeleton_irq, 0, KBUILD_MODNAME, skel); - if (ret) { - dev_err(&pdev->dev, "request_irq failed\n"); - goto disable_pci; - } - skel->pdev = pdev; - - /* Fill in the initial format-related settings */ - skel->timings = timings_def; - skel->std = V4L2_STD_625_50; - skeleton_fill_pix_format(skel, &skel->format); - - /* Initialize the top-level structure */ - ret = v4l2_device_register(&pdev->dev, &skel->v4l2_dev); - if (ret) - goto disable_pci; - - mutex_init(&skel->lock); - - /* Add the controls */ - hdl = &skel->ctrl_handler; - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); - v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 16); - v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 127); - v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, - V4L2_CID_HUE, -128, 127, 1, 0); - if (hdl->error) { - ret = hdl->error; - goto free_hdl; - } - skel->v4l2_dev.ctrl_handler = hdl; - - /* Initialize the vb2 queue */ - q = &skel->queue; - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; - q->drv_priv = skel; - q->buf_struct_size = sizeof(struct skel_buffer); - q->ops = &skel_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - /* - * Assume that this DMA engine needs to have at least two buffers - * available before it can be started. The start_streaming() op - * won't be called until at least this many buffers are queued up. - */ - q->min_buffers_needed = 2; - /* - * The serialization lock for the streaming ioctls. This is the same - * as the main serialization lock, but if some of the non-streaming - * ioctls could take a long time to execute, then you might want to - * have a different lock here to prevent VIDIOC_DQBUF from being - * blocked while waiting for another action to finish. This is - * generally not needed for PCI devices, but USB devices usually do - * want a separate lock here. - */ - q->lock = &skel->lock; - /* - * Since this driver can only do 32-bit DMA we must make sure that - * the vb2 core will allocate the buffers in 32-bit DMA memory. - */ - q->gfp_flags = GFP_DMA32; - ret = vb2_queue_init(q); - if (ret) - goto free_hdl; - - skel->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); - if (IS_ERR(skel->alloc_ctx)) { - dev_err(&pdev->dev, "Can't allocate buffer context"); - ret = PTR_ERR(skel->alloc_ctx); - goto free_hdl; - } - INIT_LIST_HEAD(&skel->buf_list); - spin_lock_init(&skel->qlock); - - /* Initialize the video_device structure */ - vdev = &skel->vdev; - strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); - /* - * There is nothing to clean up, so release is set to an empty release - * function. The release callback must be non-NULL. - */ - vdev->release = video_device_release_empty; - vdev->fops = &skel_fops, - vdev->ioctl_ops = &skel_ioctl_ops, - vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - /* - * The main serialization lock. All ioctls are serialized by this - * lock. Exception: if q->lock is set, then the streaming ioctls - * are serialized by that separate lock. - */ - vdev->lock = &skel->lock; - vdev->queue = q; - vdev->v4l2_dev = &skel->v4l2_dev; - /* Supported SDTV standards, if any */ - vdev->tvnorms = SKEL_TVNORMS; - video_set_drvdata(vdev, skel); - - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); - if (ret) - goto free_ctx; - - dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n"); - return 0; - -free_ctx: - vb2_dma_contig_cleanup_ctx(skel->alloc_ctx); -free_hdl: - v4l2_ctrl_handler_free(&skel->ctrl_handler); - v4l2_device_unregister(&skel->v4l2_dev); -disable_pci: - pci_disable_device(pdev); - return ret; -} - -static void skeleton_remove(struct pci_dev *pdev) -{ - struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); - struct skeleton *skel = container_of(v4l2_dev, struct skeleton, v4l2_dev); - - video_unregister_device(&skel->vdev); - v4l2_ctrl_handler_free(&skel->ctrl_handler); - vb2_dma_contig_cleanup_ctx(skel->alloc_ctx); - v4l2_device_unregister(&skel->v4l2_dev); - pci_disable_device(skel->pdev); -} - -static struct pci_driver skeleton_driver = { - .name = KBUILD_MODNAME, - .probe = skeleton_probe, - .remove = skeleton_remove, - .id_table = skeleton_pci_tbl, -}; - -module_pci_driver(skeleton_driver); diff --git a/samples/Makefile b/samples/Makefile index 48001d7e23f0..ad440d670cdb 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ - configfs/ + configfs/ v4l/ diff --git a/samples/v4l/Makefile b/samples/v4l/Makefile new file mode 100644 index 000000000000..65a351d75c95 --- /dev/null +++ b/samples/v4l/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_PCI_SKELETON) := v4l2-pci-skeleton.o diff --git a/samples/v4l/v4l2-pci-skeleton.c b/samples/v4l/v4l2-pci-skeleton.c new file mode 100644 index 000000000000..a55cf94ac907 --- /dev/null +++ b/samples/v4l/v4l2-pci-skeleton.c @@ -0,0 +1,922 @@ +/* + * This is a V4L2 PCI Skeleton Driver. It gives an initial skeleton source + * for use with other PCI drivers. + * + * This skeleton PCI driver assumes that the card has an S-Video connector as + * input 0 and an HDMI connector as input 1. + * + * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("V4L2 PCI Skeleton Driver"); +MODULE_AUTHOR("Hans Verkuil"); +MODULE_LICENSE("GPL v2"); + +/** + * struct skeleton - All internal data for one instance of device + * @pdev: PCI device + * @v4l2_dev: top-level v4l2 device struct + * @vdev: video node structure + * @ctrl_handler: control handler structure + * @lock: ioctl serialization mutex + * @std: current SDTV standard + * @timings: current HDTV timings + * @format: current pix format + * @input: current video input (0 = SDTV, 1 = HDTV) + * @queue: vb2 video capture queue + * @alloc_ctx: vb2 contiguous DMA context + * @qlock: spinlock controlling access to buf_list and sequence + * @buf_list: list of buffers queued for DMA + * @sequence: frame sequence counter + */ +struct skeleton { + struct pci_dev *pdev; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct v4l2_ctrl_handler ctrl_handler; + struct mutex lock; + v4l2_std_id std; + struct v4l2_dv_timings timings; + struct v4l2_pix_format format; + unsigned input; + + struct vb2_queue queue; + struct vb2_alloc_ctx *alloc_ctx; + + spinlock_t qlock; + struct list_head buf_list; + unsigned field; + unsigned sequence; +}; + +struct skel_buffer { + struct vb2_buffer vb; + struct list_head list; +}; + +static inline struct skel_buffer *to_skel_buffer(struct vb2_buffer *vb2) +{ + return container_of(vb2, struct skel_buffer, vb); +} + +static const struct pci_device_id skeleton_pci_tbl[] = { + /* { PCI_DEVICE(PCI_VENDOR_ID_, PCI_DEVICE_ID_) }, */ + { 0, } +}; +MODULE_DEVICE_TABLE(pci, skeleton_pci_tbl); + +/* + * HDTV: this structure has the capabilities of the HDTV receiver. + * It is used to constrain the huge list of possible formats based + * upon the hardware capabilities. + */ +static const struct v4l2_dv_timings_cap skel_timings_cap = { + .type = V4L2_DV_BT_656_1120, + /* keep this initialization for compatibility with GCC < 4.4.6 */ + .reserved = { 0 }, + V4L2_INIT_BT_TIMINGS( + 720, 1920, /* min/max width */ + 480, 1080, /* min/max height */ + 27000000, 74250000, /* min/max pixelclock*/ + V4L2_DV_BT_STD_CEA861, /* Supported standards */ + /* capabilities */ + V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE + ) +}; + +/* + * Supported SDTV standards. This does the same job as skel_timings_cap, but + * for standard TV formats. + */ +#define SKEL_TVNORMS V4L2_STD_ALL + +/* + * Interrupt handler: typically interrupts happen after a new frame has been + * captured. It is the job of the handler to remove the new frame from the + * internal list and give it back to the vb2 framework, updating the sequence + * counter, field and timestamp at the same time. + */ +static irqreturn_t skeleton_irq(int irq, void *dev_id) +{ +#ifdef TODO + struct skeleton *skel = dev_id; + + /* handle interrupt */ + + /* Once a new frame has been captured, mark it as done like this: */ + if (captured_new_frame) { + ... + spin_lock(&skel->qlock); + list_del(&new_buf->list); + spin_unlock(&skel->qlock); + v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp); + new_buf->vb.v4l2_buf.sequence = skel->sequence++; + new_buf->vb.v4l2_buf.field = skel->field; + if (skel->format.field == V4L2_FIELD_ALTERNATE) { + if (skel->field == V4L2_FIELD_BOTTOM) + skel->field = V4L2_FIELD_TOP; + else if (skel->field == V4L2_FIELD_TOP) + skel->field = V4L2_FIELD_BOTTOM; + } + vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE); + } +#endif + return IRQ_HANDLED; +} + +/* + * Setup the constraints of the queue: besides setting the number of planes + * per buffer and the size and allocation context of each plane, it also + * checks if sufficient buffers have been allocated. Usually 3 is a good + * minimum number: many DMA engines need a minimum of 2 buffers in the + * queue and you need to have another available for userspace processing. + */ +static int queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct skeleton *skel = vb2_get_drv_priv(vq); + + skel->field = skel->format.field; + if (skel->field == V4L2_FIELD_ALTERNATE) { + /* + * You cannot use read() with FIELD_ALTERNATE since the field + * information (TOP/BOTTOM) cannot be passed back to the user. + */ + if (vb2_fileio_is_active(vq)) + return -EINVAL; + skel->field = V4L2_FIELD_TOP; + } + + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; + alloc_ctxs[0] = skel->alloc_ctx; + + if (*nplanes) + return sizes[0] < skel->format.sizeimage ? -EINVAL : 0; + *nplanes = 1; + sizes[0] = skel->format.sizeimage; + return 0; +} + +/* + * Prepare the buffer for queueing to the DMA engine: check and set the + * payload size. + */ +static int buffer_prepare(struct vb2_buffer *vb) +{ + struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue); + unsigned long size = skel->format.sizeimage; + + if (vb2_plane_size(vb, 0) < size) { + dev_err(&skel->pdev->dev, "buffer too small (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); + return -EINVAL; + } + + vb2_set_plane_payload(vb, 0, size); + return 0; +} + +/* + * Queue this buffer to the DMA engine. + */ +static void buffer_queue(struct vb2_buffer *vb) +{ + struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue); + struct skel_buffer *buf = to_skel_buffer(vb); + unsigned long flags; + + spin_lock_irqsave(&skel->qlock, flags); + list_add_tail(&buf->list, &skel->buf_list); + + /* TODO: Update any DMA pointers if necessary */ + + spin_unlock_irqrestore(&skel->qlock, flags); +} + +static void return_all_buffers(struct skeleton *skel, + enum vb2_buffer_state state) +{ + struct skel_buffer *buf, *node; + unsigned long flags; + + spin_lock_irqsave(&skel->qlock, flags); + list_for_each_entry_safe(buf, node, &skel->buf_list, list) { + vb2_buffer_done(&buf->vb, state); + list_del(&buf->list); + } + spin_unlock_irqrestore(&skel->qlock, flags); +} + +/* + * Start streaming. First check if the minimum number of buffers have been + * queued. If not, then return -ENOBUFS and the vb2 framework will call + * this function again the next time a buffer has been queued until enough + * buffers are available to actually start the DMA engine. + */ +static int start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct skeleton *skel = vb2_get_drv_priv(vq); + int ret = 0; + + skel->sequence = 0; + + /* TODO: start DMA */ + + if (ret) { + /* + * In case of an error, return all active buffers to the + * QUEUED state + */ + return_all_buffers(skel, VB2_BUF_STATE_QUEUED); + } + return ret; +} + +/* + * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued + * and passed on to the vb2 framework marked as STATE_ERROR. + */ +static void stop_streaming(struct vb2_queue *vq) +{ + struct skeleton *skel = vb2_get_drv_priv(vq); + + /* TODO: stop DMA */ + + /* Release all active buffers */ + return_all_buffers(skel, VB2_BUF_STATE_ERROR); +} + +/* + * The vb2 queue ops. Note that since q->lock is set we can use the standard + * vb2_ops_wait_prepare/finish helper functions. If q->lock would be NULL, + * then this driver would have to provide these ops. + */ +static struct vb2_ops skel_qops = { + .queue_setup = queue_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .start_streaming = start_streaming, + .stop_streaming = stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +/* + * Required ioctl querycap. Note that the version field is prefilled with + * the version of the kernel. + */ +static int skeleton_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct skeleton *skel = video_drvdata(file); + + strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", + pci_name(skel->pdev)); + return 0; +} + +/* + * Helper function to check and correct struct v4l2_pix_format. It's used + * not only in VIDIOC_TRY/S_FMT, but also elsewhere if changes to the SDTV + * standard, HDTV timings or the video input would require updating the + * current format. + */ +static void skeleton_fill_pix_format(struct skeleton *skel, + struct v4l2_pix_format *pix) +{ + pix->pixelformat = V4L2_PIX_FMT_YUYV; + if (skel->input == 0) { + /* S-Video input */ + pix->width = 720; + pix->height = (skel->std & V4L2_STD_525_60) ? 480 : 576; + pix->field = V4L2_FIELD_INTERLACED; + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; + } else { + /* HDMI input */ + pix->width = skel->timings.bt.width; + pix->height = skel->timings.bt.height; + if (skel->timings.bt.interlaced) { + pix->field = V4L2_FIELD_ALTERNATE; + pix->height /= 2; + } else { + pix->field = V4L2_FIELD_NONE; + } + pix->colorspace = V4L2_COLORSPACE_REC709; + } + + /* + * The YUYV format is four bytes for every two pixels, so bytesperline + * is width * 2. + */ + pix->bytesperline = pix->width * 2; + pix->sizeimage = pix->bytesperline * pix->height; + pix->priv = 0; +} + +static int skeleton_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct skeleton *skel = video_drvdata(file); + struct v4l2_pix_format *pix = &f->fmt.pix; + + /* + * Due to historical reasons providing try_fmt with an unsupported + * pixelformat will return -EINVAL for video receivers. Webcam drivers, + * however, will silently correct the pixelformat. Some video capture + * applications rely on this behavior... + */ + if (pix->pixelformat != V4L2_PIX_FMT_YUYV) + return -EINVAL; + skeleton_fill_pix_format(skel, pix); + return 0; +} + +static int skeleton_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct skeleton *skel = video_drvdata(file); + int ret; + + ret = skeleton_try_fmt_vid_cap(file, priv, f); + if (ret) + return ret; + + /* + * It is not allowed to change the format while buffers for use with + * streaming have already been allocated. + */ + if (vb2_is_busy(&skel->queue)) + return -EBUSY; + + /* TODO: change format */ + skel->format = f->fmt.pix; + return 0; +} + +static int skeleton_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct skeleton *skel = video_drvdata(file); + + f->fmt.pix = skel->format; + return 0; +} + +static int skeleton_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index != 0) + return -EINVAL; + + f->pixelformat = V4L2_PIX_FMT_YUYV; + return 0; +} + +static int skeleton_s_std(struct file *file, void *priv, v4l2_std_id std) +{ + struct skeleton *skel = video_drvdata(file); + + /* S_STD is not supported on the HDMI input */ + if (skel->input) + return -ENODATA; + + /* + * No change, so just return. Some applications call S_STD again after + * the buffers for streaming have been set up, so we have to allow for + * this behavior. + */ + if (std == skel->std) + return 0; + + /* + * Changing the standard implies a format change, which is not allowed + * while buffers for use with streaming have already been allocated. + */ + if (vb2_is_busy(&skel->queue)) + return -EBUSY; + + /* TODO: handle changing std */ + + skel->std = std; + + /* Update the internal format */ + skeleton_fill_pix_format(skel, &skel->format); + return 0; +} + +static int skeleton_g_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct skeleton *skel = video_drvdata(file); + + /* G_STD is not supported on the HDMI input */ + if (skel->input) + return -ENODATA; + + *std = skel->std; + return 0; +} + +/* + * Query the current standard as seen by the hardware. This function shall + * never actually change the standard, it just detects and reports. + * The framework will initially set *std to tvnorms (i.e. the set of + * supported standards by this input), and this function should just AND + * this value. If there is no signal, then *std should be set to 0. + */ +static int skeleton_querystd(struct file *file, void *priv, v4l2_std_id *std) +{ + struct skeleton *skel = video_drvdata(file); + + /* QUERY_STD is not supported on the HDMI input */ + if (skel->input) + return -ENODATA; + +#ifdef TODO + /* + * Query currently seen standard. Initial value of *std is + * V4L2_STD_ALL. This function should look something like this: + */ + get_signal_info(); + if (no_signal) { + *std = 0; + return 0; + } + /* Use signal information to reduce the number of possible standards */ + if (signal_has_525_lines) + *std &= V4L2_STD_525_60; + else + *std &= V4L2_STD_625_50; +#endif + return 0; +} + +static int skeleton_s_dv_timings(struct file *file, void *_fh, + struct v4l2_dv_timings *timings) +{ + struct skeleton *skel = video_drvdata(file); + + /* S_DV_TIMINGS is not supported on the S-Video input */ + if (skel->input == 0) + return -ENODATA; + + /* Quick sanity check */ + if (!v4l2_valid_dv_timings(timings, &skel_timings_cap, NULL, NULL)) + return -EINVAL; + + /* Check if the timings are part of the CEA-861 timings. */ + if (!v4l2_find_dv_timings_cap(timings, &skel_timings_cap, + 0, NULL, NULL)) + return -EINVAL; + + /* Return 0 if the new timings are the same as the current timings. */ + if (v4l2_match_dv_timings(timings, &skel->timings, 0, false)) + return 0; + + /* + * Changing the timings implies a format change, which is not allowed + * while buffers for use with streaming have already been allocated. + */ + if (vb2_is_busy(&skel->queue)) + return -EBUSY; + + /* TODO: Configure new timings */ + + /* Save timings */ + skel->timings = *timings; + + /* Update the internal format */ + skeleton_fill_pix_format(skel, &skel->format); + return 0; +} + +static int skeleton_g_dv_timings(struct file *file, void *_fh, + struct v4l2_dv_timings *timings) +{ + struct skeleton *skel = video_drvdata(file); + + /* G_DV_TIMINGS is not supported on the S-Video input */ + if (skel->input == 0) + return -ENODATA; + + *timings = skel->timings; + return 0; +} + +static int skeleton_enum_dv_timings(struct file *file, void *_fh, + struct v4l2_enum_dv_timings *timings) +{ + struct skeleton *skel = video_drvdata(file); + + /* ENUM_DV_TIMINGS is not supported on the S-Video input */ + if (skel->input == 0) + return -ENODATA; + + return v4l2_enum_dv_timings_cap(timings, &skel_timings_cap, + NULL, NULL); +} + +/* + * Query the current timings as seen by the hardware. This function shall + * never actually change the timings, it just detects and reports. + * If no signal is detected, then return -ENOLINK. If the hardware cannot + * lock to the signal, then return -ENOLCK. If the signal is out of range + * of the capabilities of the system (e.g., it is possible that the receiver + * can lock but that the DMA engine it is connected to cannot handle + * pixelclocks above a certain frequency), then -ERANGE is returned. + */ +static int skeleton_query_dv_timings(struct file *file, void *_fh, + struct v4l2_dv_timings *timings) +{ + struct skeleton *skel = video_drvdata(file); + + /* QUERY_DV_TIMINGS is not supported on the S-Video input */ + if (skel->input == 0) + return -ENODATA; + +#ifdef TODO + /* + * Query currently seen timings. This function should look + * something like this: + */ + detect_timings(); + if (no_signal) + return -ENOLINK; + if (cannot_lock_to_signal) + return -ENOLCK; + if (signal_out_of_range_of_capabilities) + return -ERANGE; + + /* Useful for debugging */ + v4l2_print_dv_timings(skel->v4l2_dev.name, "query_dv_timings:", + timings, true); +#endif + return 0; +} + +static int skeleton_dv_timings_cap(struct file *file, void *fh, + struct v4l2_dv_timings_cap *cap) +{ + struct skeleton *skel = video_drvdata(file); + + /* DV_TIMINGS_CAP is not supported on the S-Video input */ + if (skel->input == 0) + return -ENODATA; + *cap = skel_timings_cap; + return 0; +} + +static int skeleton_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index > 1) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_CAMERA; + if (i->index == 0) { + i->std = SKEL_TVNORMS; + strlcpy(i->name, "S-Video", sizeof(i->name)); + i->capabilities = V4L2_IN_CAP_STD; + } else { + i->std = 0; + strlcpy(i->name, "HDMI", sizeof(i->name)); + i->capabilities = V4L2_IN_CAP_DV_TIMINGS; + } + return 0; +} + +static int skeleton_s_input(struct file *file, void *priv, unsigned int i) +{ + struct skeleton *skel = video_drvdata(file); + + if (i > 1) + return -EINVAL; + + /* + * Changing the input implies a format change, which is not allowed + * while buffers for use with streaming have already been allocated. + */ + if (vb2_is_busy(&skel->queue)) + return -EBUSY; + + skel->input = i; + /* + * Update tvnorms. The tvnorms value is used by the core to implement + * VIDIOC_ENUMSTD so it has to be correct. If tvnorms == 0, then + * ENUMSTD will return -ENODATA. + */ + skel->vdev.tvnorms = i ? 0 : SKEL_TVNORMS; + + /* Update the internal format */ + skeleton_fill_pix_format(skel, &skel->format); + return 0; +} + +static int skeleton_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct skeleton *skel = video_drvdata(file); + + *i = skel->input; + return 0; +} + +/* The control handler. */ +static int skeleton_s_ctrl(struct v4l2_ctrl *ctrl) +{ + /*struct skeleton *skel = + container_of(ctrl->handler, struct skeleton, ctrl_handler);*/ + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + /* TODO: set brightness to ctrl->val */ + break; + case V4L2_CID_CONTRAST: + /* TODO: set contrast to ctrl->val */ + break; + case V4L2_CID_SATURATION: + /* TODO: set saturation to ctrl->val */ + break; + case V4L2_CID_HUE: + /* TODO: set hue to ctrl->val */ + break; + default: + return -EINVAL; + } + return 0; +} + +/* ------------------------------------------------------------------ + File operations for the device + ------------------------------------------------------------------*/ + +static const struct v4l2_ctrl_ops skel_ctrl_ops = { + .s_ctrl = skeleton_s_ctrl, +}; + +/* + * The set of all supported ioctls. Note that all the streaming ioctls + * use the vb2 helper functions that take care of all the locking and + * that also do ownership tracking (i.e. only the filehandle that requested + * the buffers can call the streaming ioctls, all other filehandles will + * receive -EBUSY if they attempt to call the same streaming ioctls). + * + * The last three ioctls also use standard helper functions: these implement + * standard behavior for drivers with controls. + */ +static const struct v4l2_ioctl_ops skel_ioctl_ops = { + .vidioc_querycap = skeleton_querycap, + .vidioc_try_fmt_vid_cap = skeleton_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = skeleton_s_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = skeleton_g_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap = skeleton_enum_fmt_vid_cap, + + .vidioc_g_std = skeleton_g_std, + .vidioc_s_std = skeleton_s_std, + .vidioc_querystd = skeleton_querystd, + + .vidioc_s_dv_timings = skeleton_s_dv_timings, + .vidioc_g_dv_timings = skeleton_g_dv_timings, + .vidioc_enum_dv_timings = skeleton_enum_dv_timings, + .vidioc_query_dv_timings = skeleton_query_dv_timings, + .vidioc_dv_timings_cap = skeleton_dv_timings_cap, + + .vidioc_enum_input = skeleton_enum_input, + .vidioc_g_input = skeleton_g_input, + .vidioc_s_input = skeleton_s_input, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +/* + * The set of file operations. Note that all these ops are standard core + * helper functions. + */ +static const struct v4l2_file_operations skel_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .unlocked_ioctl = video_ioctl2, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, + .poll = vb2_fop_poll, +}; + +/* + * The initial setup of this device instance. Note that the initial state of + * the driver should be complete. So the initial format, standard, timings + * and video input should all be initialized to some reasonable value. + */ +static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + /* The initial timings are chosen to be 720p60. */ + static const struct v4l2_dv_timings timings_def = + V4L2_DV_BT_CEA_1280X720P60; + struct skeleton *skel; + struct video_device *vdev; + struct v4l2_ctrl_handler *hdl; + struct vb2_queue *q; + int ret; + + /* Enable PCI */ + ret = pci_enable_device(pdev); + if (ret) + return ret; + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(&pdev->dev, "no suitable DMA available.\n"); + goto disable_pci; + } + + /* Allocate a new instance */ + skel = devm_kzalloc(&pdev->dev, sizeof(struct skeleton), GFP_KERNEL); + if (!skel) + return -ENOMEM; + + /* Allocate the interrupt */ + ret = devm_request_irq(&pdev->dev, pdev->irq, + skeleton_irq, 0, KBUILD_MODNAME, skel); + if (ret) { + dev_err(&pdev->dev, "request_irq failed\n"); + goto disable_pci; + } + skel->pdev = pdev; + + /* Fill in the initial format-related settings */ + skel->timings = timings_def; + skel->std = V4L2_STD_625_50; + skeleton_fill_pix_format(skel, &skel->format); + + /* Initialize the top-level structure */ + ret = v4l2_device_register(&pdev->dev, &skel->v4l2_dev); + if (ret) + goto disable_pci; + + mutex_init(&skel->lock); + + /* Add the controls */ + hdl = &skel->ctrl_handler; + v4l2_ctrl_handler_init(hdl, 4); + v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); + v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 16); + v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 127); + v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, + V4L2_CID_HUE, -128, 127, 1, 0); + if (hdl->error) { + ret = hdl->error; + goto free_hdl; + } + skel->v4l2_dev.ctrl_handler = hdl; + + /* Initialize the vb2 queue */ + q = &skel->queue; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; + q->drv_priv = skel; + q->buf_struct_size = sizeof(struct skel_buffer); + q->ops = &skel_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + /* + * Assume that this DMA engine needs to have at least two buffers + * available before it can be started. The start_streaming() op + * won't be called until at least this many buffers are queued up. + */ + q->min_buffers_needed = 2; + /* + * The serialization lock for the streaming ioctls. This is the same + * as the main serialization lock, but if some of the non-streaming + * ioctls could take a long time to execute, then you might want to + * have a different lock here to prevent VIDIOC_DQBUF from being + * blocked while waiting for another action to finish. This is + * generally not needed for PCI devices, but USB devices usually do + * want a separate lock here. + */ + q->lock = &skel->lock; + /* + * Since this driver can only do 32-bit DMA we must make sure that + * the vb2 core will allocate the buffers in 32-bit DMA memory. + */ + q->gfp_flags = GFP_DMA32; + ret = vb2_queue_init(q); + if (ret) + goto free_hdl; + + skel->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(skel->alloc_ctx)) { + dev_err(&pdev->dev, "Can't allocate buffer context"); + ret = PTR_ERR(skel->alloc_ctx); + goto free_hdl; + } + INIT_LIST_HEAD(&skel->buf_list); + spin_lock_init(&skel->qlock); + + /* Initialize the video_device structure */ + vdev = &skel->vdev; + strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); + /* + * There is nothing to clean up, so release is set to an empty release + * function. The release callback must be non-NULL. + */ + vdev->release = video_device_release_empty; + vdev->fops = &skel_fops, + vdev->ioctl_ops = &skel_ioctl_ops, + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + /* + * The main serialization lock. All ioctls are serialized by this + * lock. Exception: if q->lock is set, then the streaming ioctls + * are serialized by that separate lock. + */ + vdev->lock = &skel->lock; + vdev->queue = q; + vdev->v4l2_dev = &skel->v4l2_dev; + /* Supported SDTV standards, if any */ + vdev->tvnorms = SKEL_TVNORMS; + video_set_drvdata(vdev, skel); + + ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (ret) + goto free_ctx; + + dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n"); + return 0; + +free_ctx: + vb2_dma_contig_cleanup_ctx(skel->alloc_ctx); +free_hdl: + v4l2_ctrl_handler_free(&skel->ctrl_handler); + v4l2_device_unregister(&skel->v4l2_dev); +disable_pci: + pci_disable_device(pdev); + return ret; +} + +static void skeleton_remove(struct pci_dev *pdev) +{ + struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); + struct skeleton *skel = container_of(v4l2_dev, struct skeleton, v4l2_dev); + + video_unregister_device(&skel->vdev); + v4l2_ctrl_handler_free(&skel->ctrl_handler); + vb2_dma_contig_cleanup_ctx(skel->alloc_ctx); + v4l2_device_unregister(&skel->v4l2_dev); + pci_disable_device(skel->pdev); +} + +static struct pci_driver skeleton_driver = { + .name = KBUILD_MODNAME, + .probe = skeleton_probe, + .remove = skeleton_remove, + .id_table = skeleton_pci_tbl, +}; + +module_pci_driver(skeleton_driver); -- cgit v1.2.3