Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1582252 > unrolled thread
| Started by | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| First post | 2017-02-16 03:30 +0100 |
| Last post | 2017-03-01 01:50 +0100 |
| Articles | 20 on this page of 98 — 8 participants |
Back to article view | Back to linux.kernel
[PATCH v4 00/36] i.MX Media Driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 05/36] ARM: dts: imx6qdl-sabrelite: remove erratum ERR006687 workaround Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 17/36] media: Add userspace header file for i.MX Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 17/36] media: Add userspace header file for i.MX Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-16 12:40 +0100
Re: [PATCH v4 17/36] media: Add userspace header file for i.MX Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-23 01:00 +0100
[PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-16 11:30 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 19:10 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-17 12:00 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-17 12:20 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-17 12:40 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-23 00:50 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-23 00:50 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-23 01:10 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-23 01:20 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-17 15:20 +0100
Re: [PATCH v4 23/36] media: imx: Add MIPI CSI-2 Receiver subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-17 19:30 +0100
[PATCH v4 28/36] media: imx: csi: fix crop rectangle changes in set_fmt Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 28/36] media: imx: csi: fix crop rectangle changes in set_fmt Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-16 12:10 +0100
Re: [PATCH v4 28/36] media: imx: csi: fix crop rectangle changes in set_fmt Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 19:20 +0100
[PATCH v4 35/36] media: imx: csi: fix crop rectangle reset in sink set_fmt Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 27/36] media: imx: csi: add support for bayer formats Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 33/36] media: imx: redo pixel format enumeration and negotiation Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 33/36] media: imx: redo pixel format enumeration and negotiation Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-16 12:40 +0100
Re: [PATCH v4 33/36] media: imx: redo pixel format enumeration and negotiation Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-23 01:00 +0100
Re: [PATCH v4 33/36] media: imx: redo pixel format enumeration and negotiation Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-23 10:20 +0100
Re: [PATCH v4 33/36] media: imx: redo pixel format enumeration and negotiation Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-24 02:50 +0100
[PATCH v4 26/36] media: imx: add support for bayer formats Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 07/36] ARM: dts: imx6-sabresd: add OV5642 and OV5640 camera sensors Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 07/36] ARM: dts: imx6-sabresd: add OV5642 and OV5640 camera sensors Fabio Estevam <festevam@gmail.com> - 2017-02-17 02:00 +0100
Re: [PATCH v4 07/36] ARM: dts: imx6-sabresd: add OV5642 and OV5640 camera sensors Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-17 02:00 +0100
[PATCH v4 10/36] ARM: dts: imx6-sabreauto: add pinctrl for gpt input capture Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 06/36] ARM: dts: imx6-sabrelite: add OV5642 and OV5640 camera sensors Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-18 02:20 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-18 10:30 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-18 18:30 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-18 19:20 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <steve_longerbeam@mentor.com> - 2017-02-18 02:20 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Sakari Ailus <sakari.ailus@iki.fi> - 2017-02-20 23:10 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-21 00:00 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-21 00:50 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Sakari Ailus <sakari.ailus@iki.fi> - 2017-02-21 13:20 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-21 23:30 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-22 00:40 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-21 01:20 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-21 10:00 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-21 01:20 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Sakari Ailus <sakari.ailus@iki.fi> - 2017-02-21 13:40 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-21 14:30 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Sakari Ailus <sakari.ailus@iki.fi> - 2017-02-21 16:40 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-21 17:10 +0100
Re: [PATCH v4 29/36] media: imx: mipi-csi2: enable setting and getting of frame rates Sakari Ailus <sakari.ailus@iki.fi> - 2017-02-21 17:20 +0100
[PATCH v4 13/36] [media] v4l2: add a frame timeout event Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 31/36] media: imx: csi: add __csi_get_fmt Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 12/36] add mux and video interface bridge entity functions Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 12/36] add mux and video interface bridge entity functions Pavel Machek <pavel@ucw.cz> - 2017-02-19 22:40 +0100
Re: [PATCH v4 12/36] add mux and video interface bridge entity functions Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-22 18:30 +0100
[PATCH v4 14/36] [media] v4l2-mc: add a function to inherit controls from a pipeline Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 14/36] [media] v4l2-mc: add a function to inherit controls from a pipeline Pavel Machek <pavel@ucw.cz> - 2017-02-19 23:00 +0100
[PATCH v4 15/36] platform: add video-multiplexer subdevice driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver Pavel Machek <pavel@ucw.cz> - 2017-02-19 23:20 +0100
Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-21 10:20 +0100
Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver Pavel Machek <pavel@ucw.cz> - 2017-02-24 21:10 +0100
Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver Rob Herring <robh@kernel.org> - 2017-02-27 15:50 +0100
Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-03-01 01:30 +0100
[PATCH v4 21/36] media: imx: Add VDIC subdev driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 32/36] media: imx: csi/fim: add support for frame intervals Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
Re: [PATCH v4 32/36] media: imx: csi/fim: add support for frame intervals Steve Longerbeam <steve_longerbeam@mentor.com> - 2017-02-16 03:40 +0100
[PATCH v4 09/36] ARM: dts: imx6-sabreauto: add reset-gpios property for max7310_b Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:30 +0100
[PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:40 +0100
Re: [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-16 13:00 +0100
Re: [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 20:30 +0100
Re: [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver Rob Herring <robh@kernel.org> - 2017-02-27 15:50 +0100
Re: [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-03-01 01:40 +0100
[PATCH v4 04/36] ARM: dts: imx6qdl: add capture-subsystem device Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 03:40 +0100
Re: [PATCH v4 18/36] media: Add i.MX media core driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-16 11:30 +0100
Re: [PATCH v4 18/36] media: Add i.MX media core driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 19:00 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-16 12:40 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 19:40 +0100
Re: [PATCH v4 18/36] media: Add i.MX media core driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-16 14:10 +0100
Re: [PATCH v4 18/36] media: Add i.MX media core driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-16 14:50 +0100
Re: [PATCH v4 18/36] media: Add i.MX media core driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-17 02:40 +0100
Re: [PATCH v4 18/36] media: Add i.MX media core driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-17 09:40 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-16 23:30 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-17 00:10 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-17 11:50 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-17 12:00 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-17 12:30 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-02-18 18:40 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-17 12:50 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Sakari Ailus <sakari.ailus@iki.fi> - 2017-02-17 13:30 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-17 13:40 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Philipp Zabel <p.zabel@pengutronix.de> - 2017-02-17 16:10 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Sakari Ailus <sakari.ailus@iki.fi> - 2017-02-18 13:10 +0100
Re: [PATCH v4 00/36] i.MX Media Driver Russell King - ARM Linux <linux@armlinux.org.uk> - 2017-02-16 23:30 +0100
Re: [PATCH v4 24/36] [media] add Omnivision OV5640 sensor driver Rob Herring <robh@kernel.org> - 2017-02-27 15:50 +0100
Re: [PATCH v4 24/36] [media] add Omnivision OV5640 sensor driver Steve Longerbeam <slongerbeam@gmail.com> - 2017-03-01 01:50 +0100
Page 4 of 5 — ← Prev page 1 2 3 [4] 5 Next page →
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 03:30 +0100 |
| Subject | [PATCH v4 15/36] platform: add video-multiplexer subdevice driver |
| Message-ID | <tbjZx-8cO-57@gated-at.bofh.it> |
| In reply to | #1582252 |
From: Philipp Zabel <p.zabel@pengutronix.de>
This driver can handle SoC internal and external video bus multiplexers,
controlled either by register bit fields or by a GPIO. The subdevice
passes through frame interval and mbus configuration of the active input
to the output side.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
--
- fixed a cut&paste error in vidsw_remove(): v4l2_async_register_subdev()
should be unregister.
- added media_entity_cleanup() and v4l2_device_unregister_subdev()
to vidsw_remove().
- added missing MODULE_DEVICE_TABLE().
Suggested-by: Javier Martinez Canillas <javier@dowhile0.org>
- there was a line left over from a previous iteration that negated
the new way of determining the pad count just before it which
has been removed (num_pads = of_get_child_count(np)).
- Philipp Zabel has developed a set of patches that allow adding
to the subdev async notifier waiting list using a chaining method
from the async registered callbacks (v4l2_of_subdev_registered()
and the prep patches for that). For now, I've removed the use of
v4l2_of_subdev_registered() for the vidmux driver's registered
callback. This doesn't affect the functionality of this driver,
but allows for it to be merged now, before adding the chaining
support.
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
.../bindings/media/video-multiplexer.txt | 59 +++
drivers/media/platform/Kconfig | 8 +
drivers/media/platform/Makefile | 2 +
drivers/media/platform/video-multiplexer.c | 474 +++++++++++++++++++++
4 files changed, 543 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/video-multiplexer.txt
create mode 100644 drivers/media/platform/video-multiplexer.c
diff --git a/Documentation/devicetree/bindings/media/video-multiplexer.txt b/Documentation/devicetree/bindings/media/video-multiplexer.txt
new file mode 100644
index 0000000..9d133d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video-multiplexer.txt
@@ -0,0 +1,59 @@
+Video Multiplexer
+=================
+
+Video multiplexers allow to select between multiple input ports. Video received
+on the active input port is passed through to the output port. Muxes described
+by this binding may be controlled by a syscon register bitfield or by a GPIO.
+
+Required properties:
+- compatible : should be "video-multiplexer"
+- reg: should be register base of the register containing the control bitfield
+- bit-mask: bitmask of the control bitfield in the control register
+- bit-shift: bit offset of the control bitfield in the control register
+- gpios: alternatively to reg, bit-mask, and bit-shift, a single GPIO phandle
+ may be given to switch between two inputs
+- #address-cells: should be <1>
+- #size-cells: should be <0>
+- port@*: at least three port nodes containing endpoints connecting to the
+ source and sink devices according to of_graph bindings. The last port is
+ the output port, all others are inputs.
+
+Example:
+
+syscon {
+ compatible = "syscon", "simple-mfd";
+
+ mux {
+ compatible = "video-multiplexer";
+ /* Single bit (1 << 19) in syscon register 0x04: */
+ reg = <0x04>;
+ bit-mask = <1>;
+ bit-shift = <19>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ mux_in0: endpoint {
+ remote-endpoint = <&video_source0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ mux_in1: endpoint {
+ remote-endpoint = <&video_source1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ mux_out: endpoint {
+ remote-endpoint = <&capture_interface_in>;
+ };
+ };
+ };
+};
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index c9106e1..3d60d4c 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -74,6 +74,14 @@ config VIDEO_M32R_AR_M64278
To compile this driver as a module, choose M here: the
module will be called arv.
+config VIDEO_MULTIPLEXER
+ tristate "Video Multiplexer"
+ depends on VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
+ help
+ This driver provides support for SoC internal N:1 video bus
+ multiplexers controlled by register bitfields as well as external
+ 2:1 video multiplexers controlled by a single GPIO.
+
config VIDEO_OMAP3
tristate "OMAP 3 Camera support"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 349ddf6..31bfa99 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -27,6 +27,8 @@ obj-$(CONFIG_VIDEO_SH_VEU) += sh_veu.o
obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE) += m2m-deinterlace.o
+obj-$(CONFIG_VIDEO_MULTIPLEXER) += video-multiplexer.o
+
obj-$(CONFIG_VIDEO_S3C_CAMIF) += s3c-camif/
obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS) += exynos4-is/
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/
diff --git a/drivers/media/platform/video-multiplexer.c b/drivers/media/platform/video-multiplexer.c
new file mode 100644
index 0000000..6cc2821
--- /dev/null
+++ b/drivers/media/platform/video-multiplexer.c
@@ -0,0 +1,474 @@
+/*
+ * video stream multiplexer controlled via gpio or syscon
+ *
+ * Copyright (C) 2013 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2016 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-of.h>
+
+struct vidsw {
+ struct v4l2_subdev subdev;
+ unsigned int num_pads;
+ struct media_pad *pads;
+ struct v4l2_mbus_framefmt *format_mbus;
+ struct v4l2_fract timeperframe;
+ struct v4l2_of_endpoint *endpoint;
+ struct regmap_field *field;
+ struct gpio_desc *gpio;
+ int active;
+};
+
+static inline struct vidsw *v4l2_subdev_to_vidsw(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct vidsw, subdev);
+}
+
+static void vidsw_set_active(struct vidsw *vidsw, int active)
+{
+ vidsw->active = active;
+ if (active < 0)
+ return;
+
+ dev_dbg(vidsw->subdev.dev, "setting %d active\n", active);
+
+ if (vidsw->field)
+ regmap_field_write(vidsw->field, active);
+ else if (vidsw->gpio)
+ gpiod_set_value(vidsw->gpio, active);
+}
+
+static int vidsw_link_setup(struct media_entity *entity,
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
+{
+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+ struct vidsw *vidsw = v4l2_subdev_to_vidsw(sd);
+
+ /* We have no limitations on enabling or disabling our output link */
+ if (local->index == vidsw->num_pads - 1)
+ return 0;
+
+ dev_dbg(sd->dev, "link setup %s -> %s", remote->entity->name,
+ local->entity->name);
+
+ if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+ if (local->index == vidsw->active) {
+ dev_dbg(sd->dev, "going inactive\n");
+ vidsw->active = -1;
+ }
+ return 0;
+ }
+
+ if (vidsw->active >= 0) {
+ struct media_pad *pad;
+
+ if (vidsw->active == local->index)
+ return 0;
+
+ pad = media_entity_remote_pad(&vidsw->pads[vidsw->active]);
+ if (pad) {
+ struct media_link *link;
+ int ret;
+
+ link = media_entity_find_link(pad,
+ &vidsw->pads[vidsw->active]);
+ if (link) {
+ ret = __media_entity_setup_link(link, 0);
+ if (ret)
+ return ret;
+ }
+ }
+ }
+
+ vidsw_set_active(vidsw, local->index);
+
+ return 0;
+}
+
+static struct media_entity_operations vidsw_ops = {
+ .link_setup = vidsw_link_setup,
+};
+
+static bool vidsw_endpoint_disabled(struct device_node *ep)
+{
+ struct device_node *rpp;
+
+ if (!of_device_is_available(ep))
+ return true;
+
+ rpp = of_graph_get_remote_port_parent(ep);
+ if (!rpp)
+ return true;
+
+ return !of_device_is_available(rpp);
+}
+
+static int vidsw_async_init(struct vidsw *vidsw, struct device_node *node)
+{
+ struct device_node *ep;
+ u32 portno;
+ int numports;
+ int ret;
+ int i;
+ bool active_link = false;
+
+ numports = vidsw->num_pads;
+
+ for (i = 0; i < numports - 1; i++)
+ vidsw->pads[i].flags = MEDIA_PAD_FL_SINK;
+ vidsw->pads[numports - 1].flags = MEDIA_PAD_FL_SOURCE;
+
+ vidsw->subdev.entity.function = MEDIA_ENT_F_VID_MUX;
+ ret = media_entity_pads_init(&vidsw->subdev.entity, numports,
+ vidsw->pads);
+ if (ret < 0)
+ return ret;
+
+ vidsw->subdev.entity.ops = &vidsw_ops;
+
+ for_each_endpoint_of_node(node, ep) {
+ struct v4l2_of_endpoint endpoint;
+
+ v4l2_of_parse_endpoint(ep, &endpoint);
+
+ portno = endpoint.base.port;
+ if (portno >= numports - 1)
+ continue;
+
+ if (vidsw_endpoint_disabled(ep)) {
+ dev_dbg(vidsw->subdev.dev,
+ "port %d disabled\n", portno);
+ continue;
+ }
+
+ vidsw->endpoint[portno] = endpoint;
+
+ if (portno == vidsw->active)
+ active_link = true;
+ }
+
+ for (portno = 0; portno < numports - 1; portno++) {
+ if (!vidsw->endpoint[portno].base.local_node)
+ continue;
+
+ /* If the active input is not connected, use another */
+ if (!active_link) {
+ vidsw_set_active(vidsw, portno);
+ active_link = true;
+ }
+ }
+
+ return v4l2_async_register_subdev(&vidsw->subdev);
+}
+
+int vidsw_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg)
+{
+ struct vidsw *vidsw = v4l2_subdev_to_vidsw(sd);
+ struct media_pad *pad;
+ int ret;
+
+ if (vidsw->active == -1) {
+ dev_err(sd->dev, "no configuration for inactive mux\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Retrieve media bus configuration from the entity connected to the
+ * active input
+ */
+ pad = media_entity_remote_pad(&vidsw->pads[vidsw->active]);
+ if (pad) {
+ sd = media_entity_to_v4l2_subdev(pad->entity);
+ ret = v4l2_subdev_call(sd, video, g_mbus_config, cfg);
+ if (ret == -ENOIOCTLCMD)
+ pad = NULL;
+ else if (ret < 0) {
+ dev_err(sd->dev, "failed to get source configuration\n");
+ return ret;
+ }
+ }
+ if (!pad) {
+ /* Mirror the input side on the output side */
+ cfg->type = vidsw->endpoint[vidsw->active].bus_type;
+ if (cfg->type == V4L2_MBUS_PARALLEL ||
+ cfg->type == V4L2_MBUS_BT656)
+ cfg->flags = vidsw->endpoint[vidsw->active].bus.parallel.flags;
+ }
+
+ return 0;
+}
+
+static int vidsw_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct vidsw *vidsw = v4l2_subdev_to_vidsw(sd);
+ struct v4l2_subdev *upstream_sd;
+ struct media_pad *pad;
+
+ if (vidsw->active == -1) {
+ dev_err(sd->dev, "Can not start streaming on inactive mux\n");
+ return -EINVAL;
+ }
+
+ pad = media_entity_remote_pad(&sd->entity.pads[vidsw->active]);
+ if (!pad) {
+ dev_err(sd->dev, "Failed to find remote source pad\n");
+ return -ENOLINK;
+ }
+
+ if (!is_media_entity_v4l2_subdev(pad->entity)) {
+ dev_err(sd->dev, "Upstream entity is not a v4l2 subdev\n");
+ return -ENODEV;
+ }
+
+ upstream_sd = media_entity_to_v4l2_subdev(pad->entity);
+
+ return v4l2_subdev_call(upstream_sd, video, s_stream, enable);
+}
+
+static int vidsw_g_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct vidsw *vidsw = v4l2_subdev_to_vidsw(sd);
+
+ fi->interval = vidsw->timeperframe;
+
+ return 0;
+}
+
+static int vidsw_s_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct vidsw *vidsw = v4l2_subdev_to_vidsw(sd);
+
+ vidsw->timeperframe = fi->interval;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_video_ops vidsw_subdev_video_ops = {
+ .g_mbus_config = vidsw_g_mbus_config,
+ .s_stream = vidsw_s_stream,
+ .g_frame_interval = vidsw_g_frame_interval,
+ .s_frame_interval = vidsw_s_frame_interval,
+};
+
+static struct v4l2_mbus_framefmt *
+__vidsw_get_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ unsigned int pad, u32 which)
+{
+ struct vidsw *vidsw = v4l2_subdev_to_vidsw(sd);
+
+ switch (which) {
+ case V4L2_SUBDEV_FORMAT_TRY:
+ return v4l2_subdev_get_try_format(sd, cfg, pad);
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
+ return &vidsw->format_mbus[pad];
+ default:
+ return NULL;
+ }
+}
+
+static int vidsw_get_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *sdformat)
+{
+ sdformat->format = *__vidsw_get_pad_format(sd, cfg, sdformat->pad,
+ sdformat->which);
+ return 0;
+}
+
+static int vidsw_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *sdformat)
+{
+ struct vidsw *vidsw = v4l2_subdev_to_vidsw(sd);
+ struct v4l2_mbus_framefmt *mbusformat;
+
+ if (sdformat->pad >= vidsw->num_pads)
+ return -EINVAL;
+
+ mbusformat = __vidsw_get_pad_format(sd, cfg, sdformat->pad,
+ sdformat->which);
+ if (!mbusformat)
+ return -EINVAL;
+
+ /* Output pad mirrors active input pad, no limitations on input pads */
+ if (sdformat->pad == (vidsw->num_pads - 1) && vidsw->active >= 0)
+ sdformat->format = vidsw->format_mbus[vidsw->active];
+
+ *mbusformat = sdformat->format;
+
+ return 0;
+}
+
+static struct v4l2_subdev_pad_ops vidsw_pad_ops = {
+ .get_fmt = vidsw_get_format,
+ .set_fmt = vidsw_set_format,
+};
+
+static struct v4l2_subdev_ops vidsw_subdev_ops = {
+ .pad = &vidsw_pad_ops,
+ .video = &vidsw_subdev_video_ops,
+};
+
+static int of_get_reg_field(struct device_node *node, struct reg_field *field)
+{
+ u32 bit_mask;
+ int ret;
+
+ ret = of_property_read_u32(node, "reg", &field->reg);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u32(node, "bit-mask", &bit_mask);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u32(node, "bit-shift", &field->lsb);
+ if (ret < 0)
+ return ret;
+
+ field->msb = field->lsb + fls(bit_mask) - 1;
+
+ return 0;
+}
+
+static int vidsw_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct of_endpoint endpoint;
+ struct device_node *ep;
+ struct reg_field field;
+ struct vidsw *vidsw;
+ struct regmap *map;
+ unsigned int num_pads;
+ int ret;
+
+ vidsw = devm_kzalloc(&pdev->dev, sizeof(*vidsw), GFP_KERNEL);
+ if (!vidsw)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, vidsw);
+
+ v4l2_subdev_init(&vidsw->subdev, &vidsw_subdev_ops);
+ snprintf(vidsw->subdev.name, sizeof(vidsw->subdev.name), "%s",
+ np->name);
+ vidsw->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ vidsw->subdev.dev = &pdev->dev;
+
+ /*
+ * The largest numbered port is the output port. It determines
+ * total number of pads
+ */
+ num_pads = 0;
+ for_each_endpoint_of_node(np, ep) {
+ of_graph_parse_endpoint(ep, &endpoint);
+ num_pads = max(num_pads, endpoint.port + 1);
+ }
+
+ if (num_pads < 2) {
+ dev_err(&pdev->dev, "Not enough ports %d\n", num_pads);
+ return -EINVAL;
+ }
+
+ ret = of_get_reg_field(np, &field);
+ if (ret == 0) {
+ map = syscon_node_to_regmap(np->parent);
+ if (!map) {
+ dev_err(&pdev->dev, "Failed to get syscon register map\n");
+ return PTR_ERR(map);
+ }
+
+ vidsw->field = devm_regmap_field_alloc(&pdev->dev, map, field);
+ if (IS_ERR(vidsw->field)) {
+ dev_err(&pdev->dev, "Failed to allocate regmap field\n");
+ return PTR_ERR(vidsw->field);
+ }
+
+ regmap_field_read(vidsw->field, &vidsw->active);
+ } else {
+ if (num_pads > 3) {
+ dev_err(&pdev->dev, "Too many ports %d\n", num_pads);
+ return -EINVAL;
+ }
+
+ vidsw->gpio = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW);
+ if (IS_ERR(vidsw->gpio)) {
+ dev_warn(&pdev->dev,
+ "could not request control gpio: %d\n", ret);
+ vidsw->gpio = NULL;
+ }
+
+ vidsw->active = gpiod_get_value(vidsw->gpio) ? 1 : 0;
+ }
+
+ vidsw->num_pads = num_pads;
+ vidsw->pads = devm_kzalloc(&pdev->dev, sizeof(*vidsw->pads) * num_pads,
+ GFP_KERNEL);
+ vidsw->format_mbus = devm_kzalloc(&pdev->dev,
+ sizeof(*vidsw->format_mbus) * num_pads, GFP_KERNEL);
+ vidsw->endpoint = devm_kzalloc(&pdev->dev,
+ sizeof(*vidsw->endpoint) * (num_pads - 1), GFP_KERNEL);
+
+ ret = vidsw_async_init(vidsw, np);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int vidsw_remove(struct platform_device *pdev)
+{
+ struct vidsw *vidsw = platform_get_drvdata(pdev);
+ struct v4l2_subdev *sd = &vidsw->subdev;
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_device_unregister_subdev(sd);
+
+ return 0;
+}
+
+static const struct of_device_id vidsw_dt_ids[] = {
+ { .compatible = "video-multiplexer", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vidsw_dt_ids);
+
+static struct platform_driver vidsw_driver = {
+ .probe = vidsw_probe,
+ .remove = vidsw_remove,
+ .driver = {
+ .of_match_table = vidsw_dt_ids,
+ .name = "video-multiplexer",
+ },
+};
+
+module_platform_driver(vidsw_driver);
+
+MODULE_DESCRIPTION("video stream multiplexer");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_AUTHOR("Philipp Zabel, Pengutronix");
+MODULE_LICENSE("GPL");
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Pavel Machek <pavel@ucw.cz> |
|---|---|
| Date | 2017-02-19 23:20 +0100 |
| Subject | Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver |
| Message-ID | <tcHZM-4Av-15@gated-at.bofh.it> |
| In reply to | #1582269 |
[Multipart message — attachments visible in raw view] — view raw
Hi!
> From: Philipp Zabel <p.zabel@pengutronix.de>
>
> This driver can handle SoC internal and external video bus multiplexers,
> controlled either by register bit fields or by a GPIO. The subdevice
> passes through frame interval and mbus configuration of the active input
> to the output side.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> --
>
Again, this is slightly non-standard format. Normally changes from v1
go below ---, but in your case it would cut off the signoff...
> diff --git a/Documentation/devicetree/bindings/media/video-multiplexer.txt b/Documentation/devicetree/bindings/media/video-multiplexer.txt
> new file mode 100644
> index 0000000..9d133d9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/video-multiplexer.txt
> @@ -0,0 +1,59 @@
> +Video Multiplexer
> +=================
> +
> +Video multiplexers allow to select between multiple input ports. Video received
> +on the active input port is passed through to the output port. Muxes described
> +by this binding may be controlled by a syscon register bitfield or by a GPIO.
> +
> +Required properties:
> +- compatible : should be "video-multiplexer"
> +- reg: should be register base of the register containing the control bitfield
> +- bit-mask: bitmask of the control bitfield in the control register
> +- bit-shift: bit offset of the control bitfield in the control register
> +- gpios: alternatively to reg, bit-mask, and bit-shift, a single GPIO phandle
> + may be given to switch between two inputs
> +- #address-cells: should be <1>
> +- #size-cells: should be <0>
> +- port@*: at least three port nodes containing endpoints connecting to the
> + source and sink devices according to of_graph bindings. The last port is
> + the output port, all others are inputs.
At least three? I guess it is exactly three with the gpio?
Plus you might want to describe which port correspond to which gpio
state/bitfield values...
> +struct vidsw {
I knew it: it is secretely a switch! :-).
> +static void vidsw_set_active(struct vidsw *vidsw, int active)
> +{
> + vidsw->active = active;
> + if (active < 0)
> + return;
> +
> + dev_dbg(vidsw->subdev.dev, "setting %d active\n", active);
> +
> + if (vidsw->field)
> + regmap_field_write(vidsw->field, active);
> + else if (vidsw->gpio)
> + gpiod_set_value(vidsw->gpio, active);
else dev_err()...?
> +static int vidsw_async_init(struct vidsw *vidsw, struct device_node *node)
> +{
> + struct device_node *ep;
> + u32 portno;
> + int numports;
numbports is int, so I guess portno should be, too?
> + portno = endpoint.base.port;
> + if (portno >= numports - 1)
> + continue;
> + if (!pad) {
> + /* Mirror the input side on the output side */
> + cfg->type = vidsw->endpoint[vidsw->active].bus_type;
> + if (cfg->type == V4L2_MBUS_PARALLEL ||
> + cfg->type == V4L2_MBUS_BT656)
> + cfg->flags = vidsw->endpoint[vidsw->active].bus.parallel.flags;
> + }
Will this need support for other V4L2_MBUS_ values?
> +MODULE_AUTHOR("Sascha Hauer, Pengutronix");
> +MODULE_AUTHOR("Philipp Zabel, Pengutronix");
Normally, MODULE_AUTHOR contains comma separated names of authors,
perhaps with <email@addresses>. Not sure two MODULE_AUTHORs per file
will work.
Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[toc] | [prev] | [next] | [standalone]
| From | Philipp Zabel <p.zabel@pengutronix.de> |
|---|---|
| Date | 2017-02-21 10:20 +0100 |
| Subject | Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver |
| Message-ID | <tdeM1-wC-7@gated-at.bofh.it> |
| In reply to | #1584266 |
On Sun, 2017-02-19 at 23:02 +0100, Pavel Machek wrote:
> Hi!
>
> > From: Philipp Zabel <p.zabel@pengutronix.de>
> >
> > This driver can handle SoC internal and external video bus multiplexers,
> > controlled either by register bit fields or by a GPIO. The subdevice
> > passes through frame interval and mbus configuration of the active input
> > to the output side.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > --
> >
>
> Again, this is slightly non-standard format. Normally changes from v1
> go below ---, but in your case it would cut off the signoff...
>
> > diff --git a/Documentation/devicetree/bindings/media/video-multiplexer.txt b/Documentation/devicetree/bindings/media/video-multiplexer.txt
> > new file mode 100644
> > index 0000000..9d133d9
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/media/video-multiplexer.txt
> > @@ -0,0 +1,59 @@
> > +Video Multiplexer
> > +=================
> > +
> > +Video multiplexers allow to select between multiple input ports. Video received
> > +on the active input port is passed through to the output port. Muxes described
> > +by this binding may be controlled by a syscon register bitfield or by a GPIO.
> > +
> > +Required properties:
> > +- compatible : should be "video-multiplexer"
> > +- reg: should be register base of the register containing the control bitfield
> > +- bit-mask: bitmask of the control bitfield in the control register
> > +- bit-shift: bit offset of the control bitfield in the control register
> > +- gpios: alternatively to reg, bit-mask, and bit-shift, a single GPIO phandle
> > + may be given to switch between two inputs
> > +- #address-cells: should be <1>
> > +- #size-cells: should be <0>
> > +- port@*: at least three port nodes containing endpoints connecting to the
> > + source and sink devices according to of_graph bindings. The last port is
> > + the output port, all others are inputs.
>
> At least three? I guess it is exactly three with the gpio?
Yes. With the mmio bitfield muxes there can be more.
> Plus you might want to describe which port correspond to which gpio
> state/bitfield values...
>
> > +struct vidsw {
>
> I knew it: it is secretely a switch! :-).
This driver started as a two-input gpio controlled bus switch.
I changed the name when adding support for bitfield controlled
multiplexers with more than two inputs.
> > +static void vidsw_set_active(struct vidsw *vidsw, int active)
> > +{
> > + vidsw->active = active;
> > + if (active < 0)
> > + return;
> > +
> > + dev_dbg(vidsw->subdev.dev, "setting %d active\n", active);
> > +
> > + if (vidsw->field)
> > + regmap_field_write(vidsw->field, active);
> > + else if (vidsw->gpio)
> > + gpiod_set_value(vidsw->gpio, active);
>
> else dev_err()...?
If neither field nor gpio are set, probe will have failed and this will
never be called.
> > +static int vidsw_async_init(struct vidsw *vidsw, struct device_node *node)
> > +{
> > + struct device_node *ep;
> > + u32 portno;
> > + int numports;
>
> numbports is int, so I guess portno should be, too?
We could change both to unsigned int, as both vidsw->num_pads and
endpoint.base.port are unsigned int, and they are only compared/assigned
to those and each other.
> > + portno = endpoint.base.port;
> > + if (portno >= numports - 1)
> > + continue;
>
I.
> > + if (!pad) {
> > + /* Mirror the input side on the output side */
> > + cfg->type = vidsw->endpoint[vidsw->active].bus_type;
> > + if (cfg->type == V4L2_MBUS_PARALLEL ||
> > + cfg->type == V4L2_MBUS_BT656)
> > + cfg->flags = vidsw->endpoint[vidsw->active].bus.parallel.flags;
> > + }
>
> Will this need support for other V4L2_MBUS_ values?
To support CSI-2 multiplexers, yes.
> > +MODULE_AUTHOR("Sascha Hauer, Pengutronix");
> > +MODULE_AUTHOR("Philipp Zabel, Pengutronix");
>
> Normally, MODULE_AUTHOR contains comma separated names of authors,
> perhaps with <email@addresses>. Not sure two MODULE_AUTHORs per file
> will work.
>
> Thanks,
> Pavel
regards
Philipp
[toc] | [prev] | [next] | [standalone]
| From | Pavel Machek <pavel@ucw.cz> |
|---|---|
| Date | 2017-02-24 21:10 +0100 |
| Subject | Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver |
| Message-ID | <teulH-5iW-19@gated-at.bofh.it> |
| In reply to | #1585155 |
[Multipart message — attachments visible in raw view] — view raw
Hi!
> > Plus you might want to describe which port correspond to which gpio
> > state/bitfield values...
> >
> > > +struct vidsw {
> >
> > I knew it: it is secretely a switch! :-).
>
> This driver started as a two-input gpio controlled bus switch.
> I changed the name when adding support for bitfield controlled
> multiplexers with more than two inputs.
We had discussion with Sakari / Rob whether gpio controlled thing is a
switch or a multiplexer :-).
> > > + if (!pad) {
> > > + /* Mirror the input side on the output side */
> > > + cfg->type = vidsw->endpoint[vidsw->active].bus_type;
> > > + if (cfg->type == V4L2_MBUS_PARALLEL ||
> > > + cfg->type == V4L2_MBUS_BT656)
> > > + cfg->flags = vidsw->endpoint[vidsw->active].bus.parallel.flags;
> > > + }
> >
> > Will this need support for other V4L2_MBUS_ values?
>
> To support CSI-2 multiplexers, yes.
Can you stick switch () { .... default: dev_err() } there, to help
future hackers?
Thank,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[toc] | [prev] | [next] | [standalone]
| From | Rob Herring <robh@kernel.org> |
|---|---|
| Date | 2017-02-27 15:50 +0100 |
| Subject | Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver |
| Message-ID | <tfuMG-6Wf-5@gated-at.bofh.it> |
| In reply to | #1582269 |
On Wed, Feb 15, 2017 at 06:19:17PM -0800, Steve Longerbeam wrote:
> From: Philipp Zabel <p.zabel@pengutronix.de>
>
> This driver can handle SoC internal and external video bus multiplexers,
> controlled either by register bit fields or by a GPIO. The subdevice
> passes through frame interval and mbus configuration of the active input
> to the output side.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
>
> --
>
> - fixed a cut&paste error in vidsw_remove(): v4l2_async_register_subdev()
> should be unregister.
>
> - added media_entity_cleanup() and v4l2_device_unregister_subdev()
> to vidsw_remove().
>
> - added missing MODULE_DEVICE_TABLE().
> Suggested-by: Javier Martinez Canillas <javier@dowhile0.org>
>
> - there was a line left over from a previous iteration that negated
> the new way of determining the pad count just before it which
> has been removed (num_pads = of_get_child_count(np)).
>
> - Philipp Zabel has developed a set of patches that allow adding
> to the subdev async notifier waiting list using a chaining method
> from the async registered callbacks (v4l2_of_subdev_registered()
> and the prep patches for that). For now, I've removed the use of
> v4l2_of_subdev_registered() for the vidmux driver's registered
> callback. This doesn't affect the functionality of this driver,
> but allows for it to be merged now, before adding the chaining
> support.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> .../bindings/media/video-multiplexer.txt | 59 +++
Please make this a separate commit.
> drivers/media/platform/Kconfig | 8 +
> drivers/media/platform/Makefile | 2 +
> drivers/media/platform/video-multiplexer.c | 474 +++++++++++++++++++++
> 4 files changed, 543 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/video-multiplexer.txt
> create mode 100644 drivers/media/platform/video-multiplexer.c
>
> diff --git a/Documentation/devicetree/bindings/media/video-multiplexer.txt b/Documentation/devicetree/bindings/media/video-multiplexer.txt
> new file mode 100644
> index 0000000..9d133d9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/video-multiplexer.txt
> @@ -0,0 +1,59 @@
> +Video Multiplexer
> +=================
> +
> +Video multiplexers allow to select between multiple input ports. Video received
> +on the active input port is passed through to the output port. Muxes described
> +by this binding may be controlled by a syscon register bitfield or by a GPIO.
> +
> +Required properties:
> +- compatible : should be "video-multiplexer"
> +- reg: should be register base of the register containing the control bitfield
> +- bit-mask: bitmask of the control bitfield in the control register
> +- bit-shift: bit offset of the control bitfield in the control register
> +- gpios: alternatively to reg, bit-mask, and bit-shift, a single GPIO phandle
> + may be given to switch between two inputs
> +- #address-cells: should be <1>
> +- #size-cells: should be <0>
> +- port@*: at least three port nodes containing endpoints connecting to the
> + source and sink devices according to of_graph bindings. The last port is
> + the output port, all others are inputs.
> +
> +Example:
> +
> +syscon {
> + compatible = "syscon", "simple-mfd";
> +
> + mux {
> + compatible = "video-multiplexer";
> + /* Single bit (1 << 19) in syscon register 0x04: */
> + reg = <0x04>;
> + bit-mask = <1>;
> + bit-shift = <19>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + mux_in0: endpoint {
> + remote-endpoint = <&video_source0_out>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + mux_in1: endpoint {
> + remote-endpoint = <&video_source1_out>;
> + };
> + };
> +
> + port@2 {
> + reg = <2>;
> +
> + mux_out: endpoint {
> + remote-endpoint = <&capture_interface_in>;
> + };
> + };
> + };
> +};
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-03-01 01:30 +0100 |
| Subject | Re: [PATCH v4 15/36] platform: add video-multiplexer subdevice driver |
| Message-ID | <tg0jw-3kp-7@gated-at.bofh.it> |
| In reply to | #1588686 |
On 02/27/2017 06:41 AM, Rob Herring wrote: > On Wed, Feb 15, 2017 at 06:19:17PM -0800, Steve Longerbeam wrote: >> From: Philipp Zabel <p.zabel@pengutronix.de> >> >> This driver can handle SoC internal and external video bus multiplexers, >> controlled either by register bit fields or by a GPIO. The subdevice >> passes through frame interval and mbus configuration of the active input >> to the output side. >> >> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> >> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> >> >> -- >> >> - fixed a cut&paste error in vidsw_remove(): v4l2_async_register_subdev() >> should be unregister. >> >> - added media_entity_cleanup() and v4l2_device_unregister_subdev() >> to vidsw_remove(). >> >> - added missing MODULE_DEVICE_TABLE(). >> Suggested-by: Javier Martinez Canillas <javier@dowhile0.org> >> >> - there was a line left over from a previous iteration that negated >> the new way of determining the pad count just before it which >> has been removed (num_pads = of_get_child_count(np)). >> >> - Philipp Zabel has developed a set of patches that allow adding >> to the subdev async notifier waiting list using a chaining method >> from the async registered callbacks (v4l2_of_subdev_registered() >> and the prep patches for that). For now, I've removed the use of >> v4l2_of_subdev_registered() for the vidmux driver's registered >> callback. This doesn't affect the functionality of this driver, >> but allows for it to be merged now, before adding the chaining >> support. >> >> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> >> --- >> .../bindings/media/video-multiplexer.txt | 59 +++ > Please make this a separate commit. Done. Steve
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 03:30 +0100 |
| Subject | [PATCH v4 21/36] media: imx: Add VDIC subdev driver |
| Message-ID | <tbjZx-8cO-65@gated-at.bofh.it> |
| In reply to | #1582252 |
This is a media entity subdevice driver for the i.MX Video De-Interlacing
or Combining Block. So far this entity does not implement the Combining
function but only motion compensated deinterlacing. Video frames are
received from the CSI and are routed to the IC PRPVF entity.
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
drivers/staging/media/imx/Makefile | 1 +
drivers/staging/media/imx/imx-media-vdic.c | 886 +++++++++++++++++++++++++++++
2 files changed, 887 insertions(+)
create mode 100644 drivers/staging/media/imx/imx-media-vdic.c
diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile
index c054490..1f01520 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -4,5 +4,6 @@ imx-media-common-objs := imx-media-utils.o imx-media-fim.o
obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
+obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-vdic.o
obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c
new file mode 100644
index 0000000..5bb21e9
--- /dev/null
+++ b/drivers/staging/media/imx/imx-media-vdic.c
@@ -0,0 +1,886 @@
+/*
+ * V4L2 Deinterlacer Subdev for Freescale i.MX5/6 SOC
+ *
+ * Copyright (c) 2017 Mentor Graphics Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+#include <media/imx.h>
+#include "imx-media.h"
+
+/*
+ * This subdev implements two different video pipelines:
+ *
+ * CSI -> VDIC
+ *
+ * In this pipeline, the CSI sends a single interlaced field F(n-1)
+ * directly to the VDIC (and optionally the following field F(n)
+ * can be sent to memory via IDMAC channel 13). This pipeline only works
+ * in VDIC's high motion mode, which only requires a single field for
+ * processing. The other motion modes (low and medium) require three
+ * fields, so this pipeline does not work in those modes. Also, it is
+ * not clear how this pipeline can deal with the various field orders
+ * (sequential BT/TB, interlaced BT/TB).
+ *
+ * MEM -> CH8,9,10 -> VDIC
+ *
+ * In this pipeline, previous field F(n-1), current field F(n), and next
+ * field F(n+1) are transferred to the VDIC via IDMAC channels 8,9,10.
+ * These memory buffers can come from a video output or mem2mem device.
+ * All motion modes are supported by this pipeline.
+ *
+ * The "direct" CSI->VDIC pipeline requires no DMA, but it can only be
+ * used in high motion mode.
+ */
+
+struct vdic_priv;
+
+struct vdic_pipeline_ops {
+ int (*setup)(struct vdic_priv *priv);
+ void (*start)(struct vdic_priv *priv);
+ void (*stop)(struct vdic_priv *priv);
+ void (*disable)(struct vdic_priv *priv);
+};
+
+/*
+ * Min/Max supported width and heights.
+ */
+#define MIN_W 176
+#define MIN_H 144
+#define MAX_W_VDIC 968
+#define MAX_H_VDIC 2048
+#define W_ALIGN 4 /* multiple of 16 pixels */
+#define H_ALIGN 1 /* multiple of 2 lines */
+#define S_ALIGN 1 /* multiple of 2 */
+
+struct vdic_priv {
+ struct device *dev;
+ struct ipu_soc *ipu;
+ struct imx_media_dev *md;
+ struct v4l2_subdev sd;
+ int ipu_id;
+
+ /* IPU units we require */
+ struct ipu_vdi *vdi;
+
+ struct media_pad pad[VDIC_NUM_PADS];
+ int active_input_pad;
+
+ struct ipuv3_channel *vdi_in_ch_p; /* F(n-1) transfer channel */
+ struct ipuv3_channel *vdi_in_ch; /* F(n) transfer channel */
+ struct ipuv3_channel *vdi_in_ch_n; /* F(n+1) transfer channel */
+
+ /* pipeline operations */
+ struct vdic_pipeline_ops *ops;
+
+ /* current and previous input buffers indirect path */
+ struct imx_media_buffer *curr_in_buf;
+ struct imx_media_buffer *prev_in_buf;
+
+ /*
+ * translated field type, input line stride, and field size
+ * for indirect path
+ */
+ u32 fieldtype;
+ u32 in_stride;
+ u32 field_size;
+
+ /* the source (a video device or subdev) */
+ struct media_entity *src;
+ /* the sink that will receive the progressive out buffers */
+ struct v4l2_subdev *sink_sd;
+
+ /* the attached sensor at stream on */
+ struct imx_media_subdev *sensor;
+
+ /* the video standard from sensor at time of streamon */
+ v4l2_std_id std;
+
+ struct v4l2_mbus_framefmt format_mbus[VDIC_NUM_PADS];
+ const struct imx_media_pixfmt *cc[VDIC_NUM_PADS];
+
+ /* the video device at IDMAC input pad */
+ struct imx_media_video_dev *vdev;
+
+ bool csi_direct; /* using direct CSI->VDIC->IC pipeline */
+
+ /* motion select control */
+ struct v4l2_ctrl_handler ctrl_hdlr;
+ enum ipu_motion_sel motion;
+
+ bool stream_on; /* streaming is on */
+};
+
+static void vdic_put_ipu_resources(struct vdic_priv *priv)
+{
+ if (!IS_ERR_OR_NULL(priv->vdi_in_ch_p))
+ ipu_idmac_put(priv->vdi_in_ch_p);
+ priv->vdi_in_ch_p = NULL;
+
+ if (!IS_ERR_OR_NULL(priv->vdi_in_ch))
+ ipu_idmac_put(priv->vdi_in_ch);
+ priv->vdi_in_ch = NULL;
+
+ if (!IS_ERR_OR_NULL(priv->vdi_in_ch_n))
+ ipu_idmac_put(priv->vdi_in_ch_n);
+ priv->vdi_in_ch_n = NULL;
+
+ if (!IS_ERR_OR_NULL(priv->vdi))
+ ipu_vdi_put(priv->vdi);
+ priv->vdi = NULL;
+}
+
+static int vdic_get_ipu_resources(struct vdic_priv *priv)
+{
+ int ret, err_chan;
+
+ priv->ipu = priv->md->ipu[priv->ipu_id];
+
+ priv->vdi = ipu_vdi_get(priv->ipu);
+ if (IS_ERR(priv->vdi)) {
+ v4l2_err(&priv->sd, "failed to get VDIC\n");
+ ret = PTR_ERR(priv->vdi);
+ goto out;
+ }
+
+ if (!priv->csi_direct) {
+ priv->vdi_in_ch_p = ipu_idmac_get(priv->ipu,
+ IPUV3_CHANNEL_MEM_VDI_PREV);
+ if (IS_ERR(priv->vdi_in_ch_p)) {
+ err_chan = IPUV3_CHANNEL_MEM_VDI_PREV;
+ ret = PTR_ERR(priv->vdi_in_ch_p);
+ goto out_err_chan;
+ }
+
+ priv->vdi_in_ch = ipu_idmac_get(priv->ipu,
+ IPUV3_CHANNEL_MEM_VDI_CUR);
+ if (IS_ERR(priv->vdi_in_ch)) {
+ err_chan = IPUV3_CHANNEL_MEM_VDI_CUR;
+ ret = PTR_ERR(priv->vdi_in_ch);
+ goto out_err_chan;
+ }
+
+ priv->vdi_in_ch_n = ipu_idmac_get(priv->ipu,
+ IPUV3_CHANNEL_MEM_VDI_NEXT);
+ if (IS_ERR(priv->vdi_in_ch_n)) {
+ err_chan = IPUV3_CHANNEL_MEM_VDI_NEXT;
+ ret = PTR_ERR(priv->vdi_in_ch_n);
+ goto out_err_chan;
+ }
+ }
+
+ return 0;
+
+out_err_chan:
+ v4l2_err(&priv->sd, "could not get IDMAC channel %u\n", err_chan);
+out:
+ vdic_put_ipu_resources(priv);
+ return ret;
+}
+
+/*
+ * This function is currently unused, but will be called when the
+ * output/mem2mem device at the IDMAC input pad sends us a new
+ * buffer. It kicks off the IDMAC read channels to bring in the
+ * buffer fields from memory and begin the conversions.
+ */
+static void __maybe_unused prepare_vdi_in_buffers(struct vdic_priv *priv,
+ struct imx_media_buffer *curr)
+{
+ dma_addr_t prev_phys, curr_phys, next_phys;
+ struct imx_media_buffer *prev;
+ struct vb2_buffer *curr_vb, *prev_vb;
+ u32 fs = priv->field_size;
+ u32 is = priv->in_stride;
+
+ /* current input buffer is now previous */
+ priv->prev_in_buf = priv->curr_in_buf;
+ priv->curr_in_buf = curr;
+ prev = priv->prev_in_buf ? priv->prev_in_buf : curr;
+
+ prev_vb = &prev->vbuf.vb2_buf;
+ curr_vb = &curr->vbuf.vb2_buf;
+
+ switch (priv->fieldtype) {
+ case V4L2_FIELD_SEQ_TB:
+ prev_phys = vb2_dma_contig_plane_dma_addr(prev_vb, 0);
+ curr_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0) + fs;
+ next_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0);
+ break;
+ case V4L2_FIELD_SEQ_BT:
+ prev_phys = vb2_dma_contig_plane_dma_addr(prev_vb, 0) + fs;
+ curr_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0);
+ next_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0) + fs;
+ break;
+ case V4L2_FIELD_INTERLACED_BT:
+ prev_phys = vb2_dma_contig_plane_dma_addr(prev_vb, 0) + is;
+ curr_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0);
+ next_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0) + is;
+ break;
+ default:
+ /* assume V4L2_FIELD_INTERLACED_TB */
+ prev_phys = vb2_dma_contig_plane_dma_addr(prev_vb, 0);
+ curr_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0) + is;
+ next_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0);
+ break;
+ }
+
+ ipu_cpmem_set_buffer(priv->vdi_in_ch_p, 0, prev_phys);
+ ipu_cpmem_set_buffer(priv->vdi_in_ch, 0, curr_phys);
+ ipu_cpmem_set_buffer(priv->vdi_in_ch_n, 0, next_phys);
+
+ ipu_idmac_select_buffer(priv->vdi_in_ch_p, 0);
+ ipu_idmac_select_buffer(priv->vdi_in_ch, 0);
+ ipu_idmac_select_buffer(priv->vdi_in_ch_n, 0);
+}
+
+static int setup_vdi_channel(struct vdic_priv *priv,
+ struct ipuv3_channel *channel,
+ dma_addr_t phys0, dma_addr_t phys1)
+{
+ struct imx_media_video_dev *vdev = priv->vdev;
+ unsigned int burst_size;
+ struct ipu_image image;
+ int ret;
+
+ ipu_cpmem_zero(channel);
+
+ memset(&image, 0, sizeof(image));
+ image.pix = vdev->fmt.fmt.pix;
+ /* one field to VDIC channels */
+ image.pix.height /= 2;
+ image.rect.width = image.pix.width;
+ image.rect.height = image.pix.height;
+ image.phys0 = phys0;
+ image.phys1 = phys1;
+
+ ret = ipu_cpmem_set_image(channel, &image);
+ if (ret)
+ return ret;
+
+ burst_size = (image.pix.width & 0xf) ? 8 : 16;
+ ipu_cpmem_set_burstsize(channel, burst_size);
+
+ ipu_cpmem_set_axi_id(channel, 1);
+
+ ipu_idmac_set_double_buffer(channel, false);
+
+ return 0;
+}
+
+static int vdic_setup_direct(struct vdic_priv *priv)
+{
+ /* set VDIC to receive from CSI for direct path */
+ ipu_fsu_link(priv->ipu, IPUV3_CHANNEL_CSI_DIRECT,
+ IPUV3_CHANNEL_CSI_VDI_PREV);
+
+ return 0;
+}
+
+static void vdic_start_direct(struct vdic_priv *priv)
+{
+}
+
+static void vdic_stop_direct(struct vdic_priv *priv)
+{
+}
+
+static void vdic_disable_direct(struct vdic_priv *priv)
+{
+ ipu_fsu_unlink(priv->ipu, IPUV3_CHANNEL_CSI_DIRECT,
+ IPUV3_CHANNEL_CSI_VDI_PREV);
+}
+
+static int vdic_setup_indirect(struct vdic_priv *priv)
+{
+ struct v4l2_mbus_framefmt *infmt;
+ const struct imx_media_pixfmt *incc;
+ int in_size, ret;
+
+ infmt = &priv->format_mbus[VDIC_SINK_PAD_IDMAC];
+ incc = priv->cc[VDIC_SINK_PAD_IDMAC];
+
+ in_size = (infmt->width * incc->bpp * infmt->height) >> 3;
+
+ /* 1/2 full image size */
+ priv->field_size = in_size / 2;
+ priv->in_stride = incc->planar ?
+ infmt->width : (infmt->width * incc->bpp) >> 3;
+
+ priv->prev_in_buf = NULL;
+ priv->curr_in_buf = NULL;
+
+ priv->fieldtype = infmt->field;
+
+ /* init the vdi-in channels */
+ ret = setup_vdi_channel(priv, priv->vdi_in_ch_p, 0, 0);
+ if (ret)
+ return ret;
+ ret = setup_vdi_channel(priv, priv->vdi_in_ch, 0, 0);
+ if (ret)
+ return ret;
+ return setup_vdi_channel(priv, priv->vdi_in_ch_n, 0, 0);
+}
+
+static void vdic_start_indirect(struct vdic_priv *priv)
+{
+ /* enable the channels */
+ ipu_idmac_enable_channel(priv->vdi_in_ch_p);
+ ipu_idmac_enable_channel(priv->vdi_in_ch);
+ ipu_idmac_enable_channel(priv->vdi_in_ch_n);
+}
+
+static void vdic_stop_indirect(struct vdic_priv *priv)
+{
+ /* disable channels */
+ ipu_idmac_disable_channel(priv->vdi_in_ch_p);
+ ipu_idmac_disable_channel(priv->vdi_in_ch);
+ ipu_idmac_disable_channel(priv->vdi_in_ch_n);
+}
+
+static void vdic_disable_indirect(struct vdic_priv *priv)
+{
+}
+
+static struct vdic_pipeline_ops direct_ops = {
+ .setup = vdic_setup_direct,
+ .start = vdic_start_direct,
+ .stop = vdic_stop_direct,
+ .disable = vdic_disable_direct,
+};
+
+static struct vdic_pipeline_ops indirect_ops = {
+ .setup = vdic_setup_indirect,
+ .start = vdic_start_indirect,
+ .stop = vdic_stop_indirect,
+ .disable = vdic_disable_indirect,
+};
+
+static int vdic_start(struct vdic_priv *priv)
+{
+ struct v4l2_mbus_framefmt *infmt;
+ int ret;
+
+ if (!priv->sensor) {
+ v4l2_err(&priv->sd, "no sensor attached\n");
+ return -EINVAL;
+ }
+
+ infmt = &priv->format_mbus[priv->active_input_pad];
+
+ priv->ops = priv->csi_direct ? &direct_ops : &indirect_ops;
+
+ ret = vdic_get_ipu_resources(priv);
+ if (ret)
+ return ret;
+
+ ret = v4l2_subdev_call(priv->sensor->sd, video, g_std, &priv->std);
+ if (ret)
+ goto out_put_ipu;
+
+ /*
+ * init the VDIC.
+ *
+ * note we don't give infmt->code to ipu_vdi_setup(). The VDIC
+ * only supports 4:2:2 or 4:2:0, and this subdev will only
+ * negotiate 4:2:2 at its sink pads.
+ */
+ ipu_vdi_setup(priv->vdi, MEDIA_BUS_FMT_UYVY8_2X8,
+ infmt->width, infmt->height);
+ ipu_vdi_set_field_order(priv->vdi, priv->std, infmt->field);
+ ipu_vdi_set_motion(priv->vdi, priv->motion);
+
+ ret = priv->ops->setup(priv);
+ if (ret)
+ goto out_put_ipu;
+
+ ipu_vdi_enable(priv->vdi);
+
+ priv->ops->start(priv);
+
+ return 0;
+
+out_put_ipu:
+ vdic_put_ipu_resources(priv);
+ return ret;
+}
+
+static void vdic_stop(struct vdic_priv *priv)
+{
+ priv->ops->stop(priv);
+ ipu_vdi_disable(priv->vdi);
+ priv->ops->disable(priv);
+
+ vdic_put_ipu_resources(priv);
+}
+
+static int vdic_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vdic_priv *priv = container_of(ctrl->handler,
+ struct vdic_priv, ctrl_hdlr);
+ enum ipu_motion_sel motion;
+
+ switch (ctrl->id) {
+ case V4L2_CID_IMX_MOTION:
+ motion = ctrl->val;
+ if (motion != priv->motion) {
+ /* can't change motion control mid-streaming */
+ if (priv->stream_on)
+ return -EBUSY;
+ priv->motion = motion;
+ }
+ break;
+ default:
+ v4l2_err(&priv->sd, "Invalid control\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops vdic_ctrl_ops = {
+ .s_ctrl = vdic_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config vdic_custom_ctrl[] = {
+ {
+ .ops = &vdic_ctrl_ops,
+ .id = V4L2_CID_IMX_MOTION,
+ .name = "Motion Compensation",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = HIGH_MOTION,
+ .min = MOTION_NONE,
+ .max = HIGH_MOTION,
+ .step = 1,
+ },
+};
+
+#define VDIC_NUM_CONTROLS ARRAY_SIZE(vdic_custom_ctrl)
+
+static int vdic_init_controls(struct vdic_priv *priv)
+{
+ struct v4l2_ctrl_handler *hdlr = &priv->ctrl_hdlr;
+ const struct v4l2_ctrl_config *c;
+ int i, ret;
+
+ v4l2_ctrl_handler_init(hdlr, VDIC_NUM_CONTROLS);
+
+ for (i = 0; i < VDIC_NUM_CONTROLS; i++) {
+ c = &vdic_custom_ctrl[i];
+ v4l2_ctrl_new_custom(hdlr, c, NULL);
+ }
+
+ priv->sd.ctrl_handler = hdlr;
+
+ if (hdlr->error) {
+ ret = hdlr->error;
+ goto out_free;
+ }
+
+ v4l2_ctrl_handler_setup(hdlr);
+ return 0;
+
+out_free:
+ v4l2_ctrl_handler_free(hdlr);
+ return ret;
+}
+
+static int vdic_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct vdic_priv *priv = v4l2_get_subdevdata(sd);
+ int ret = 0;
+
+ if (!priv->src || !priv->sink_sd)
+ return -EPIPE;
+
+ dev_dbg(priv->dev, "stream %s\n", enable ? "ON" : "OFF");
+
+ if (enable && !priv->stream_on)
+ ret = vdic_start(priv);
+ else if (!enable && priv->stream_on)
+ vdic_stop(priv);
+
+ if (!ret)
+ priv->stream_on = enable;
+ return ret;
+}
+
+static int vdic_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->pad >= VDIC_NUM_PADS)
+ return -EINVAL;
+
+ if (code->pad == VDIC_SINK_PAD_IDMAC)
+ return imx_media_enum_format(NULL, &code->code, code->index,
+ false, false);
+
+ return imx_media_enum_ipu_format(NULL, &code->code, code->index, false);
+}
+
+static struct v4l2_mbus_framefmt *
+__vdic_get_fmt(struct vdic_priv *priv, struct v4l2_subdev_pad_config *cfg,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ if (which == V4L2_SUBDEV_FORMAT_TRY)
+ return v4l2_subdev_get_try_format(&priv->sd, cfg, pad);
+ else
+ return &priv->format_mbus[pad];
+}
+
+static int vdic_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *sdformat)
+{
+ struct vdic_priv *priv = v4l2_get_subdevdata(sd);
+ struct v4l2_mbus_framefmt *fmt;
+
+ if (sdformat->pad >= VDIC_NUM_PADS)
+ return -EINVAL;
+
+ fmt = __vdic_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
+ if (!fmt)
+ return -EINVAL;
+
+ sdformat->format = *fmt;
+
+ return 0;
+}
+
+static int vdic_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *sdformat)
+{
+ struct vdic_priv *priv = v4l2_get_subdevdata(sd);
+ const struct imx_media_pixfmt *cc;
+ struct v4l2_mbus_framefmt *infmt;
+ u32 code;
+
+ if (sdformat->pad >= VDIC_NUM_PADS)
+ return -EINVAL;
+
+ if (priv->stream_on)
+ return -EBUSY;
+
+ v4l_bound_align_image(&sdformat->format.width, MIN_W, MAX_W_VDIC,
+ W_ALIGN, &sdformat->format.height,
+ MIN_H, MAX_H_VDIC, H_ALIGN, S_ALIGN);
+
+ switch (sdformat->pad) {
+ case VDIC_SRC_PAD_DIRECT:
+ infmt = __vdic_get_fmt(priv, cfg, priv->active_input_pad,
+ sdformat->which);
+
+ cc = imx_media_find_ipu_format(0, sdformat->format.code, false);
+ if (!cc) {
+ imx_media_enum_ipu_format(NULL, &code, 0, false);
+ cc = imx_media_find_ipu_format(0, code, false);
+ sdformat->format.code = cc->codes[0];
+ }
+
+ sdformat->format.width = infmt->width;
+ sdformat->format.height = infmt->height;
+ /* output is always progressive! */
+ sdformat->format.field = V4L2_FIELD_NONE;
+ break;
+ case VDIC_SINK_PAD_IDMAC:
+ case VDIC_SINK_PAD_DIRECT:
+ if (sdformat->pad == VDIC_SINK_PAD_DIRECT) {
+ cc = imx_media_find_ipu_format(0, sdformat->format.code,
+ false);
+ if (!cc) {
+ imx_media_enum_ipu_format(NULL, &code, 0,
+ false);
+ cc = imx_media_find_ipu_format(0, code, false);
+ sdformat->format.code = cc->codes[0];
+ }
+ } else {
+ cc = imx_media_find_format(0, sdformat->format.code,
+ false, false);
+ if (!cc) {
+ imx_media_enum_format(NULL, &code, 0,
+ false, false);
+ cc = imx_media_find_format(0, code,
+ false, false);
+ sdformat->format.code = cc->codes[0];
+ }
+ }
+
+ /* input must be interlaced! Choose SEQ_TB if not */
+ if (!V4L2_FIELD_HAS_BOTH(sdformat->format.field))
+ sdformat->format.field = V4L2_FIELD_SEQ_TB;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = sdformat->format;
+ } else {
+ priv->format_mbus[sdformat->pad] = sdformat->format;
+ priv->cc[sdformat->pad] = cc;
+ }
+
+ return 0;
+}
+
+static int vdic_link_setup(struct media_entity *entity,
+ const struct media_pad *local,
+ const struct media_pad *remote, u32 flags)
+{
+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+ struct vdic_priv *priv = v4l2_get_subdevdata(sd);
+ struct v4l2_subdev *remote_sd;
+ int ret;
+
+ dev_dbg(priv->dev, "link setup %s -> %s", remote->entity->name,
+ local->entity->name);
+
+ if (local->flags & MEDIA_PAD_FL_SOURCE) {
+ if (!is_media_entity_v4l2_subdev(remote->entity))
+ return -EINVAL;
+
+ remote_sd = media_entity_to_v4l2_subdev(remote->entity);
+
+ if (flags & MEDIA_LNK_FL_ENABLED) {
+ if (priv->sink_sd)
+ return -EBUSY;
+ priv->sink_sd = remote_sd;
+ } else {
+ priv->sink_sd = NULL;
+ }
+
+ return 0;
+ }
+
+ /* this is a sink pad */
+
+ if (flags & MEDIA_LNK_FL_ENABLED) {
+ if (priv->src)
+ return -EBUSY;
+ } else {
+ priv->src = NULL;
+ return 0;
+ }
+
+ if (local->index == VDIC_SINK_PAD_IDMAC) {
+ struct imx_media_video_dev *vdev = priv->vdev;
+
+ if (!is_media_entity_v4l2_video_device(remote->entity))
+ return -EINVAL;
+
+ if (!vdev)
+ return -ENOSYS;
+
+ /* reset video device controls to refresh from subdevs */
+ v4l2_ctrl_handler_free(vdev->vfd->ctrl_handler);
+ v4l2_ctrl_handler_init(vdev->vfd->ctrl_handler, 0);
+ ret = __v4l2_pipeline_inherit_controls(vdev->vfd,
+ &priv->sd.entity);
+ if (ret)
+ return ret;
+
+ priv->csi_direct = false;
+ } else {
+ if (!is_media_entity_v4l2_subdev(remote->entity))
+ return -EINVAL;
+
+ remote_sd = media_entity_to_v4l2_subdev(remote->entity);
+
+ /* direct pad must connect to a CSI */
+ if (!(remote_sd->grp_id & IMX_MEDIA_GRP_ID_CSI) ||
+ remote->index != CSI_SRC_PAD_DIRECT)
+ return -EINVAL;
+
+ priv->csi_direct = true;
+ }
+
+ priv->src = remote->entity;
+ /* record which input pad is now active */
+ priv->active_input_pad = local->index;
+
+ return 0;
+}
+
+static int vdic_link_validate(struct v4l2_subdev *sd,
+ struct media_link *link,
+ struct v4l2_subdev_format *source_fmt,
+ struct v4l2_subdev_format *sink_fmt)
+{
+ struct vdic_priv *priv = v4l2_get_subdevdata(sd);
+ int ret;
+
+ ret = v4l2_subdev_link_validate_default(sd, link,
+ source_fmt, sink_fmt);
+ if (ret)
+ return ret;
+
+ priv->sensor = __imx_media_find_sensor(priv->md, &priv->sd.entity);
+ if (IS_ERR(priv->sensor)) {
+ v4l2_err(&priv->sd, "no sensor attached\n");
+ ret = PTR_ERR(priv->sensor);
+ priv->sensor = NULL;
+ return ret;
+ }
+
+ if (priv->csi_direct && priv->motion != HIGH_MOTION) {
+ v4l2_err(&priv->sd,
+ "direct CSI pipeline requires high motion\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * retrieve our pads parsed from the OF graph by the media device
+ */
+static int vdic_registered(struct v4l2_subdev *sd)
+{
+ struct vdic_priv *priv = v4l2_get_subdevdata(sd);
+ int i, ret;
+ u32 code;
+
+ /* get media device */
+ priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
+
+ for (i = 0; i < VDIC_NUM_PADS; i++) {
+ priv->pad[i].flags = (i == VDIC_SRC_PAD_DIRECT) ?
+ MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;
+
+ code = 0;
+ if (i != VDIC_SINK_PAD_IDMAC)
+ imx_media_enum_ipu_format(NULL, &code, 0, true);
+
+ /* set a default mbus format */
+ ret = imx_media_init_mbus_fmt(&priv->format_mbus[i],
+ 640, 480, code, V4L2_FIELD_NONE,
+ &priv->cc[i]);
+ if (ret)
+ return ret;
+ }
+
+ priv->active_input_pad = VDIC_SINK_PAD_DIRECT;
+
+ ret = vdic_init_controls(priv);
+ if (ret)
+ return ret;
+
+ ret = media_entity_pads_init(&sd->entity, VDIC_NUM_PADS, priv->pad);
+ if (ret)
+ v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
+
+ return ret;
+}
+
+static void vdic_unregistered(struct v4l2_subdev *sd)
+{
+ struct vdic_priv *priv = v4l2_get_subdevdata(sd);
+
+ v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
+}
+
+static struct v4l2_subdev_pad_ops vdic_pad_ops = {
+ .enum_mbus_code = vdic_enum_mbus_code,
+ .get_fmt = vdic_get_fmt,
+ .set_fmt = vdic_set_fmt,
+ .link_validate = vdic_link_validate,
+};
+
+static struct v4l2_subdev_video_ops vdic_video_ops = {
+ .s_stream = vdic_s_stream,
+};
+
+static struct media_entity_operations vdic_entity_ops = {
+ .link_setup = vdic_link_setup,
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+static struct v4l2_subdev_ops vdic_subdev_ops = {
+ .video = &vdic_video_ops,
+ .pad = &vdic_pad_ops,
+};
+
+static struct v4l2_subdev_internal_ops vdic_internal_ops = {
+ .registered = vdic_registered,
+ .unregistered = vdic_unregistered,
+};
+
+static int imx_vdic_probe(struct platform_device *pdev)
+{
+ struct imx_media_internal_sd_platformdata *pdata;
+ struct vdic_priv *priv;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, &priv->sd);
+ priv->dev = &pdev->dev;
+
+ pdata = priv->dev->platform_data;
+ priv->ipu_id = pdata->ipu_id;
+
+ v4l2_subdev_init(&priv->sd, &vdic_subdev_ops);
+ v4l2_set_subdevdata(&priv->sd, priv);
+ priv->sd.internal_ops = &vdic_internal_ops;
+ priv->sd.entity.ops = &vdic_entity_ops;
+ priv->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
+ priv->sd.dev = &pdev->dev;
+ priv->sd.owner = THIS_MODULE;
+ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+ /* get our group id */
+ priv->sd.grp_id = pdata->grp_id;
+ strncpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name));
+
+ return v4l2_async_register_subdev(&priv->sd);
+}
+
+static int imx_vdic_remove(struct platform_device *pdev)
+{
+ struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+
+ v4l2_info(sd, "Removing\n");
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+
+ return 0;
+}
+
+static const struct platform_device_id imx_vdic_ids[] = {
+ { .name = "imx-ipuv3-vdic" },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, imx_vdic_ids);
+
+static struct platform_driver imx_vdic_driver = {
+ .probe = imx_vdic_probe,
+ .remove = imx_vdic_remove,
+ .id_table = imx_vdic_ids,
+ .driver = {
+ .name = "imx-ipuv3-vdic",
+ },
+};
+module_platform_driver(imx_vdic_driver);
+
+MODULE_DESCRIPTION("i.MX VDIC subdev driver");
+MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx-ipuv3-vdic");
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 03:30 +0100 |
| Subject | [PATCH v4 32/36] media: imx: csi/fim: add support for frame intervals |
| Message-ID | <tbjZx-8cO-71@gated-at.bofh.it> |
| In reply to | #1582252 |
Add support to CSI for negotiation of frame intervals, and use this
information to configure the frame interval monitor.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++++++++++---
drivers/staging/media/imx/imx-media-fim.c | 28 +++++++++---------------
drivers/staging/media/imx/imx-media.h | 2 +-
3 files changed, 44 insertions(+), 22 deletions(-)
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index b0aac82..040cca6 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -56,6 +56,7 @@ struct csi_priv {
struct v4l2_mbus_framefmt format_mbus[CSI_NUM_PADS];
const struct imx_media_pixfmt *cc[CSI_NUM_PADS];
+ struct v4l2_fract frame_interval;
struct v4l2_rect crop;
/* the video device at IDMAC output pad */
@@ -565,7 +566,8 @@ static int csi_start(struct csi_priv *priv)
/* start the frame interval monitor */
if (priv->fim) {
- ret = imx_media_fim_set_stream(priv->fim, priv->sensor, true);
+ ret = imx_media_fim_set_stream(priv->fim,
+ &priv->frame_interval, true);
if (ret)
goto idmac_stop;
}
@@ -580,7 +582,8 @@ static int csi_start(struct csi_priv *priv)
fim_off:
if (priv->fim)
- imx_media_fim_set_stream(priv->fim, priv->sensor, false);
+ imx_media_fim_set_stream(priv->fim,
+ &priv->frame_interval, false);
idmac_stop:
if (priv->dest == IPU_CSI_DEST_IDMAC)
csi_idmac_stop(priv);
@@ -594,11 +597,36 @@ static void csi_stop(struct csi_priv *priv)
/* stop the frame interval monitor */
if (priv->fim)
- imx_media_fim_set_stream(priv->fim, priv->sensor, false);
+ imx_media_fim_set_stream(priv->fim,
+ &priv->frame_interval, false);
ipu_csi_disable(priv->csi);
}
+static int csi_g_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct csi_priv *priv = v4l2_get_subdevdata(sd);
+
+ fi->interval = priv->frame_interval;
+
+ return 0;
+}
+
+static int csi_s_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct csi_priv *priv = v4l2_get_subdevdata(sd);
+
+ /* Output pads mirror active input pad, no limits on input pads */
+ if (fi->pad == CSI_SRC_PAD_IDMAC || fi->pad == CSI_SRC_PAD_DIRECT)
+ fi->interval = priv->frame_interval;
+
+ priv->frame_interval = fi->interval;
+
+ return 0;
+}
+
static int csi_s_stream(struct v4l2_subdev *sd, int enable)
{
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1187,6 +1215,8 @@ static struct v4l2_subdev_core_ops csi_core_ops = {
};
static struct v4l2_subdev_video_ops csi_video_ops = {
+ .g_frame_interval = csi_g_frame_interval,
+ .s_frame_interval = csi_s_frame_interval,
.s_stream = csi_s_stream,
};
diff --git a/drivers/staging/media/imx/imx-media-fim.c b/drivers/staging/media/imx/imx-media-fim.c
index acc7e39..a6ed57e 100644
--- a/drivers/staging/media/imx/imx-media-fim.c
+++ b/drivers/staging/media/imx/imx-media-fim.c
@@ -67,26 +67,18 @@ struct imx_media_fim {
};
static void update_fim_nominal(struct imx_media_fim *fim,
- struct imx_media_subdev *sensor)
+ const struct v4l2_fract *fi)
{
- struct v4l2_streamparm parm;
- struct v4l2_fract tpf;
- int ret;
-
- parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- ret = v4l2_subdev_call(sensor->sd, video, g_parm, &parm);
- tpf = parm.parm.capture.timeperframe;
-
- if (ret || tpf.denominator == 0) {
- dev_dbg(fim->sd->dev, "no tpf from sensor, FIM disabled\n");
+ if (fi->denominator == 0) {
+ dev_dbg(fim->sd->dev, "no frame interval, FIM disabled\n");
fim->enabled = false;
return;
}
- fim->nominal = DIV_ROUND_CLOSEST(1000 * 1000 * tpf.numerator,
- tpf.denominator);
+ fim->nominal = DIV_ROUND_CLOSEST_ULL(1000000ULL * (u64)fi->numerator,
+ fi->denominator);
- dev_dbg(fim->sd->dev, "sensor FI=%lu usec\n", fim->nominal);
+ dev_dbg(fim->sd->dev, "FI=%lu usec\n", fim->nominal);
}
static void reset_fim(struct imx_media_fim *fim, bool curval)
@@ -130,8 +122,8 @@ static void send_fim_event(struct imx_media_fim *fim, unsigned long error)
/*
* Monitor an averaged frame interval. If the average deviates too much
- * from the sensor's nominal frame rate, send the frame interval error
- * event. The frame intervals are averaged in order to quiet noise from
+ * from the nominal frame rate, send the frame interval error event. The
+ * frame intervals are averaged in order to quiet noise from
* (presumably random) interrupt latency.
*/
static void frame_interval_monitor(struct imx_media_fim *fim,
@@ -422,12 +414,12 @@ EXPORT_SYMBOL_GPL(imx_media_fim_set_power);
/* Called by the subdev in its s_stream callback */
int imx_media_fim_set_stream(struct imx_media_fim *fim,
- struct imx_media_subdev *sensor,
+ const struct v4l2_fract *fi,
bool on)
{
if (on) {
reset_fim(fim, true);
- update_fim_nominal(fim, sensor);
+ update_fim_nominal(fim, fi);
if (fim->icap_channel >= 0)
fim_acquire_first_ts(fim);
diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
index ae3af0d..7f19739 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -259,7 +259,7 @@ struct imx_media_fim;
void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts);
int imx_media_fim_set_power(struct imx_media_fim *fim, bool on);
int imx_media_fim_set_stream(struct imx_media_fim *fim,
- struct imx_media_subdev *sensor,
+ const struct v4l2_fract *frame_interval,
bool on);
struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd);
void imx_media_fim_free(struct imx_media_fim *fim);
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <steve_longerbeam@mentor.com> |
|---|---|
| Date | 2017-02-16 03:40 +0100 |
| Subject | Re: [PATCH v4 32/36] media: imx: csi/fim: add support for frame intervals |
| Message-ID | <tbk9b-8g7-19@gated-at.bofh.it> |
| In reply to | #1582271 |
Sorry, I forgot to change authorship on this patch. It should
be authored by Russell King <rmk+kernel@armlinux.org.uk>.
Steve
On 02/15/2017 06:19 PM, Steve Longerbeam wrote:
> Add support to CSI for negotiation of frame intervals, and use this
> information to configure the frame interval monitor.
>
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> drivers/staging/media/imx/imx-media-csi.c | 36 ++++++++++++++++++++++++++++---
> drivers/staging/media/imx/imx-media-fim.c | 28 +++++++++---------------
> drivers/staging/media/imx/imx-media.h | 2 +-
> 3 files changed, 44 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> index b0aac82..040cca6 100644
> --- a/drivers/staging/media/imx/imx-media-csi.c
> +++ b/drivers/staging/media/imx/imx-media-csi.c
> @@ -56,6 +56,7 @@ struct csi_priv {
>
> struct v4l2_mbus_framefmt format_mbus[CSI_NUM_PADS];
> const struct imx_media_pixfmt *cc[CSI_NUM_PADS];
> + struct v4l2_fract frame_interval;
> struct v4l2_rect crop;
>
> /* the video device at IDMAC output pad */
> @@ -565,7 +566,8 @@ static int csi_start(struct csi_priv *priv)
>
> /* start the frame interval monitor */
> if (priv->fim) {
> - ret = imx_media_fim_set_stream(priv->fim, priv->sensor, true);
> + ret = imx_media_fim_set_stream(priv->fim,
> + &priv->frame_interval, true);
> if (ret)
> goto idmac_stop;
> }
> @@ -580,7 +582,8 @@ static int csi_start(struct csi_priv *priv)
>
> fim_off:
> if (priv->fim)
> - imx_media_fim_set_stream(priv->fim, priv->sensor, false);
> + imx_media_fim_set_stream(priv->fim,
> + &priv->frame_interval, false);
> idmac_stop:
> if (priv->dest == IPU_CSI_DEST_IDMAC)
> csi_idmac_stop(priv);
> @@ -594,11 +597,36 @@ static void csi_stop(struct csi_priv *priv)
>
> /* stop the frame interval monitor */
> if (priv->fim)
> - imx_media_fim_set_stream(priv->fim, priv->sensor, false);
> + imx_media_fim_set_stream(priv->fim,
> + &priv->frame_interval, false);
>
> ipu_csi_disable(priv->csi);
> }
>
> +static int csi_g_frame_interval(struct v4l2_subdev *sd,
> + struct v4l2_subdev_frame_interval *fi)
> +{
> + struct csi_priv *priv = v4l2_get_subdevdata(sd);
> +
> + fi->interval = priv->frame_interval;
> +
> + return 0;
> +}
> +
> +static int csi_s_frame_interval(struct v4l2_subdev *sd,
> + struct v4l2_subdev_frame_interval *fi)
> +{
> + struct csi_priv *priv = v4l2_get_subdevdata(sd);
> +
> + /* Output pads mirror active input pad, no limits on input pads */
> + if (fi->pad == CSI_SRC_PAD_IDMAC || fi->pad == CSI_SRC_PAD_DIRECT)
> + fi->interval = priv->frame_interval;
> +
> + priv->frame_interval = fi->interval;
> +
> + return 0;
> +}
> +
> static int csi_s_stream(struct v4l2_subdev *sd, int enable)
> {
> struct csi_priv *priv = v4l2_get_subdevdata(sd);
> @@ -1187,6 +1215,8 @@ static struct v4l2_subdev_core_ops csi_core_ops = {
> };
>
> static struct v4l2_subdev_video_ops csi_video_ops = {
> + .g_frame_interval = csi_g_frame_interval,
> + .s_frame_interval = csi_s_frame_interval,
> .s_stream = csi_s_stream,
> };
>
> diff --git a/drivers/staging/media/imx/imx-media-fim.c b/drivers/staging/media/imx/imx-media-fim.c
> index acc7e39..a6ed57e 100644
> --- a/drivers/staging/media/imx/imx-media-fim.c
> +++ b/drivers/staging/media/imx/imx-media-fim.c
> @@ -67,26 +67,18 @@ struct imx_media_fim {
> };
>
> static void update_fim_nominal(struct imx_media_fim *fim,
> - struct imx_media_subdev *sensor)
> + const struct v4l2_fract *fi)
> {
> - struct v4l2_streamparm parm;
> - struct v4l2_fract tpf;
> - int ret;
> -
> - parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> - ret = v4l2_subdev_call(sensor->sd, video, g_parm, &parm);
> - tpf = parm.parm.capture.timeperframe;
> -
> - if (ret || tpf.denominator == 0) {
> - dev_dbg(fim->sd->dev, "no tpf from sensor, FIM disabled\n");
> + if (fi->denominator == 0) {
> + dev_dbg(fim->sd->dev, "no frame interval, FIM disabled\n");
> fim->enabled = false;
> return;
> }
>
> - fim->nominal = DIV_ROUND_CLOSEST(1000 * 1000 * tpf.numerator,
> - tpf.denominator);
> + fim->nominal = DIV_ROUND_CLOSEST_ULL(1000000ULL * (u64)fi->numerator,
> + fi->denominator);
>
> - dev_dbg(fim->sd->dev, "sensor FI=%lu usec\n", fim->nominal);
> + dev_dbg(fim->sd->dev, "FI=%lu usec\n", fim->nominal);
> }
>
> static void reset_fim(struct imx_media_fim *fim, bool curval)
> @@ -130,8 +122,8 @@ static void send_fim_event(struct imx_media_fim *fim, unsigned long error)
>
> /*
> * Monitor an averaged frame interval. If the average deviates too much
> - * from the sensor's nominal frame rate, send the frame interval error
> - * event. The frame intervals are averaged in order to quiet noise from
> + * from the nominal frame rate, send the frame interval error event. The
> + * frame intervals are averaged in order to quiet noise from
> * (presumably random) interrupt latency.
> */
> static void frame_interval_monitor(struct imx_media_fim *fim,
> @@ -422,12 +414,12 @@ EXPORT_SYMBOL_GPL(imx_media_fim_set_power);
>
> /* Called by the subdev in its s_stream callback */
> int imx_media_fim_set_stream(struct imx_media_fim *fim,
> - struct imx_media_subdev *sensor,
> + const struct v4l2_fract *fi,
> bool on)
> {
> if (on) {
> reset_fim(fim, true);
> - update_fim_nominal(fim, sensor);
> + update_fim_nominal(fim, fi);
>
> if (fim->icap_channel >= 0)
> fim_acquire_first_ts(fim);
> diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
> index ae3af0d..7f19739 100644
> --- a/drivers/staging/media/imx/imx-media.h
> +++ b/drivers/staging/media/imx/imx-media.h
> @@ -259,7 +259,7 @@ struct imx_media_fim;
> void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts);
> int imx_media_fim_set_power(struct imx_media_fim *fim, bool on);
> int imx_media_fim_set_stream(struct imx_media_fim *fim,
> - struct imx_media_subdev *sensor,
> + const struct v4l2_fract *frame_interval,
> bool on);
> struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd);
> void imx_media_fim_free(struct imx_media_fim *fim);
--
Steve Longerbeam | Senior Embedded Engineer, ESD Services
Mentor Embedded(tm) | 46871 Bayside Parkway, Fremont, CA 94538
P 510.354.5838 | M 408.410.2735
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 03:30 +0100 |
| Subject | [PATCH v4 09/36] ARM: dts: imx6-sabreauto: add reset-gpios property for max7310_b |
| Message-ID | <tbjZx-8cO-63@gated-at.bofh.it> |
| In reply to | #1582252 |
The reset pin to the port expander chip (MAX7310) is controlled by a gpio,
so define a reset-gpios property to control it. There are three MAX7310's
on the SabreAuto CPU card (max7310_[abc]), but all use the same pin for
their reset. Since all can't acquire the same pin, assign it to max7310_b,
that chip is needed by more functions (usb and adv7180).
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index cace88c..967c3b8 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -136,6 +136,9 @@
reg = <0x32>;
gpio-controller;
#gpio-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_max7310>;
+ reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
max7310_c: gpio@34 {
@@ -442,6 +445,12 @@
>;
};
+ pinctrl_max7310: max7310grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x1b0b0
+ >;
+ };
+
pinctrl_pwm3: pwm1grp {
fsl,pins = <
MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 03:40 +0100 |
| Subject | [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver |
| Message-ID | <tbk9b-8g7-1@gated-at.bofh.it> |
| In reply to | #1582252 |
Add bindings documentation for the i.MX media driver.
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Documentation/devicetree/bindings/media/imx.txt | 66 +++++++++++++++++++++++++
1 file changed, 66 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/imx.txt
diff --git a/Documentation/devicetree/bindings/media/imx.txt b/Documentation/devicetree/bindings/media/imx.txt
new file mode 100644
index 0000000..fd5af50
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/imx.txt
@@ -0,0 +1,66 @@
+Freescale i.MX Media Video Device
+=================================
+
+Video Media Controller node
+---------------------------
+
+This is the media controller node for video capture support. It is a
+virtual device that lists the camera serial interface nodes that the
+media device will control.
+
+Required properties:
+- compatible : "fsl,imx-capture-subsystem";
+- ports : Should contain a list of phandles pointing to camera
+ sensor interface ports of IPU devices
+
+example:
+
+capture-subsystem {
+ compatible = "fsl,capture-subsystem";
+ ports = <&ipu1_csi0>, <&ipu1_csi1>;
+};
+
+fim child node
+--------------
+
+This is an optional child node of the ipu_csi port nodes. If present and
+available, it enables the Frame Interval Monitor. Its properties can be
+used to modify the method in which the FIM measures frame intervals.
+Refer to Documentation/media/v4l-drivers/imx.rst for more info on the
+Frame Interval Monitor.
+
+Optional properties:
+- fsl,input-capture-channel: an input capture channel and channel flags,
+ specified as <chan flags>. The channel number
+ must be 0 or 1. The flags can be
+ IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, or
+ IRQ_TYPE_EDGE_BOTH, and specify which input
+ capture signal edge will trigger the input
+ capture event. If an input capture channel is
+ specified, the FIM will use this method to
+ measure frame intervals instead of via the EOF
+ interrupt. The input capture method is much
+ preferred over EOF as it is not subject to
+ interrupt latency errors. However it requires
+ routing the VSYNC or FIELD output signals of
+ the camera sensor to one of the i.MX input
+ capture pads (SD1_DAT0, SD1_DAT1), which also
+ gives up support for SD1.
+
+
+mipi_csi2 node
+--------------
+
+This is the device node for the MIPI CSI-2 Receiver, required for MIPI
+CSI-2 sensors.
+
+Required properties:
+- compatible : "fsl,imx6-mipi-csi2", "snps,dw-mipi-csi2";
+- reg : physical base address and length of the register set;
+- clocks : the MIPI CSI-2 receiver requires three clocks: hsi_tx
+ (the DPHY clock), video_27m, and eim_podf;
+- clock-names : must contain "dphy", "cfg", "pix";
+
+Optional properties:
+- interrupts : must contain two level-triggered interrupts,
+ in order: 100 and 101;
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Philipp Zabel <p.zabel@pengutronix.de> |
|---|---|
| Date | 2017-02-16 13:00 +0100 |
| Subject | Re: [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver |
| Message-ID | <tbsT8-5Hw-19@gated-at.bofh.it> |
| In reply to | #1582274 |
On Wed, 2017-02-15 at 18:19 -0800, Steve Longerbeam wrote:
> Add bindings documentation for the i.MX media driver.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> Documentation/devicetree/bindings/media/imx.txt | 66 +++++++++++++++++++++++++
> 1 file changed, 66 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/imx.txt
>
> diff --git a/Documentation/devicetree/bindings/media/imx.txt b/Documentation/devicetree/bindings/media/imx.txt
> new file mode 100644
> index 0000000..fd5af50
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/imx.txt
> @@ -0,0 +1,66 @@
> +Freescale i.MX Media Video Device
> +=================================
> +
> +Video Media Controller node
> +---------------------------
> +
> +This is the media controller node for video capture support. It is a
> +virtual device that lists the camera serial interface nodes that the
> +media device will control.
> +
> +Required properties:
> +- compatible : "fsl,imx-capture-subsystem";
> +- ports : Should contain a list of phandles pointing to camera
> + sensor interface ports of IPU devices
> +
> +example:
> +
> +capture-subsystem {
> + compatible = "fsl,capture-subsystem";
"fsl,imx-capture-subsystem"
regards
Philipp
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 20:30 +0100 |
| Subject | Re: [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver |
| Message-ID | <tbzUC-2oT-19@gated-at.bofh.it> |
| In reply to | #1582520 |
On 02/16/2017 03:54 AM, Philipp Zabel wrote:
> On Wed, 2017-02-15 at 18:19 -0800, Steve Longerbeam wrote:
>> Add bindings documentation for the i.MX media driver.
>>
>> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
>> ---
>> Documentation/devicetree/bindings/media/imx.txt | 66 +++++++++++++++++++++++++
>> 1 file changed, 66 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/media/imx.txt
>>
>> diff --git a/Documentation/devicetree/bindings/media/imx.txt b/Documentation/devicetree/bindings/media/imx.txt
>> new file mode 100644
>> index 0000000..fd5af50
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/imx.txt
>> @@ -0,0 +1,66 @@
>> +Freescale i.MX Media Video Device
>> +=================================
>> +
>> +Video Media Controller node
>> +---------------------------
>> +
>> +This is the media controller node for video capture support. It is a
>> +virtual device that lists the camera serial interface nodes that the
>> +media device will control.
>> +
>> +Required properties:
>> +- compatible : "fsl,imx-capture-subsystem";
>> +- ports : Should contain a list of phandles pointing to camera
>> + sensor interface ports of IPU devices
>> +
>> +example:
>> +
>> +capture-subsystem {
>> + compatible = "fsl,capture-subsystem";
>
> "fsl,imx-capture-subsystem"
Fixed.
Steve
[toc] | [prev] | [next] | [standalone]
| From | Rob Herring <robh@kernel.org> |
|---|---|
| Date | 2017-02-27 15:50 +0100 |
| Subject | Re: [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver |
| Message-ID | <tfuMH-6Wf-25@gated-at.bofh.it> |
| In reply to | #1582274 |
On Wed, Feb 15, 2017 at 06:19:03PM -0800, Steve Longerbeam wrote:
> Add bindings documentation for the i.MX media driver.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> Documentation/devicetree/bindings/media/imx.txt | 66 +++++++++++++++++++++++++
> 1 file changed, 66 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/imx.txt
>
> diff --git a/Documentation/devicetree/bindings/media/imx.txt b/Documentation/devicetree/bindings/media/imx.txt
> new file mode 100644
> index 0000000..fd5af50
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/imx.txt
> @@ -0,0 +1,66 @@
> +Freescale i.MX Media Video Device
> +=================================
> +
> +Video Media Controller node
> +---------------------------
> +
> +This is the media controller node for video capture support. It is a
> +virtual device that lists the camera serial interface nodes that the
> +media device will control.
> +
> +Required properties:
> +- compatible : "fsl,imx-capture-subsystem";
> +- ports : Should contain a list of phandles pointing to camera
> + sensor interface ports of IPU devices
> +
> +example:
> +
> +capture-subsystem {
> + compatible = "fsl,capture-subsystem";
> + ports = <&ipu1_csi0>, <&ipu1_csi1>;
> +};
> +
> +fim child node
> +--------------
> +
> +This is an optional child node of the ipu_csi port nodes. If present and
> +available, it enables the Frame Interval Monitor. Its properties can be
> +used to modify the method in which the FIM measures frame intervals.
> +Refer to Documentation/media/v4l-drivers/imx.rst for more info on the
> +Frame Interval Monitor.
This should have a compatible string.
> +
> +Optional properties:
> +- fsl,input-capture-channel: an input capture channel and channel flags,
> + specified as <chan flags>. The channel number
> + must be 0 or 1. The flags can be
> + IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, or
> + IRQ_TYPE_EDGE_BOTH, and specify which input
> + capture signal edge will trigger the input
> + capture event. If an input capture channel is
> + specified, the FIM will use this method to
> + measure frame intervals instead of via the EOF
> + interrupt. The input capture method is much
> + preferred over EOF as it is not subject to
> + interrupt latency errors. However it requires
> + routing the VSYNC or FIELD output signals of
> + the camera sensor to one of the i.MX input
> + capture pads (SD1_DAT0, SD1_DAT1), which also
> + gives up support for SD1.
> +
> +
> +mipi_csi2 node
> +--------------
> +
> +This is the device node for the MIPI CSI-2 Receiver, required for MIPI
> +CSI-2 sensors.
> +
> +Required properties:
> +- compatible : "fsl,imx6-mipi-csi2", "snps,dw-mipi-csi2";
> +- reg : physical base address and length of the register set;
> +- clocks : the MIPI CSI-2 receiver requires three clocks: hsi_tx
> + (the DPHY clock), video_27m, and eim_podf;
> +- clock-names : must contain "dphy", "cfg", "pix";
Don't you need ports to describe the sensor and IPU connections?
> +
> +Optional properties:
> +- interrupts : must contain two level-triggered interrupts,
> + in order: 100 and 101;
> --
> 2.7.4
>
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-03-01 01:40 +0100 |
| Subject | Re: [PATCH v4 01/36] [media] dt-bindings: Add bindings for i.MX media driver |
| Message-ID | <tg0tc-3nR-17@gated-at.bofh.it> |
| In reply to | #1588696 |
Hi Rob,
On 02/27/2017 06:38 AM, Rob Herring wrote:
> On Wed, Feb 15, 2017 at 06:19:03PM -0800, Steve Longerbeam wrote:
>> Add bindings documentation for the i.MX media driver.
>>
>> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
>> ---
>> Documentation/devicetree/bindings/media/imx.txt | 66 +++++++++++++++++++++++++
>> 1 file changed, 66 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/media/imx.txt
>>
>> diff --git a/Documentation/devicetree/bindings/media/imx.txt b/Documentation/devicetree/bindings/media/imx.txt
>> new file mode 100644
>> index 0000000..fd5af50
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/imx.txt
>> @@ -0,0 +1,66 @@
>> +Freescale i.MX Media Video Device
>> +=================================
>> +
>> +Video Media Controller node
>> +---------------------------
>> +
>> +This is the media controller node for video capture support. It is a
>> +virtual device that lists the camera serial interface nodes that the
>> +media device will control.
>> +
>> +Required properties:
>> +- compatible : "fsl,imx-capture-subsystem";
>> +- ports : Should contain a list of phandles pointing to camera
>> + sensor interface ports of IPU devices
>> +
>> +example:
>> +
>> +capture-subsystem {
>> + compatible = "fsl,capture-subsystem";
>> + ports = <&ipu1_csi0>, <&ipu1_csi1>;
>> +};
>> +
>> +fim child node
>> +--------------
>> +
>> +This is an optional child node of the ipu_csi port nodes. If present and
>> +available, it enables the Frame Interval Monitor. Its properties can be
>> +used to modify the method in which the FIM measures frame intervals.
>> +Refer to Documentation/media/v4l-drivers/imx.rst for more info on the
>> +Frame Interval Monitor.
> This should have a compatible string.
I don't think so. The fim child node does not represent a device. The
CSI supports monitoring frame intervals (reporting via a v4l2 event
when a measured frame interval falls outside the nominal interval
by some tolerance value). The fim child node is only to group properties
for the FIM under a common child node.
>> +
>> +Optional properties:
>> +- fsl,input-capture-channel: an input capture channel and channel flags,
>> + specified as <chan flags>. The channel number
>> + must be 0 or 1. The flags can be
>> + IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, or
>> + IRQ_TYPE_EDGE_BOTH, and specify which input
>> + capture signal edge will trigger the input
>> + capture event. If an input capture channel is
>> + specified, the FIM will use this method to
>> + measure frame intervals instead of via the EOF
>> + interrupt. The input capture method is much
>> + preferred over EOF as it is not subject to
>> + interrupt latency errors. However it requires
>> + routing the VSYNC or FIELD output signals of
>> + the camera sensor to one of the i.MX input
>> + capture pads (SD1_DAT0, SD1_DAT1), which also
>> + gives up support for SD1.
>> +
>> +
>> +mipi_csi2 node
>> +--------------
>> +
>> +This is the device node for the MIPI CSI-2 Receiver, required for MIPI
>> +CSI-2 sensors.
>> +
>> +Required properties:
>> +- compatible : "fsl,imx6-mipi-csi2", "snps,dw-mipi-csi2";
>> +- reg : physical base address and length of the register set;
>> +- clocks : the MIPI CSI-2 receiver requires three clocks: hsi_tx
>> + (the DPHY clock), video_27m, and eim_podf;
>> +- clock-names : must contain "dphy", "cfg", "pix";
> Don't you need ports to describe the sensor and IPU connections?
Done.
Steve
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 03:40 +0100 |
| Subject | [PATCH v4 04/36] ARM: dts: imx6qdl: add capture-subsystem device |
| Message-ID | <tbk9b-8g7-11@gated-at.bofh.it> |
| In reply to | #1582252 |
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
arch/arm/boot/dts/imx6dl.dtsi | 5 +++++
arch/arm/boot/dts/imx6q.dtsi | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 371288a..f1743fc 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -100,6 +100,11 @@
};
};
+ capture-subsystem {
+ compatible = "fsl,imx-capture-subsystem";
+ ports = <&ipu1_csi0>, <&ipu1_csi1>;
+ };
+
display-subsystem {
compatible = "fsl,imx-display-subsystem";
ports = <&ipu1_di0>, <&ipu1_di1>;
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index b833b0d..4cc6579 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -206,6 +206,11 @@
};
};
+ capture-subsystem {
+ compatible = "fsl,imx-capture-subsystem";
+ ports = <&ipu1_csi0>, <&ipu1_csi1>, <&ipu2_csi0>, <&ipu2_csi1>;
+ };
+
display-subsystem {
compatible = "fsl,imx-display-subsystem";
ports = <&ipu1_di0>, <&ipu1_di1>, <&ipu2_di0>, <&ipu2_di1>;
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Russell King - ARM Linux <linux@armlinux.org.uk> |
|---|---|
| Date | 2017-02-16 11:30 +0100 |
| Subject | Re: [PATCH v4 18/36] media: Add i.MX media core driver |
| Message-ID | <tbru2-4Oj-7@gated-at.bofh.it> |
| In reply to | #1582252 |
On Wed, Feb 15, 2017 at 06:19:20PM -0800, Steve Longerbeam wrote: > Add the core media driver for i.MX SOC. > > Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> Just as I reported on the 30th January: Applying: media: Add i.MX media core driver .git/rebase-apply/patch:614: new blank line at EOF. + .git/rebase-apply/patch:626: new blank line at EOF. + .git/rebase-apply/patch:668: new blank line at EOF. + These need fixing. -- RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up according to speedtest.net.
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 19:00 +0100 |
| Subject | Re: [PATCH v4 18/36] media: Add i.MX media core driver |
| Message-ID | <tbyvy-1iO-61@gated-at.bofh.it> |
| In reply to | #1582444 |
On 02/16/2017 02:27 AM, Russell King - ARM Linux wrote: > On Wed, Feb 15, 2017 at 06:19:20PM -0800, Steve Longerbeam wrote: >> Add the core media driver for i.MX SOC. >> >> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> > Just as I reported on the 30th January: > > Applying: media: Add i.MX media core driver > .git/rebase-apply/patch:614: new blank line at EOF. > + > .git/rebase-apply/patch:626: new blank line at EOF. > + > .git/rebase-apply/patch:668: new blank line at EOF. > + > > These need fixing. Missed these obviously, fixed. Steve
[toc] | [prev] | [next] | [standalone]
| From | Russell King - ARM Linux <linux@armlinux.org.uk> |
|---|---|
| Date | 2017-02-16 12:40 +0100 |
| Message-ID | <tbszM-5Ab-5@gated-at.bofh.it> |
| In reply to | #1582252 |
Two problems.
On Wed, Feb 15, 2017 at 06:19:02PM -0800, Steve Longerbeam wrote:
> media: imx: propagate sink pad formats to source pads
1) It looks like all cases aren't being caught:
- entity 74: ipu1_csi0 (3 pads, 4 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev13
pad0: Sink
[fmt:SRGGB8/816x616 field:none]
<- "ipu1_csi0_mux":2 [ENABLED]
pad1: Source
[fmt:AYUV32/816x616 field:none
crop.bounds:(0,0)/816x616
crop:(0,0)/816x616]
-> "ipu1_ic_prp":0 []
-> "ipu1_vdic":0 []
pad2: Source
[fmt:SRGGB8/816x616 field:none
crop.bounds:(0,0)/816x616
crop:(0,0)/816x616]
-> "ipu1_csi0 capture":0 [ENABLED]
While the size has been propagated to pad1, the format has not.
2) /dev/video* device node assignment
I've no idea at the moment how the correct /dev/video* node should be
chosen - initially with Philipp and your previous code, it was
/dev/video3 after initial boot. Philipp's was consistently /dev/video3.
Yours changed to /dev/video7 when removing and re-inserting the modules
(having fixed that locally.) This version makes CSI0 be /dev/video7,
but after a remove+reinsert, it becomes (eg) /dev/video8.
/dev/v4l/by-path/platform-capture-subsystem-video-index4 also is not a
stable path - the digit changes (it's supposed to be a stable path.)
After a remove+reinsert, it becomes (eg)
/dev/v4l/by-path/platform-capture-subsystem-video-index5.
/dev/v4l/by-id doesn't contain a symlink for this either.
What this means is that it's very hard to script the setup, because
there's no easy way to know what device is the capture device. While
it may be possible to do:
media-ctl -d /dev/media1 -p | \
grep -A2 ': ipu1_csi0 capture' | \
sed -n 's|.*\(/dev/video[0-9]*\).*|\1|p'
that's hardly a nice solution - while it fixes the setup script, it
doesn't stop the pain of having to delve around to find the correct
device to use for gstreamer to test with.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
[toc] | [prev] | [next] | [standalone]
| From | Steve Longerbeam <slongerbeam@gmail.com> |
|---|---|
| Date | 2017-02-16 19:40 +0100 |
| Message-ID | <tbz8d-1OZ-19@gated-at.bofh.it> |
| In reply to | #1582489 |
On 02/16/2017 03:37 AM, Russell King - ARM Linux wrote: > Two problems. > > On Wed, Feb 15, 2017 at 06:19:02PM -0800, Steve Longerbeam wrote: >> media: imx: propagate sink pad formats to source pads > > 1) It looks like all cases aren't being caught: > > - entity 74: ipu1_csi0 (3 pads, 4 links) > type V4L2 subdev subtype Unknown flags 0 > device node name /dev/v4l-subdev13 > pad0: Sink > [fmt:SRGGB8/816x616 field:none] > <- "ipu1_csi0_mux":2 [ENABLED] > pad1: Source > [fmt:AYUV32/816x616 field:none > crop.bounds:(0,0)/816x616 > crop:(0,0)/816x616] > -> "ipu1_ic_prp":0 [] > -> "ipu1_vdic":0 [] > pad2: Source > [fmt:SRGGB8/816x616 field:none > crop.bounds:(0,0)/816x616 > crop:(0,0)/816x616] > -> "ipu1_csi0 capture":0 [ENABLED] > > While the size has been propagated to pad1, the format has not. Right, Philipp also caught this. I need to finish propagating all params from sink to source pads (mbus code and field, and colorimetry eventually). > > 2) /dev/video* device node assignment > > I've no idea at the moment how the correct /dev/video* node should be > chosen - initially with Philipp and your previous code, it was > /dev/video3 after initial boot. Philipp's was consistently /dev/video3. > Yours changed to /dev/video7 when removing and re-inserting the modules > (having fixed that locally.) This version makes CSI0 be /dev/video7, > but after a remove+reinsert, it becomes (eg) /dev/video8. > > /dev/v4l/by-path/platform-capture-subsystem-video-index4 also is not a > stable path - the digit changes (it's supposed to be a stable path.) > After a remove+reinsert, it becomes (eg) > /dev/v4l/by-path/platform-capture-subsystem-video-index5. > /dev/v4l/by-id doesn't contain a symlink for this either. > > What this means is that it's very hard to script the setup, because > there's no easy way to know what device is the capture device. While > it may be possible to do: > > media-ctl -d /dev/media1 -p | \ > grep -A2 ': ipu1_csi0 capture' | \ > sed -n 's|.*\(/dev/video[0-9]*\).*|\1|p' > > that's hardly a nice solution - while it fixes the setup script, it > doesn't stop the pain of having to delve around to find the correct > device to use for gstreamer to test with. > I'll try to nail down the main capture node numbers, even after module reload. Steve
[toc] | [prev] | [next] | [standalone]
Page 4 of 5 — ← Prev page 1 2 3 [4] 5 Next page →
Back to top | Article view | linux.kernel
csiph-web