* [PATCH v9 1/8] media: dt-bindings: Add JH7110 Camera Subsystem
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
@ 2023-09-14 3:16 ` Jack Zhu
2023-09-14 3:16 ` [PATCH v9 2/8] media: admin-guide: Add starfive_camss.rst for Starfive " Jack Zhu
` (7 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Jack Zhu @ 2023-09-14 3:16 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Robert Foss, Todor Tomov, bryan.odonoghue,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart, Hans Verkuil
Cc: linux-media, linux-kernel, devicetree, linux-staging, jack.zhu,
changhuang.liang
Add the bindings documentation for Starfive JH7110 Camera Subsystem
which is used for handing image sensor data.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
.../bindings/media/starfive,jh7110-camss.yaml | 180 ++++++++++++++++++
MAINTAINERS | 7 +
2 files changed, 187 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
diff --git a/Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml b/Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
new file mode 100644
index 000000000000..c66586d90fa2
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
@@ -0,0 +1,180 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/starfive,jh7110-camss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Starfive SoC CAMSS ISP
+
+maintainers:
+ - Jack Zhu <jack.zhu@starfivetech.com>
+ - Changhuang Liang <changhuang.liang@starfivetech.com>
+
+description:
+ The Starfive CAMSS ISP is a Camera interface for Starfive JH7110 SoC. It
+ consists of a VIN controller (Video In Controller, a top-level control unit)
+ and an ISP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-camss
+
+ reg:
+ maxItems: 2
+
+ reg-names:
+ items:
+ - const: syscon
+ - const: isp
+
+ clocks:
+ maxItems: 7
+
+ clock-names:
+ items:
+ - const: apb_func
+ - const: wrapper_clk_c
+ - const: dvp_inv
+ - const: axiwr
+ - const: mipi_rx0_pxl
+ - const: ispcore_2x
+ - const: isp_axi
+
+ resets:
+ maxItems: 6
+
+ reset-names:
+ items:
+ - const: wrapper_p
+ - const: wrapper_c
+ - const: axird
+ - const: axiwr
+ - const: isp_top_n
+ - const: isp_top_axi
+
+ power-domains:
+ items:
+ - description: JH7110 ISP Power Domain Switch Controller.
+
+ interrupts:
+ maxItems: 4
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: Input port for receiving DVP data.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ bus-type:
+ enum: [5, 6]
+
+ bus-width:
+ enum: [8, 10, 12]
+
+ data-shift:
+ enum: [0, 2]
+ default: 0
+
+ hsync-active:
+ enum: [0, 1]
+ default: 1
+
+ vsync-active:
+ enum: [0, 1]
+ default: 1
+
+ required:
+ - bus-type
+ - bus-width
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Input port for receiving CSI data.
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - power-domains
+ - interrupts
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ isp@19840000 {
+ compatible = "starfive,jh7110-camss";
+ reg = <0x19840000 0x10000>,
+ <0x19870000 0x30000>;
+ reg-names = "syscon", "isp";
+ clocks = <&ispcrg 0>,
+ <&ispcrg 13>,
+ <&ispcrg 2>,
+ <&ispcrg 12>,
+ <&ispcrg 1>,
+ <&syscrg 51>,
+ <&syscrg 52>;
+ clock-names = "apb_func",
+ "wrapper_clk_c",
+ "dvp_inv",
+ "axiwr",
+ "mipi_rx0_pxl",
+ "ispcore_2x",
+ "isp_axi";
+ resets = <&ispcrg 0>,
+ <&ispcrg 1>,
+ <&ispcrg 10>,
+ <&ispcrg 11>,
+ <&syscrg 41>,
+ <&syscrg 42>;
+ reset-names = "wrapper_p",
+ "wrapper_c",
+ "axird",
+ "axiwr",
+ "isp_top_n",
+ "isp_top_axi";
+ power-domains = <&pwrc 5>;
+ interrupts = <92>, <87>, <88>, <90>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ vin_from_sc2235: endpoint {
+ remote-endpoint = <&sc2235_to_vin>;
+ bus-type = <5>;
+ bus-width = <8>;
+ data-shift = <2>;
+ hsync-active = <1>;
+ vsync-active = <0>;
+ pclk-sample = <1>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ vin_from_csi2rx: endpoint {
+ remote-endpoint = <&csi2rx_to_vin>;
+ };
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 6bb6d27b823c..8fd44a3e0b8f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20263,6 +20263,13 @@ M: Ion Badulescu <ionut@badula.org>
S: Odd Fixes
F: drivers/net/ethernet/adaptec/starfire*
+STARFIVE CAMERA SUBSYSTEM DRIVER
+M: Jack Zhu <jack.zhu@starfivetech.com>
+M: Changhuang Liang <changhuang.liang@starfivetech.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
+
STARFIVE CRYPTO DRIVER
M: Jia Jie Ho <jiajie.ho@starfivetech.com>
M: William Qiu <william.qiu@starfivetech.com>
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v9 2/8] media: admin-guide: Add starfive_camss.rst for Starfive Camera Subsystem
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
2023-09-14 3:16 ` [PATCH v9 1/8] media: dt-bindings: Add JH7110 Camera Subsystem Jack Zhu
@ 2023-09-14 3:16 ` Jack Zhu
2023-09-14 3:16 ` [PATCH v9 3/8] media: staging: media: starfive: camss: Add core driver Jack Zhu
` (6 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Jack Zhu @ 2023-09-14 3:16 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Robert Foss, Todor Tomov, bryan.odonoghue,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart, Hans Verkuil
Cc: linux-media, linux-kernel, devicetree, linux-staging, jack.zhu,
changhuang.liang
Add starfive_camss.rst file that documents the Starfive Camera
Subsystem driver which is used for handing image sensor data.
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
.../admin-guide/media/starfive_camss.rst | 72 +++++++++++++++++++
.../media/starfive_camss_graph.dot | 12 ++++
.../admin-guide/media/v4l-drivers.rst | 1 +
MAINTAINERS | 1 +
4 files changed, 86 insertions(+)
create mode 100644 Documentation/admin-guide/media/starfive_camss.rst
create mode 100644 Documentation/admin-guide/media/starfive_camss_graph.dot
diff --git a/Documentation/admin-guide/media/starfive_camss.rst b/Documentation/admin-guide/media/starfive_camss.rst
new file mode 100644
index 000000000000..ca42e9447c47
--- /dev/null
+++ b/Documentation/admin-guide/media/starfive_camss.rst
@@ -0,0 +1,72 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: <isonum.txt>
+
+================================
+Starfive Camera Subsystem driver
+================================
+
+Introduction
+------------
+
+This file documents the driver for the Starfive Camera Subsystem found on
+Starfive JH7110 SoC. The driver is located under drivers/staging/media/starfive/
+camss.
+
+The driver implements V4L2, Media controller and v4l2_subdev interfaces. Camera
+sensor using V4L2 subdev interface in the kernel is supported.
+
+The driver has been successfully used on the Gstreamer 1.18.5 with v4l2src
+plugin.
+
+
+Starfive Camera Subsystem hardware
+----------------------------------
+
+The Starfive Camera Subsystem hardware consists of::
+
+ |\ +---------------+ +-----------+
+ +----------+ | \ | | | |
+ | | | | | | | |
+ | MIPI |----->| |----->| ISP |----->| |
+ | | | | | | | |
+ +----------+ | | | | | Memory |
+ |MUX| +---------------+ | Interface |
+ +----------+ | | | |
+ | | | |---------------------------->| |
+ | Parallel |----->| | | |
+ | | | | | |
+ +----------+ | / | |
+ |/ +-----------+
+
+- MIPI: The MIPI interface, receiving data from a MIPI CSI-2 camera sensor.
+
+- Parallel: The parallel interface, receiving data from a parallel sensor.
+
+- ISP: The ISP, processing raw Bayer data from an image sensor and producing
+ YUV frames.
+
+
+Topology
+--------
+
+The media controller pipeline graph is as follows:
+
+.. _starfive_camss_graph:
+
+.. kernel-figure:: starfive_camss_graph.dot
+ :alt: starfive_camss_graph.dot
+ :align: center
+
+The driver has 2 video devices:
+
+- capture_raw: The capture device, capturing image data directly from a sensor.
+- capture_yuv: The capture device, capturing YUV frame data processed by the
+ ISP module
+
+The driver has 3 subdevices:
+
+- stf_isp: is responsible for all the isp operations, outputs YUV frames.
+- cdns_csi2rx: a CSI-2 bridge supporting up to 4 CSI lanes in input, and 4
+ different pixel streams in output.
+- imx219: an image sensor, image data is sent through MIPI CSI-2.
diff --git a/Documentation/admin-guide/media/starfive_camss_graph.dot b/Documentation/admin-guide/media/starfive_camss_graph.dot
new file mode 100644
index 000000000000..8eff1f161ac7
--- /dev/null
+++ b/Documentation/admin-guide/media/starfive_camss_graph.dot
@@ -0,0 +1,12 @@
+digraph board {
+ rankdir=TB
+ n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
+ n00000001:port1 -> n00000008 [style=dashed]
+ n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
+ n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
+ n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
+ n0000000e:port1 -> n00000001:port0 [style=dashed]
+ n0000000e:port1 -> n00000004 [style=dashed]
+ n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
+ n00000018:port0 -> n0000000e:port0 [style=bold]
+}
diff --git a/Documentation/admin-guide/media/v4l-drivers.rst b/Documentation/admin-guide/media/v4l-drivers.rst
index 1c41f87c3917..2274fd29c1d7 100644
--- a/Documentation/admin-guide/media/v4l-drivers.rst
+++ b/Documentation/admin-guide/media/v4l-drivers.rst
@@ -27,6 +27,7 @@ Video4Linux (V4L) driver-specific documentation
si470x
si4713
si476x
+ starfive_camss
vimc
visl
vivid
diff --git a/MAINTAINERS b/MAINTAINERS
index 8fd44a3e0b8f..60945bf4b381 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20268,6 +20268,7 @@ M: Jack Zhu <jack.zhu@starfivetech.com>
M: Changhuang Liang <changhuang.liang@starfivetech.com>
L: linux-media@vger.kernel.org
S: Maintained
+F: Documentation/admin-guide/media/starfive_camss.rst
F: Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
STARFIVE CRYPTO DRIVER
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v9 3/8] media: staging: media: starfive: camss: Add core driver
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
2023-09-14 3:16 ` [PATCH v9 1/8] media: dt-bindings: Add JH7110 Camera Subsystem Jack Zhu
2023-09-14 3:16 ` [PATCH v9 2/8] media: admin-guide: Add starfive_camss.rst for Starfive " Jack Zhu
@ 2023-09-14 3:16 ` Jack Zhu
2023-09-14 3:16 ` [PATCH v9 4/8] media: staging: media: starfive: camss: Add video driver Jack Zhu
` (5 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Jack Zhu @ 2023-09-14 3:16 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Robert Foss, Todor Tomov, bryan.odonoghue,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart, Hans Verkuil
Cc: linux-media, linux-kernel, devicetree, linux-staging, jack.zhu,
changhuang.liang
Add core driver for StarFive Camera Subsystem. The code parses
the device platform resources and registers related devices.
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
MAINTAINERS | 1 +
drivers/staging/media/Kconfig | 2 +
drivers/staging/media/Makefile | 1 +
drivers/staging/media/starfive/Kconfig | 5 +
drivers/staging/media/starfive/Makefile | 2 +
drivers/staging/media/starfive/camss/Kconfig | 17 +
drivers/staging/media/starfive/camss/Makefile | 9 +
.../staging/media/starfive/camss/stf-camss.c | 320 ++++++++++++++++++
.../staging/media/starfive/camss/stf-camss.h | 129 +++++++
9 files changed, 486 insertions(+)
create mode 100644 drivers/staging/media/starfive/Kconfig
create mode 100644 drivers/staging/media/starfive/Makefile
create mode 100644 drivers/staging/media/starfive/camss/Kconfig
create mode 100644 drivers/staging/media/starfive/camss/Makefile
create mode 100644 drivers/staging/media/starfive/camss/stf-camss.c
create mode 100644 drivers/staging/media/starfive/camss/stf-camss.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 60945bf4b381..e6feb7fd3f2a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20270,6 +20270,7 @@ L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/admin-guide/media/starfive_camss.rst
F: Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
+F: drivers/staging/media/starfive/camss
STARFIVE CRYPTO DRIVER
M: Jia Jie Ho <jiajie.ho@starfivetech.com>
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index bc6c7b248f86..554c2e475ce3 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -36,6 +36,8 @@ source "drivers/staging/media/omap4iss/Kconfig"
source "drivers/staging/media/rkvdec/Kconfig"
+source "drivers/staging/media/starfive/Kconfig"
+
source "drivers/staging/media/sunxi/Kconfig"
source "drivers/staging/media/tegra-video/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 1a4c3a062e3d..dcaeeca0ee6d 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_VIDEO_MAX96712) += max96712/
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/
obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/
+obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/
obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/
obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/
diff --git a/drivers/staging/media/starfive/Kconfig b/drivers/staging/media/starfive/Kconfig
new file mode 100644
index 000000000000..34727cf56072
--- /dev/null
+++ b/drivers/staging/media/starfive/Kconfig
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+comment "StarFive media platform drivers"
+
+source "drivers/staging/media/starfive/camss/Kconfig"
diff --git a/drivers/staging/media/starfive/Makefile b/drivers/staging/media/starfive/Makefile
new file mode 100644
index 000000000000..4639fa1bca32
--- /dev/null
+++ b/drivers/staging/media/starfive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += camss/
diff --git a/drivers/staging/media/starfive/camss/Kconfig b/drivers/staging/media/starfive/camss/Kconfig
new file mode 100644
index 000000000000..bd184f42c98f
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config VIDEO_STARFIVE_CAMSS
+ tristate "Starfive Camera Subsystem driver"
+ depends on V4L_PLATFORM_DRIVERS
+ depends on VIDEO_DEV && OF
+ depends on HAS_DMA
+ depends on PM
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
+ select VIDEOBUF2_DMA_CONTIG
+ select V4L2_FWNODE
+ help
+ Enable this to support for the Starfive Camera subsystem
+ found on Starfive JH7110 SoC.
+
+ To compile this driver as a module, choose M here: the
+ module will be called starfive-camss.
diff --git a/drivers/staging/media/starfive/camss/Makefile b/drivers/staging/media/starfive/camss/Makefile
new file mode 100644
index 000000000000..78211e30550f
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for StarFive Camera Subsystem driver
+#
+
+starfive-camss-objs += \
+ stf-camss.o
+
+obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o
diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c
new file mode 100644
index 000000000000..f083bc0e6e97
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-camss.c
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * stf_camss.c
+ *
+ * Starfive Camera Subsystem driver
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ *
+ * Author: Jack Zhu <jack.zhu@starfivetech.com>
+ * Author: Changhuang Liang <changhuang.liang@starfivetech.com>
+ *
+ */
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+
+#include "stf-camss.h"
+
+static const char * const stfcamss_clocks[] = {
+ "clk_wrapper_clk_c",
+ "clk_ispcore_2x",
+ "clk_isp_axi",
+};
+
+static const char * const stfcamss_resets[] = {
+ "rst_wrapper_p",
+ "rst_wrapper_c",
+ "rst_axiwr",
+ "rst_isp_top_n",
+ "rst_isp_top_axi",
+};
+
+static int stfcamss_get_mem_res(struct stfcamss *stfcamss)
+{
+ struct platform_device *pdev = to_platform_device(stfcamss->dev);
+
+ stfcamss->syscon_base =
+ devm_platform_ioremap_resource_byname(pdev, "syscon");
+ if (IS_ERR(stfcamss->syscon_base))
+ return PTR_ERR(stfcamss->syscon_base);
+
+ stfcamss->isp_base = devm_platform_ioremap_resource_byname(pdev, "isp");
+ if (IS_ERR(stfcamss->isp_base))
+ return PTR_ERR(stfcamss->isp_base);
+
+ return 0;
+}
+
+/*
+ * stfcamss_of_parse_endpoint_node - Parse port endpoint node
+ * @dev: Device
+ * @node: Device node to be parsed
+ * @csd: Parsed data from port endpoint node
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+static int stfcamss_of_parse_endpoint_node(struct stfcamss *stfcamss,
+ struct device_node *node,
+ struct stfcamss_async_subdev *csd)
+{
+ struct v4l2_fwnode_endpoint vep = { { 0 } };
+ int ret;
+
+ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep);
+ if (ret) {
+ dev_err(stfcamss->dev, "endpoint not defined at %pOF\n", node);
+ return ret;
+ }
+
+ csd->port = vep.base.port;
+
+ return 0;
+}
+
+/*
+ * stfcamss_of_parse_ports - Parse ports node
+ * @stfcamss: STFCAMSS device
+ *
+ * Return number of "port" nodes found in "ports" node
+ */
+static int stfcamss_of_parse_ports(struct stfcamss *stfcamss)
+{
+ struct device_node *node = NULL;
+ int ret, num_subdevs = 0;
+
+ for_each_endpoint_of_node(stfcamss->dev->of_node, node) {
+ struct stfcamss_async_subdev *csd;
+
+ if (!of_device_is_available(node))
+ continue;
+
+ csd = v4l2_async_nf_add_fwnode_remote(&stfcamss->notifier,
+ of_fwnode_handle(node),
+ struct stfcamss_async_subdev);
+ if (IS_ERR(csd)) {
+ ret = PTR_ERR(csd);
+ dev_err(stfcamss->dev, "failed to add async notifier\n");
+ goto err_cleanup;
+ }
+
+ ret = stfcamss_of_parse_endpoint_node(stfcamss, node, csd);
+ if (ret)
+ goto err_cleanup;
+
+ num_subdevs++;
+ }
+
+ return num_subdevs;
+
+err_cleanup:
+ of_node_put(node);
+ return ret;
+}
+
+static int stfcamss_subdev_notifier_complete(struct v4l2_async_notifier *ntf)
+{
+ struct stfcamss *stfcamss =
+ container_of(ntf, struct stfcamss, notifier);
+
+ return v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
+}
+
+static const struct v4l2_async_notifier_operations
+stfcamss_subdev_notifier_ops = {
+ .complete = stfcamss_subdev_notifier_complete,
+};
+
+static void stfcamss_mc_init(struct platform_device *pdev,
+ struct stfcamss *stfcamss)
+{
+ stfcamss->media_dev.dev = stfcamss->dev;
+ strscpy(stfcamss->media_dev.model, "Starfive Camera Subsystem",
+ sizeof(stfcamss->media_dev.model));
+ media_device_init(&stfcamss->media_dev);
+
+ stfcamss->v4l2_dev.mdev = &stfcamss->media_dev;
+}
+
+/*
+ * stfcamss_probe - Probe STFCAMSS platform device
+ * @pdev: Pointer to STFCAMSS platform device
+ *
+ * Return 0 on success or a negative error code on failure
+ */
+static int stfcamss_probe(struct platform_device *pdev)
+{
+ struct stfcamss *stfcamss;
+ struct device *dev = &pdev->dev;
+ int ret, num_subdevs;
+ unsigned int i;
+
+ stfcamss = devm_kzalloc(dev, sizeof(*stfcamss), GFP_KERNEL);
+ if (!stfcamss)
+ return -ENOMEM;
+
+ stfcamss->dev = dev;
+
+ stfcamss->nclks = ARRAY_SIZE(stfcamss->sys_clk);
+ for (i = 0; i < stfcamss->nclks; ++i)
+ stfcamss->sys_clk[i].id = stfcamss_clocks[i];
+ ret = devm_clk_bulk_get(dev, stfcamss->nclks, stfcamss->sys_clk);
+ if (ret) {
+ dev_err(dev, "Failed to get clk controls\n");
+ return ret;
+ }
+
+ stfcamss->nrsts = ARRAY_SIZE(stfcamss->sys_rst);
+ for (i = 0; i < stfcamss->nrsts; ++i)
+ stfcamss->sys_rst[i].id = stfcamss_resets[i];
+ ret = devm_reset_control_bulk_get_shared(dev, stfcamss->nrsts,
+ stfcamss->sys_rst);
+ if (ret) {
+ dev_err(dev, "Failed to get reset controls\n");
+ return ret;
+ }
+
+ ret = stfcamss_get_mem_res(stfcamss);
+ if (ret) {
+ dev_err(dev, "Could not map registers\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, stfcamss);
+
+ v4l2_async_nf_init(&stfcamss->notifier, &stfcamss->v4l2_dev);
+
+ num_subdevs = stfcamss_of_parse_ports(stfcamss);
+ if (num_subdevs < 0) {
+ ret = -ENODEV;
+ dev_err(dev, "Failed to get sub devices: %d\n", ret);
+ goto err_cleanup_notifier;
+ }
+
+ stfcamss_mc_init(pdev, stfcamss);
+
+ ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev);
+ if (ret < 0) {
+ dev_err(dev, "Failed to register V4L2 device: %d\n", ret);
+ goto err_cleanup_media_device;
+ }
+
+ ret = media_device_register(&stfcamss->media_dev);
+ if (ret) {
+ dev_err(dev, "Failed to register media device: %d\n", ret);
+ goto err_unregister_device;
+ }
+
+ pm_runtime_enable(dev);
+
+ stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
+ ret = v4l2_async_nf_register(&stfcamss->notifier);
+ if (ret) {
+ dev_err(dev, "Failed to register async subdev nodes: %d\n",
+ ret);
+ pm_runtime_disable(dev);
+ goto err_unregister_media_dev;
+ }
+
+ return 0;
+
+err_unregister_media_dev:
+ media_device_unregister(&stfcamss->media_dev);
+err_unregister_device:
+ v4l2_device_unregister(&stfcamss->v4l2_dev);
+err_cleanup_media_device:
+ media_device_cleanup(&stfcamss->media_dev);
+err_cleanup_notifier:
+ v4l2_async_nf_cleanup(&stfcamss->notifier);
+ return ret;
+}
+
+/*
+ * stfcamss_remove - Remove STFCAMSS platform device
+ * @pdev: Pointer to STFCAMSS platform device
+ *
+ * Always returns 0.
+ */
+static int stfcamss_remove(struct platform_device *pdev)
+{
+ struct stfcamss *stfcamss = platform_get_drvdata(pdev);
+
+ v4l2_device_unregister(&stfcamss->v4l2_dev);
+ media_device_cleanup(&stfcamss->media_dev);
+ v4l2_async_nf_cleanup(&stfcamss->notifier);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id stfcamss_of_match[] = {
+ { .compatible = "starfive,jh7110-camss" },
+ { /* sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, stfcamss_of_match);
+
+static int __maybe_unused stfcamss_runtime_suspend(struct device *dev)
+{
+ struct stfcamss *stfcamss = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_bulk_assert(stfcamss->nrsts, stfcamss->sys_rst);
+ if (ret) {
+ dev_err(dev, "reset assert failed\n");
+ return ret;
+ }
+
+ clk_bulk_disable_unprepare(stfcamss->nclks, stfcamss->sys_clk);
+
+ return 0;
+}
+
+static int __maybe_unused stfcamss_runtime_resume(struct device *dev)
+{
+ struct stfcamss *stfcamss = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_bulk_prepare_enable(stfcamss->nclks, stfcamss->sys_clk);
+ if (ret) {
+ dev_err(dev, "clock prepare enable failed\n");
+ return ret;
+ }
+
+ ret = reset_control_bulk_deassert(stfcamss->nrsts, stfcamss->sys_rst);
+ if (ret < 0) {
+ dev_err(dev, "cannot deassert resets\n");
+ clk_bulk_disable_unprepare(stfcamss->nclks, stfcamss->sys_clk);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops stfcamss_pm_ops = {
+ SET_RUNTIME_PM_OPS(stfcamss_runtime_suspend,
+ stfcamss_runtime_resume,
+ NULL)
+};
+
+static struct platform_driver stfcamss_driver = {
+ .probe = stfcamss_probe,
+ .remove = stfcamss_remove,
+ .driver = {
+ .name = "starfive-camss",
+ .pm = &stfcamss_pm_ops,
+ .of_match_table = stfcamss_of_match,
+ },
+};
+
+module_platform_driver(stfcamss_driver);
+
+MODULE_AUTHOR("Jack Zhu <jack.zhu@starfivetech.com>");
+MODULE_AUTHOR("Changhuang Liang <changhuang.liang@starfivetech.com>");
+MODULE_DESCRIPTION("StarFive Camera Subsystem driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/starfive/camss/stf-camss.h b/drivers/staging/media/starfive/camss/stf-camss.h
new file mode 100644
index 000000000000..47d715122155
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-camss.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * stf_camss.h
+ *
+ * Starfive Camera Subsystem driver
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#ifndef STF_CAMSS_H
+#define STF_CAMSS_H
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/reset.h>
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-device.h>
+
+enum stf_port_num {
+ STF_PORT_DVP = 0,
+ STF_PORT_CSI2RX
+};
+
+enum stf_clk {
+ STF_CLK_WRAPPER_CLK_C = 0,
+ STF_CLK_ISPCORE_2X,
+ STF_CLK_ISP_AXI,
+ STF_CLK_NUM
+};
+
+enum stf_rst {
+ STF_RST_WRAPPER_P = 0,
+ STF_RST_WRAPPER_C,
+ STF_RST_AXIWR,
+ STF_RST_ISP_TOP_N,
+ STF_RST_ISP_TOP_AXI,
+ STF_RST_NUM
+};
+
+struct stf_isr_data {
+ const char *name;
+ irqreturn_t (*isr)(int irq, void *priv);
+};
+
+struct stfcamss {
+ struct v4l2_device v4l2_dev;
+ struct media_device media_dev;
+ struct media_pipeline pipe;
+ struct device *dev;
+ struct v4l2_async_notifier notifier;
+ void __iomem *syscon_base;
+ void __iomem *isp_base;
+ struct clk_bulk_data sys_clk[STF_CLK_NUM];
+ int nclks;
+ struct reset_control_bulk_data sys_rst[STF_RST_NUM];
+ int nrsts;
+};
+
+struct stfcamss_async_subdev {
+ struct v4l2_async_connection asd; /* must be first */
+ enum stf_port_num port;
+};
+
+static inline u32 stf_isp_reg_read(struct stfcamss *stfcamss, u32 reg)
+{
+ return ioread32(stfcamss->isp_base + reg);
+}
+
+static inline void stf_isp_reg_write(struct stfcamss *stfcamss,
+ u32 reg, u32 val)
+{
+ iowrite32(val, stfcamss->isp_base + reg);
+}
+
+static inline void stf_isp_reg_write_delay(struct stfcamss *stfcamss,
+ u32 reg, u32 val, u32 delay)
+{
+ iowrite32(val, stfcamss->isp_base + reg);
+ usleep_range(1000 * delay, 1000 * delay + 100);
+}
+
+static inline void stf_isp_reg_set_bit(struct stfcamss *stfcamss,
+ u32 reg, u32 mask, u32 val)
+{
+ u32 value;
+
+ value = ioread32(stfcamss->isp_base + reg) & ~mask;
+ val &= mask;
+ val |= value;
+ iowrite32(val, stfcamss->isp_base + reg);
+}
+
+static inline void stf_isp_reg_set(struct stfcamss *stfcamss, u32 reg, u32 mask)
+{
+ iowrite32(ioread32(stfcamss->isp_base + reg) | mask,
+ stfcamss->isp_base + reg);
+}
+
+static inline u32 stf_syscon_reg_read(struct stfcamss *stfcamss, u32 reg)
+{
+ return ioread32(stfcamss->syscon_base + reg);
+}
+
+static inline void stf_syscon_reg_write(struct stfcamss *stfcamss,
+ u32 reg, u32 val)
+{
+ iowrite32(val, stfcamss->syscon_base + reg);
+}
+
+static inline void stf_syscon_reg_set_bit(struct stfcamss *stfcamss,
+ u32 reg, u32 bit_mask)
+{
+ u32 value;
+
+ value = ioread32(stfcamss->syscon_base + reg);
+ iowrite32(value | bit_mask, stfcamss->syscon_base + reg);
+}
+
+static inline void stf_syscon_reg_clear_bit(struct stfcamss *stfcamss,
+ u32 reg, u32 bit_mask)
+{
+ u32 value;
+
+ value = ioread32(stfcamss->syscon_base + reg);
+ iowrite32(value & ~bit_mask, stfcamss->syscon_base + reg);
+}
+#endif /* STF_CAMSS_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v9 4/8] media: staging: media: starfive: camss: Add video driver
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
` (2 preceding siblings ...)
2023-09-14 3:16 ` [PATCH v9 3/8] media: staging: media: starfive: camss: Add core driver Jack Zhu
@ 2023-09-14 3:16 ` Jack Zhu
2023-09-14 3:16 ` [PATCH v9 5/8] media: staging: media: starfive: camss: Add ISP driver Jack Zhu
` (4 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Jack Zhu @ 2023-09-14 3:16 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Robert Foss, Todor Tomov, bryan.odonoghue,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart, Hans Verkuil
Cc: linux-media, linux-kernel, devicetree, linux-staging, jack.zhu,
changhuang.liang
Add video driver for StarFive Camera Subsystem.
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
drivers/staging/media/starfive/camss/Makefile | 3 +-
.../staging/media/starfive/camss/stf-video.c | 571 ++++++++++++++++++
.../staging/media/starfive/camss/stf-video.h | 100 +++
3 files changed, 673 insertions(+), 1 deletion(-)
create mode 100644 drivers/staging/media/starfive/camss/stf-video.c
create mode 100644 drivers/staging/media/starfive/camss/stf-video.h
diff --git a/drivers/staging/media/starfive/camss/Makefile b/drivers/staging/media/starfive/camss/Makefile
index 78211e30550f..7d320b9317c8 100644
--- a/drivers/staging/media/starfive/camss/Makefile
+++ b/drivers/staging/media/starfive/camss/Makefile
@@ -4,6 +4,7 @@
#
starfive-camss-objs += \
- stf-camss.o
+ stf-camss.o \
+ stf-video.o
obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o
diff --git a/drivers/staging/media/starfive/camss/stf-video.c b/drivers/staging/media/starfive/camss/stf-video.c
new file mode 100644
index 000000000000..bb21aa04482b
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-video.c
@@ -0,0 +1,571 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * stf_video.c
+ *
+ * StarFive Camera Subsystem - V4L2 device node
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#include <linux/pm_runtime.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mc.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "stf-camss.h"
+#include "stf-video.h"
+
+/* -----------------------------------------------------------------------------
+ * Helper functions
+ */
+
+static inline struct stfcamss_buffer *
+to_stfcamss_buffer(struct vb2_v4l2_buffer *vbuf)
+{
+ return container_of(vbuf, struct stfcamss_buffer, vb);
+}
+
+static const struct stfcamss_format_info *
+video_g_fi_by_index(struct stfcamss_video *video, int index)
+{
+ if (index >= video->nformats)
+ return NULL;
+
+ return &video->formats[index];
+}
+
+static const struct stfcamss_format_info *
+video_g_fi_by_mcode(struct stfcamss_video *video, u32 mcode)
+{
+ unsigned int i;
+
+ for (i = 0; i < video->nformats; i++) {
+ if (video->formats[i].code == mcode)
+ return &video->formats[i];
+ }
+
+ return NULL;
+}
+
+static const struct stfcamss_format_info *
+video_g_fi_by_pfmt(struct stfcamss_video *video, u32 pixelformat)
+{
+ unsigned int i;
+
+ for (i = 0; i < video->nformats; i++) {
+ if (video->formats[i].pixelformat == pixelformat)
+ return &video->formats[i];
+ }
+
+ return NULL;
+}
+
+static int __video_try_fmt(struct stfcamss_video *video, struct v4l2_format *f)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ const struct stfcamss_format_info *fi;
+ u32 width, height;
+ u32 bpl;
+ unsigned int i;
+
+ fi = video_g_fi_by_pfmt(video, pix->pixelformat);
+ if (!fi)
+ fi = &video->formats[0]; /* default format */
+
+ width = pix->width;
+ height = pix->height;
+
+ memset(pix, 0, sizeof(*pix));
+
+ pix->pixelformat = fi->pixelformat;
+ pix->width = clamp_t(u32, width, STFCAMSS_FRAME_MIN_WIDTH,
+ STFCAMSS_FRAME_MAX_WIDTH);
+ pix->height = clamp_t(u32, height, STFCAMSS_FRAME_MIN_HEIGHT,
+ STFCAMSS_FRAME_MAX_HEIGHT);
+ bpl = pix->width * fi->bpp / 8;
+ bpl = ALIGN(bpl, video->bpl_alignment);
+ pix->bytesperline = bpl;
+
+ for (i = 0; i < fi->planes; ++i)
+ pix->sizeimage += bpl * pix->height / fi->vsub[i];
+
+ pix->field = V4L2_FIELD_NONE;
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ pix->flags = 0;
+ pix->ycbcr_enc =
+ V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
+ pix->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
+ pix->colorspace,
+ pix->ycbcr_enc);
+ pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
+
+ return 0;
+}
+
+static int stf_video_init_format(struct stfcamss_video *video)
+{
+ int ret;
+ struct v4l2_format format = {
+ .type = video->type,
+ .fmt.pix = {
+ .width = 1920,
+ .height = 1080,
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ },
+ };
+
+ ret = __video_try_fmt(video, &format);
+
+ if (ret < 0)
+ return ret;
+
+ video->active_fmt = format;
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Video queue operations
+ */
+
+static int video_queue_setup(struct vb2_queue *q,
+ unsigned int *num_buffers,
+ unsigned int *num_planes,
+ unsigned int sizes[],
+ struct device *alloc_devs[])
+{
+ struct stfcamss_video *video = vb2_get_drv_priv(q);
+ const struct v4l2_pix_format *format = &video->active_fmt.fmt.pix;
+
+ if (*num_planes) {
+ if (*num_planes != 1)
+ return -EINVAL;
+
+ if (sizes[0] < format->sizeimage)
+ return -EINVAL;
+ }
+
+ *num_planes = 1;
+ sizes[0] = format->sizeimage;
+ if (!sizes[0]) {
+ dev_dbg(video->stfcamss->dev,
+ "%s: error size is zero.\n", __func__);
+ return -EINVAL;
+ }
+
+ dev_dbg(video->stfcamss->dev, "planes = %d, size = %d\n",
+ *num_planes, sizes[0]);
+
+ return 0;
+}
+
+static int video_buf_init(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
+ struct stfcamss_buffer *buffer = to_stfcamss_buffer(vbuf);
+ const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix;
+ dma_addr_t *paddr;
+
+ paddr = vb2_plane_cookie(vb, 0);
+ buffer->addr[0] = *paddr;
+
+ if (fmt->pixelformat == V4L2_PIX_FMT_NV12)
+ buffer->addr[1] =
+ buffer->addr[0] + fmt->bytesperline * fmt->height;
+
+ return 0;
+}
+
+static int video_buf_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
+ const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix;
+
+ if (fmt->sizeimage > vb2_plane_size(vb, 0)) {
+ dev_dbg(video->stfcamss->dev,
+ "sizeimage = %u, plane size = %u\n",
+ fmt->sizeimage, (unsigned int)vb2_plane_size(vb, 0));
+ return -EINVAL;
+ }
+ vb2_set_plane_payload(vb, 0, fmt->sizeimage);
+
+ vbuf->field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+static void video_buf_queue(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
+ struct stfcamss_buffer *buffer = to_stfcamss_buffer(vbuf);
+
+ video->ops->queue_buffer(video, buffer);
+}
+
+static int video_get_subdev_format(struct stfcamss_video *video,
+ struct v4l2_subdev_format *fmt)
+{
+ struct v4l2_subdev *subdev;
+ struct media_pad *pad;
+ struct media_entity *entity;
+ int ret;
+
+ entity = &video->vdev.entity;
+ while (1) {
+ pad = &entity->pads[0];
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ break;
+
+ pad = media_pad_remote_pad_first(pad);
+ if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+ break;
+
+ entity = pad->entity;
+ subdev = media_entity_to_v4l2_subdev(entity);
+
+ fmt->pad = pad->index;
+
+ ret = v4l2_subdev_call_state_active(subdev, pad, get_fmt, fmt);
+ if (ret < 0 && ret != -ENOIOCTLCMD)
+ return ret;
+ else if (!ret)
+ break;
+ }
+
+ return 0;
+}
+
+static int stf_video_check_format(struct stfcamss_video *video)
+{
+ struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix;
+ const struct stfcamss_format_info *fi;
+ int ret;
+ struct v4l2_subdev_format sd_fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+
+ ret = video_get_subdev_format(video, &sd_fmt);
+ if (ret < 0)
+ return ret;
+
+ fi = video_g_fi_by_mcode(video, sd_fmt.format.code);
+ if (!fi)
+ return -EINVAL;
+
+ if (pix->pixelformat != fi->pixelformat ||
+ pix->height != sd_fmt.format.height ||
+ pix->width != sd_fmt.format.width ||
+ pix->field != sd_fmt.format.field)
+ return -EPIPE;
+
+ return 0;
+}
+
+static int video_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct stfcamss_video *video = vb2_get_drv_priv(q);
+ struct video_device *vdev = &video->vdev;
+ int ret;
+
+ ret = video_device_pipeline_start(vdev, &video->stfcamss->pipe);
+ if (ret < 0) {
+ dev_err(video->stfcamss->dev,
+ "Failed to media_pipeline_start: %d\n", ret);
+ goto err_ret_buffers;
+ }
+
+ ret = pm_runtime_resume_and_get(video->stfcamss->dev);
+ if (ret < 0) {
+ dev_err(video->stfcamss->dev, "power up failed %d\n", ret);
+ goto err_pipeline_stop;
+ }
+
+ video->ops->start_streaming(video);
+
+ ret = v4l2_subdev_call(video->source_subdev, video, s_stream, true);
+ if (ret) {
+ dev_err(video->stfcamss->dev, "stream on failed\n");
+ goto err_pm_put;
+ }
+
+ return 0;
+
+err_pm_put:
+ pm_runtime_put(video->stfcamss->dev);
+err_pipeline_stop:
+ video_device_pipeline_stop(vdev);
+err_ret_buffers:
+ video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
+ return ret;
+}
+
+static void video_stop_streaming(struct vb2_queue *q)
+{
+ struct stfcamss_video *video = vb2_get_drv_priv(q);
+ struct video_device *vdev = &video->vdev;
+
+ video->ops->stop_streaming(video);
+
+ v4l2_subdev_call(video->source_subdev, video, s_stream, false);
+
+ pm_runtime_put(video->stfcamss->dev);
+
+ video_device_pipeline_stop(vdev);
+ video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
+}
+
+static const struct vb2_ops stf_video_vb2_q_ops = {
+ .queue_setup = video_queue_setup,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .buf_init = video_buf_init,
+ .buf_prepare = video_buf_prepare,
+ .buf_queue = video_buf_queue,
+ .start_streaming = video_start_streaming,
+ .stop_streaming = video_stop_streaming,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 ioctls
+ */
+
+static int video_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ strscpy(cap->driver, "stf camss", sizeof(cap->driver));
+ strscpy(cap->card, "Starfive Camera Subsystem", sizeof(cap->card));
+
+ return 0;
+}
+
+static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+ struct stfcamss_video *video = video_drvdata(file);
+ const struct stfcamss_format_info *fi;
+
+ if (f->index >= video->nformats)
+ return -EINVAL;
+
+ if (f->mbus_code) {
+ /* Each entry in formats[] table has unique mbus_code */
+ if (f->index > 0)
+ return -EINVAL;
+
+ fi = video_g_fi_by_mcode(video, f->mbus_code);
+ } else {
+ fi = video_g_fi_by_index(video, f->index);
+ }
+
+ if (!fi)
+ return -EINVAL;
+
+ f->pixelformat = fi->pixelformat;
+
+ return 0;
+}
+
+static int video_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct stfcamss_video *video = video_drvdata(file);
+ unsigned int i;
+
+ if (fsize->index)
+ return -EINVAL;
+
+ for (i = 0; i < video->nformats; i++) {
+ if (video->formats[i].pixelformat == fsize->pixel_format)
+ break;
+ }
+
+ if (i == video->nformats)
+ return -EINVAL;
+
+ fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+ fsize->stepwise.min_width = STFCAMSS_FRAME_MIN_WIDTH;
+ fsize->stepwise.max_width = STFCAMSS_FRAME_MAX_WIDTH;
+ fsize->stepwise.min_height = STFCAMSS_FRAME_MIN_HEIGHT;
+ fsize->stepwise.max_height = STFCAMSS_FRAME_MAX_HEIGHT;
+ fsize->stepwise.step_width = 1;
+ fsize->stepwise.step_height = 1;
+
+ return 0;
+}
+
+static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct stfcamss_video *video = video_drvdata(file);
+
+ *f = video->active_fmt;
+
+ return 0;
+}
+
+static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct stfcamss_video *video = video_drvdata(file);
+ int ret;
+
+ if (vb2_is_busy(&video->vb2_q))
+ return -EBUSY;
+
+ ret = __video_try_fmt(video, f);
+ if (ret < 0)
+ return ret;
+
+ video->active_fmt = *f;
+
+ return 0;
+}
+
+static int video_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct stfcamss_video *video = video_drvdata(file);
+
+ return __video_try_fmt(video, f);
+}
+
+static const struct v4l2_ioctl_ops stf_vid_ioctl_ops = {
+ .vidioc_querycap = video_querycap,
+ .vidioc_enum_fmt_vid_cap = video_enum_fmt,
+ .vidioc_enum_framesizes = video_enum_framesizes,
+ .vidioc_g_fmt_vid_cap = video_g_fmt,
+ .vidioc_s_fmt_vid_cap = video_s_fmt,
+ .vidioc_try_fmt_vid_cap = video_try_fmt,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 file operations
+ */
+
+static const struct v4l2_file_operations stf_vid_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = video_ioctl2,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+ .read = vb2_fop_read,
+};
+
+/* -----------------------------------------------------------------------------
+ * STFCAMSS video core
+ */
+
+static int stf_link_validate(struct media_link *link)
+{
+ struct video_device *vdev =
+ media_entity_to_video_device(link->sink->entity);
+ struct stfcamss_video *video = video_get_drvdata(vdev);
+ int ret;
+
+ ret = stf_video_check_format(video);
+
+ return ret;
+}
+
+static const struct media_entity_operations stf_media_ops = {
+ .link_validate = stf_link_validate,
+};
+
+static void stf_video_release(struct video_device *vdev)
+{
+ struct stfcamss_video *video = video_get_drvdata(vdev);
+
+ media_entity_cleanup(&vdev->entity);
+
+ mutex_destroy(&video->q_lock);
+ mutex_destroy(&video->lock);
+}
+
+int stf_video_register(struct stfcamss_video *video,
+ struct v4l2_device *v4l2_dev, const char *name)
+{
+ struct video_device *vdev = &video->vdev;
+ struct vb2_queue *q;
+ struct media_pad *pad = &video->pad;
+ int ret;
+
+ mutex_init(&video->q_lock);
+ mutex_init(&video->lock);
+
+ q = &video->vb2_q;
+ q->drv_priv = video;
+ q->mem_ops = &vb2_dma_contig_memops;
+ q->ops = &stf_video_vb2_q_ops;
+ q->type = video->type;
+ q->io_modes = VB2_DMABUF | VB2_MMAP;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->buf_struct_size = sizeof(struct stfcamss_buffer);
+ q->dev = video->stfcamss->dev;
+ q->lock = &video->q_lock;
+ q->min_buffers_needed = STFCAMSS_MIN_BUFFERS;
+ ret = vb2_queue_init(q);
+ if (ret < 0) {
+ dev_err(video->stfcamss->dev,
+ "Failed to init vb2 queue: %d\n", ret);
+ goto err_mutex_destroy;
+ }
+
+ pad->flags = MEDIA_PAD_FL_SINK;
+ ret = media_entity_pads_init(&vdev->entity, 1, pad);
+ if (ret < 0) {
+ dev_err(video->stfcamss->dev,
+ "Failed to init video entity: %d\n", ret);
+ goto err_mutex_destroy;
+ }
+
+ ret = stf_video_init_format(video);
+ if (ret < 0) {
+ dev_err(video->stfcamss->dev,
+ "Failed to init format: %d\n", ret);
+ goto err_media_cleanup;
+ }
+
+ vdev->fops = &stf_vid_fops;
+ vdev->ioctl_ops = &stf_vid_ioctl_ops;
+ vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ vdev->entity.ops = &stf_media_ops;
+ vdev->vfl_dir = VFL_DIR_RX;
+ vdev->release = stf_video_release;
+ vdev->v4l2_dev = v4l2_dev;
+ vdev->queue = &video->vb2_q;
+ vdev->lock = &video->lock;
+ strscpy(vdev->name, name, sizeof(vdev->name));
+
+ video_set_drvdata(vdev, video);
+
+ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+ if (ret < 0) {
+ dev_err(video->stfcamss->dev,
+ "Failed to register video device: %d\n", ret);
+ goto err_media_cleanup;
+ }
+
+ return 0;
+
+err_media_cleanup:
+ media_entity_cleanup(&vdev->entity);
+err_mutex_destroy:
+ mutex_destroy(&video->lock);
+ mutex_destroy(&video->q_lock);
+ return ret;
+}
+
+void stf_video_unregister(struct stfcamss_video *video)
+{
+ vb2_video_unregister_device(&video->vdev);
+}
diff --git a/drivers/staging/media/starfive/camss/stf-video.h b/drivers/staging/media/starfive/camss/stf-video.h
new file mode 100644
index 000000000000..8052b77e3ad8
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-video.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * stf_video.h
+ *
+ * StarFive Camera Subsystem - V4L2 device node
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#ifndef STF_VIDEO_H
+#define STF_VIDEO_H
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-v4l2.h>
+
+#define STFCAMSS_FRAME_MIN_WIDTH 64
+#define STFCAMSS_FRAME_MAX_WIDTH 1920
+#define STFCAMSS_FRAME_MIN_HEIGHT 64
+#define STFCAMSS_FRAME_MAX_HEIGHT 1080
+#define STFCAMSS_FRAME_WIDTH_ALIGN_8 8
+#define STFCAMSS_FRAME_WIDTH_ALIGN_128 128
+#define STFCAMSS_MIN_BUFFERS 2
+
+#define STFCAMSS_MAX_ENTITY_NAME_LEN 27
+
+enum stf_v_line_id {
+ STF_V_LINE_WR = 0,
+ STF_V_LINE_ISP,
+ STF_V_LINE_MAX,
+};
+
+enum stf_capture_type {
+ STF_CAPTURE_RAW = 0,
+ STF_CAPTURE_YUV,
+ STF_CAPTURE_NUM,
+};
+
+struct stfcamss_buffer {
+ struct vb2_v4l2_buffer vb;
+ dma_addr_t addr[2];
+ struct list_head queue;
+};
+
+struct fract {
+ u8 numerator;
+ u8 denominator;
+};
+
+/*
+ * struct stfcamss_format_info - ISP media bus format information
+ * @code: V4L2 media bus format code
+ * @pixelformat: V4L2 pixel format FCC identifier
+ * @planes: Number of planes
+ * @vsub: Vertical subsampling (for each plane)
+ * @bpp: Bits per pixel when stored in memory (for each plane)
+ */
+struct stfcamss_format_info {
+ u32 code;
+ u32 pixelformat;
+ u8 planes;
+ u8 vsub[3];
+ u8 bpp;
+};
+
+struct stfcamss_video {
+ struct stfcamss *stfcamss;
+ struct vb2_queue vb2_q;
+ struct video_device vdev;
+ struct media_pad pad;
+ struct v4l2_format active_fmt;
+ enum v4l2_buf_type type;
+ const struct stfcamss_video_ops *ops;
+ struct mutex lock; /* serialize device access */
+ struct mutex q_lock; /* protects the queue */
+ unsigned int bpl_alignment;
+ const struct stfcamss_format_info *formats;
+ unsigned int nformats;
+ struct v4l2_subdev *source_subdev;
+};
+
+struct stfcamss_video_ops {
+ int (*queue_buffer)(struct stfcamss_video *video,
+ struct stfcamss_buffer *buf);
+ int (*flush_buffers)(struct stfcamss_video *video,
+ enum vb2_buffer_state state);
+ void (*start_streaming)(struct stfcamss_video *video);
+ void (*stop_streaming)(struct stfcamss_video *video);
+};
+
+int stf_video_register(struct stfcamss_video *video,
+ struct v4l2_device *v4l2_dev, const char *name);
+
+void stf_video_unregister(struct stfcamss_video *video);
+
+#endif /* STF_VIDEO_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v9 5/8] media: staging: media: starfive: camss: Add ISP driver
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
` (3 preceding siblings ...)
2023-09-14 3:16 ` [PATCH v9 4/8] media: staging: media: starfive: camss: Add video driver Jack Zhu
@ 2023-09-14 3:16 ` Jack Zhu
2023-09-14 3:16 ` [PATCH v9 6/8] media: staging: media: starfive: camss: Add capture driver Jack Zhu
` (3 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Jack Zhu @ 2023-09-14 3:16 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Robert Foss, Todor Tomov, bryan.odonoghue,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart, Hans Verkuil
Cc: linux-media, linux-kernel, devicetree, linux-staging, jack.zhu,
changhuang.liang
Add ISP driver for StarFive Camera Subsystem.
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
drivers/staging/media/starfive/camss/Makefile | 2 +
.../staging/media/starfive/camss/stf-camss.h | 3 +
.../media/starfive/camss/stf-isp-hw-ops.c | 445 ++++++++++++++++++
.../staging/media/starfive/camss/stf-isp.c | 407 ++++++++++++++++
.../staging/media/starfive/camss/stf-isp.h | 428 +++++++++++++++++
5 files changed, 1285 insertions(+)
create mode 100644 drivers/staging/media/starfive/camss/stf-isp-hw-ops.c
create mode 100644 drivers/staging/media/starfive/camss/stf-isp.c
create mode 100644 drivers/staging/media/starfive/camss/stf-isp.h
diff --git a/drivers/staging/media/starfive/camss/Makefile b/drivers/staging/media/starfive/camss/Makefile
index 7d320b9317c8..97e1522b21ae 100644
--- a/drivers/staging/media/starfive/camss/Makefile
+++ b/drivers/staging/media/starfive/camss/Makefile
@@ -5,6 +5,8 @@
starfive-camss-objs += \
stf-camss.o \
+ stf-isp.o \
+ stf-isp-hw-ops.o \
stf-video.o
obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o
diff --git a/drivers/staging/media/starfive/camss/stf-camss.h b/drivers/staging/media/starfive/camss/stf-camss.h
index 47d715122155..c7b0a34cd29b 100644
--- a/drivers/staging/media/starfive/camss/stf-camss.h
+++ b/drivers/staging/media/starfive/camss/stf-camss.h
@@ -18,6 +18,8 @@
#include <media/v4l2-async.h>
#include <media/v4l2-device.h>
+#include "stf-isp.h"
+
enum stf_port_num {
STF_PORT_DVP = 0,
STF_PORT_CSI2RX
@@ -49,6 +51,7 @@ struct stfcamss {
struct media_device media_dev;
struct media_pipeline pipe;
struct device *dev;
+ struct stf_isp_dev isp_dev;
struct v4l2_async_notifier notifier;
void __iomem *syscon_base;
void __iomem *isp_base;
diff --git a/drivers/staging/media/starfive/camss/stf-isp-hw-ops.c b/drivers/staging/media/starfive/camss/stf-isp-hw-ops.c
new file mode 100644
index 000000000000..c34631ff9422
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-isp-hw-ops.c
@@ -0,0 +1,445 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * stf_isp_hw_ops.c
+ *
+ * Register interface file for StarFive ISP driver
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ *
+ */
+
+#include "stf-camss.h"
+
+static void stf_isp_config_obc(struct stfcamss *stfcamss)
+{
+ u32 reg_val, reg_add;
+
+ stf_isp_reg_write(stfcamss, ISP_REG_OBC_CFG, OBC_W_H(11) | OBC_W_W(11));
+
+ reg_val = GAIN_D_POINT(0x40) | GAIN_C_POINT(0x40) |
+ GAIN_B_POINT(0x40) | GAIN_A_POINT(0x40);
+ for (reg_add = ISP_REG_OBCG_CFG_0; reg_add <= ISP_REG_OBCG_CFG_3;) {
+ stf_isp_reg_write(stfcamss, reg_add, reg_val);
+ reg_add += 4;
+ }
+
+ reg_val = OFFSET_D_POINT(0) | OFFSET_C_POINT(0) |
+ OFFSET_B_POINT(0) | OFFSET_A_POINT(0);
+ for (reg_add = ISP_REG_OBCO_CFG_0; reg_add <= ISP_REG_OBCO_CFG_3;) {
+ stf_isp_reg_write(stfcamss, reg_add, reg_val);
+ reg_add += 4;
+ }
+}
+
+static void stf_isp_config_oecf(struct stfcamss *stfcamss)
+{
+ u32 reg_add, par_val;
+ u16 par_h, par_l;
+
+ par_h = 0x10; par_l = 0;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_X0_CFG0; reg_add <= ISP_REG_OECF_Y3_CFG0;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 0x20;
+ }
+
+ par_h = 0x40; par_l = 0x20;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_X0_CFG1; reg_add <= ISP_REG_OECF_Y3_CFG1;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 0x20;
+ }
+
+ par_h = 0x80; par_l = 0x60;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_X0_CFG2; reg_add <= ISP_REG_OECF_Y3_CFG2;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 0x20;
+ }
+
+ par_h = 0xc0; par_l = 0xa0;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_X0_CFG3; reg_add <= ISP_REG_OECF_Y3_CFG3;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 0x20;
+ }
+
+ par_h = 0x100; par_l = 0xe0;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_X0_CFG4; reg_add <= ISP_REG_OECF_Y3_CFG4;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 0x20;
+ }
+
+ par_h = 0x200; par_l = 0x180;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_X0_CFG5; reg_add <= ISP_REG_OECF_Y3_CFG5;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 0x20;
+ }
+
+ par_h = 0x300; par_l = 0x280;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_X0_CFG6; reg_add <= ISP_REG_OECF_Y3_CFG6;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 0x20;
+ }
+
+ par_h = 0x3fe; par_l = 0x380;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_X0_CFG7; reg_add <= ISP_REG_OECF_Y3_CFG7;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 0x20;
+ }
+
+ par_h = 0x80; par_l = 0x80;
+ par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
+ for (reg_add = ISP_REG_OECF_S0_CFG0; reg_add <= ISP_REG_OECF_S3_CFG7;) {
+ stf_isp_reg_write(stfcamss, reg_add, par_val);
+ reg_add += 4;
+ }
+}
+
+static void stf_isp_config_lccf(struct stfcamss *stfcamss)
+{
+ u32 reg_add;
+
+ stf_isp_reg_write(stfcamss, ISP_REG_LCCF_CFG_0,
+ Y_DISTANCE(0x21C) | X_DISTANCE(0x3C0));
+ stf_isp_reg_write(stfcamss, ISP_REG_LCCF_CFG_1, LCCF_MAX_DIS(0xb));
+
+ for (reg_add = ISP_REG_LCCF_CFG_2; reg_add <= ISP_REG_LCCF_CFG_5;) {
+ stf_isp_reg_write(stfcamss, reg_add,
+ LCCF_F2_PAR(0x0) | LCCF_F1_PAR(0x0));
+ reg_add += 4;
+ }
+}
+
+static void stf_isp_config_awb(struct stfcamss *stfcamss)
+{
+ u32 reg_val, reg_add;
+ u16 symbol_h, symbol_l;
+
+ symbol_h = 0x0; symbol_l = 0x0;
+ reg_val = AWB_X_SYMBOL_H(symbol_h) | AWB_X_SYMBOL_L(symbol_l);
+
+ for (reg_add = ISP_REG_AWB_X0_CFG_0; reg_add <= ISP_REG_AWB_X3_CFG_1;) {
+ stf_isp_reg_write(stfcamss, reg_add, reg_val);
+ reg_add += 4;
+ }
+
+ symbol_h = 0x0, symbol_l = 0x0;
+ reg_val = AWB_Y_SYMBOL_H(symbol_h) | AWB_Y_SYMBOL_L(symbol_l);
+
+ for (reg_add = ISP_REG_AWB_Y0_CFG_0; reg_add <= ISP_REG_AWB_Y3_CFG_1;) {
+ stf_isp_reg_write(stfcamss, reg_add, reg_val);
+ reg_add += 4;
+ }
+
+ symbol_h = 0x80, symbol_l = 0x80;
+ reg_val = AWB_S_SYMBOL_H(symbol_h) | AWB_S_SYMBOL_L(symbol_l);
+
+ for (reg_add = ISP_REG_AWB_S0_CFG_0; reg_add <= ISP_REG_AWB_S3_CFG_1;) {
+ stf_isp_reg_write(stfcamss, reg_add, reg_val);
+ reg_add += 4;
+ }
+}
+
+static void stf_isp_config_grgb(struct stfcamss *stfcamss)
+{
+ stf_isp_reg_write(stfcamss, ISP_REG_ICTC,
+ GF_MODE(1) | MAXGT(0x140) | MINGT(0x40));
+ stf_isp_reg_write(stfcamss, ISP_REG_IDBC, BADGT(0x200) | BADXT(0x200));
+}
+
+static void stf_isp_config_cfa(struct stfcamss *stfcamss)
+{
+ stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG,
+ SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) | SMY3(2) |
+ SMY2(3) | SMY1(2) | SMY0(3));
+ stf_isp_reg_write(stfcamss, ISP_REG_ICFAM, CROSS_COV(3) | HV_W(2));
+}
+
+static void stf_isp_config_ccm(struct stfcamss *stfcamss)
+{
+ u32 reg_add;
+
+ stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_0, DNRM_F(6) | CCM_M_DAT(0));
+
+ for (reg_add = ISP_REG_ICAMD_12; reg_add <= ISP_REG_ICAMD_20;) {
+ stf_isp_reg_write(stfcamss, reg_add, CCM_M_DAT(0x80));
+ reg_add += 0x10;
+ }
+
+ stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_24, CCM_M_DAT(0x700));
+ stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_25, CCM_M_DAT(0x200));
+}
+
+static void stf_isp_config_gamma(struct stfcamss *stfcamss)
+{
+ u32 reg_val, reg_add;
+ u16 gamma_slope_v, gamma_v;
+
+ gamma_slope_v = 0x2400; gamma_v = 0x0;
+ reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
+ stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL0, reg_val);
+
+ gamma_slope_v = 0x800; gamma_v = 0x20;
+ for (reg_add = ISP_REG_GAMMA_VAL1; reg_add <= ISP_REG_GAMMA_VAL7;) {
+ reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
+ stf_isp_reg_write(stfcamss, reg_add, reg_val);
+ reg_add += 4;
+ gamma_v += 0x20;
+ }
+
+ gamma_v = 0x100;
+ for (reg_add = ISP_REG_GAMMA_VAL8; reg_add <= ISP_REG_GAMMA_VAL13;) {
+ reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
+ stf_isp_reg_write(stfcamss, reg_add, reg_val);
+ reg_add += 4;
+ gamma_v += 0x80;
+ }
+
+ gamma_v = 0x3fe;
+ reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
+ stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL14, reg_val);
+}
+
+static void stf_isp_config_r2y(struct stfcamss *stfcamss)
+{
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_0, 0x4C);
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_1, 0x97);
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_2, 0x1d);
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_3, 0x1d5);
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_4, 0x1ac);
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_5, 0x80);
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_6, 0x80);
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_7, 0x194);
+ stf_isp_reg_write(stfcamss, ISP_REG_R2Y_8, 0x1ec);
+}
+
+static void stf_isp_config_y_curve(struct stfcamss *stfcamss)
+{
+ u32 reg_add;
+ u16 y_curve;
+
+ y_curve = 0x0;
+ for (reg_add = ISP_REG_YCURVE_0; reg_add <= ISP_REG_YCURVE_63;) {
+ stf_isp_reg_write(stfcamss, reg_add, y_curve);
+ reg_add += 4;
+ y_curve += 0x10;
+ }
+}
+
+static void stf_isp_config_sharpen(struct stfcamss *sc)
+{
+ u32 reg_add;
+
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN0, S_DELTA(0x7) | S_WEIGHT(0xf));
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN1, S_DELTA(0x18) | S_WEIGHT(0xf));
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN2, S_DELTA(0x80) | S_WEIGHT(0xf));
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN3, S_DELTA(0x100) | S_WEIGHT(0xf));
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN4, S_DELTA(0x10) | S_WEIGHT(0xf));
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN5, S_DELTA(0x60) | S_WEIGHT(0xf));
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN6, S_DELTA(0x100) | S_WEIGHT(0xf));
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN7, S_DELTA(0x190) | S_WEIGHT(0xf));
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN8, S_DELTA(0x0) | S_WEIGHT(0xf));
+
+ for (reg_add = ISP_REG_SHARPEN9; reg_add <= ISP_REG_SHARPEN14;) {
+ stf_isp_reg_write(sc, reg_add, S_WEIGHT(0xf));
+ reg_add += 4;
+ }
+
+ for (reg_add = ISP_REG_SHARPEN_FS0; reg_add <= ISP_REG_SHARPEN_FS5;) {
+ stf_isp_reg_write(sc, reg_add, S_FACTOR(0x10) | S_SLOPE(0x0));
+ reg_add += 4;
+ }
+
+ stf_isp_reg_write(sc, ISP_REG_SHARPEN_WN,
+ PDIRF(0x8) | NDIRF(0x8) | WSUM(0xd7c));
+ stf_isp_reg_write(sc, ISP_REG_IUVS1, UVDIFF2(0xC0) | UVDIFF1(0x40));
+ stf_isp_reg_write(sc, ISP_REG_IUVS2, UVF(0xff) | UVSLOPE(0x0));
+ stf_isp_reg_write(sc, ISP_REG_IUVCKS1,
+ UVCKDIFF2(0xa0) | UVCKDIFF1(0x40));
+}
+
+static void stf_isp_config_dnyuv(struct stfcamss *stfcamss)
+{
+ u32 reg_val;
+
+ reg_val = YUVSW5(7) | YUVSW4(7) | YUVSW3(7) | YUVSW2(7) |
+ YUVSW1(7) | YUVSW0(7);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR0, reg_val);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR0, reg_val);
+
+ reg_val = YUVSW3(7) | YUVSW2(7) | YUVSW1(7) | YUVSW0(7);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR1, reg_val);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR1, reg_val);
+
+ reg_val = CURVE_D_H(0x60) | CURVE_D_L(0x40);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR0, reg_val);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR0, reg_val);
+
+ reg_val = CURVE_D_H(0xd8) | CURVE_D_L(0x90);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR1, reg_val);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR1, reg_val);
+
+ reg_val = CURVE_D_H(0x1e6) | CURVE_D_L(0x144);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR2, reg_val);
+ stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR2, reg_val);
+}
+
+static void stf_isp_config_sat(struct stfcamss *stfcamss)
+{
+ stf_isp_reg_write(stfcamss, ISP_REG_CS_GAIN, CMAD(0x0) | CMAB(0x100));
+ stf_isp_reg_write(stfcamss, ISP_REG_CS_THRESHOLD, CMD(0x1f) | CMB(0x1));
+ stf_isp_reg_write(stfcamss, ISP_REG_CS_OFFSET, VOFF(0x0) | UOFF(0x0));
+ stf_isp_reg_write(stfcamss, ISP_REG_CS_HUE_F, SIN(0x0) | COS(0x100));
+ stf_isp_reg_write(stfcamss, ISP_REG_CS_SCALE, 0x8);
+ stf_isp_reg_write(stfcamss, ISP_REG_YADJ0, YOIR(0x401) | YIMIN(0x1));
+ stf_isp_reg_write(stfcamss, ISP_REG_YADJ1, YOMAX(0x3ff) | YOMIN(0x1));
+}
+
+int stf_isp_reset(struct stf_isp_dev *isp_dev)
+{
+ stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0,
+ ISPC_RST_MASK, ISPC_RST);
+ stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0,
+ ISPC_RST_MASK, 0);
+
+ return 0;
+}
+
+void stf_isp_init_cfg(struct stf_isp_dev *isp_dev)
+{
+ stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DC_CFG_1, DC_AXI_ID(0x0));
+ stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DEC_CFG,
+ DEC_V_KEEP(0x0) |
+ DEC_V_PERIOD(0x0) |
+ DEC_H_KEEP(0x0) |
+ DEC_H_PERIOD(0x0));
+
+ stf_isp_config_obc(isp_dev->stfcamss);
+ stf_isp_config_oecf(isp_dev->stfcamss);
+ stf_isp_config_lccf(isp_dev->stfcamss);
+ stf_isp_config_awb(isp_dev->stfcamss);
+ stf_isp_config_grgb(isp_dev->stfcamss);
+ stf_isp_config_cfa(isp_dev->stfcamss);
+ stf_isp_config_ccm(isp_dev->stfcamss);
+ stf_isp_config_gamma(isp_dev->stfcamss);
+ stf_isp_config_r2y(isp_dev->stfcamss);
+ stf_isp_config_y_curve(isp_dev->stfcamss);
+ stf_isp_config_sharpen(isp_dev->stfcamss);
+ stf_isp_config_dnyuv(isp_dev->stfcamss);
+ stf_isp_config_sat(isp_dev->stfcamss);
+
+ stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_CSI_MODULE_CFG,
+ CSI_DUMP_EN | CSI_SC_EN | CSI_AWB_EN |
+ CSI_LCCF_EN | CSI_OECF_EN | CSI_OBC_EN | CSI_DEC_EN);
+ stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_ISP_CTRL_1,
+ CTRL_SAT(1) | CTRL_DBC | CTRL_CTC | CTRL_YHIST |
+ CTRL_YCURVE | CTRL_BIYUV | CTRL_SCE | CTRL_EE |
+ CTRL_CCE | CTRL_RGE | CTRL_CME | CTRL_AE | CTRL_CE);
+}
+
+static void stf_isp_config_crop(struct stfcamss *stfcamss,
+ struct v4l2_rect *crop)
+{
+ u32 bpp = stfcamss->isp_dev.current_fmt->bpp;
+ u32 val;
+
+ val = VSTART_CAP(crop->top) | HSTART_CAP(crop->left);
+ stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_START_CFG, val);
+
+ val = VEND_CAP(crop->height + crop->top - 1) |
+ HEND_CAP(crop->width + crop->left - 1);
+ stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_END_CFG, val);
+
+ val = H_ACT_CAP(crop->height) | W_ACT_CAP(crop->width);
+ stf_isp_reg_write(stfcamss, ISP_REG_PIPELINE_XY_SIZE, val);
+
+ val = ALIGN(crop->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
+ stf_isp_reg_write(stfcamss, ISP_REG_STRIDE, val);
+}
+
+static void stf_isp_config_raw_fmt(struct stfcamss *stfcamss, u32 mcode)
+{
+ u32 val, val1;
+
+ switch (mcode) {
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
+ /* 3 2 3 2 1 0 1 0 B Gb B Gb Gr R Gr R */
+ val = SMY13(3) | SMY12(2) | SMY11(3) | SMY10(2) |
+ SMY3(1) | SMY2(0) | SMY1(1) | SMY0(0);
+ val1 = CTRL_SAT(0x0);
+ break;
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
+ /* 2 3 2 3 0 1 0 1, Gb B Gb B R Gr R Gr */
+ val = SMY13(2) | SMY12(3) | SMY11(2) | SMY10(3) |
+ SMY3(0) | SMY2(1) | SMY1(0) | SMY0(1);
+ val1 = CTRL_SAT(0x2);
+ break;
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
+ /* 1 0 1 0 3 2 3 2, Gr R Gr R B Gb B Gb */
+ val = SMY13(1) | SMY12(0) | SMY11(1) | SMY10(0) |
+ SMY3(3) | SMY2(2) | SMY1(3) | SMY0(2);
+ val1 = CTRL_SAT(0x3);
+ break;
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ /* 0 1 0 1 2 3 2 3 R Gr R Gr Gb B Gb B */
+ val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) |
+ SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3);
+ val1 = CTRL_SAT(0x1);
+ break;
+ default:
+ val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) |
+ SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3);
+ val1 = CTRL_SAT(0x1);
+ break;
+ }
+ stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG, val);
+ stf_isp_reg_set_bit(stfcamss, ISP_REG_ISP_CTRL_1, CTRL_SAT_MASK, val1);
+}
+
+void stf_isp_settings(struct stf_isp_dev *isp_dev,
+ struct v4l2_rect *crop, u32 mcode)
+{
+ struct stfcamss *stfcamss = isp_dev->stfcamss;
+
+ stf_isp_config_crop(stfcamss, crop);
+ stf_isp_config_raw_fmt(stfcamss, mcode);
+
+ stf_isp_reg_set_bit(stfcamss, ISP_REG_DUMP_CFG_1,
+ DUMP_BURST_LEN_MASK | DUMP_SD_MASK,
+ DUMP_BURST_LEN(3));
+
+ stf_isp_reg_write(stfcamss, ISP_REG_ITIIWSR,
+ ITI_HSIZE(IMAGE_MAX_HEIGH) |
+ ITI_WSIZE(IMAGE_MAX_WIDTH));
+ stf_isp_reg_write(stfcamss, ISP_REG_ITIDWLSR, 0x960);
+ stf_isp_reg_write(stfcamss, ISP_REG_ITIDRLSR, 0x960);
+ stf_isp_reg_write(stfcamss, ISP_REG_SENSOR, IMAGER_SEL(1));
+}
+
+void stf_isp_stream_set(struct stf_isp_dev *isp_dev)
+{
+ struct stfcamss *stfcamss = isp_dev->stfcamss;
+
+ stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
+ ISPC_ENUO | ISPC_ENLS | ISPC_RST, 10);
+ stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
+ ISPC_ENUO | ISPC_ENLS, 10);
+ stf_isp_reg_write(stfcamss, ISP_REG_IESHD, SHAD_UP_M);
+ stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
+ ISPC_ENUO | ISPC_ENLS | ISPC_EN, 10);
+ stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS,
+ CSI_INTS(1) | CSI_SHA_M(4), 10);
+ stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS,
+ CSI_INTS(2) | CSI_SHA_M(4), 10);
+ stf_isp_reg_write_delay(stfcamss, ISP_REG_CSI_INPUT_EN_AND_STATUS,
+ CSI_EN_S, 10);
+}
diff --git a/drivers/staging/media/starfive/camss/stf-isp.c b/drivers/staging/media/starfive/camss/stf-isp.c
new file mode 100644
index 000000000000..d9c866499d52
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-isp.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * stf_isp.c
+ *
+ * StarFive Camera Subsystem - ISP Module
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+#include <media/v4l2-rect.h>
+
+#include "stf-camss.h"
+
+#define SINK_FORMATS_INDEX 0
+#define SOURCE_FORMATS_INDEX 1
+
+static int isp_set_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_selection *sel);
+
+static const struct stf_isp_format isp_formats_sink[] = {
+ { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
+ { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
+ { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
+ { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
+};
+
+static const struct stf_isp_format isp_formats_source[] = {
+ { MEDIA_BUS_FMT_YUYV8_1_5X8, 8 },
+};
+
+static const struct stf_isp_format_table isp_formats_st7110[] = {
+ { isp_formats_sink, ARRAY_SIZE(isp_formats_sink) },
+ { isp_formats_source, ARRAY_SIZE(isp_formats_source) },
+};
+
+static const struct stf_isp_format *
+stf_g_fmt_by_mcode(const struct stf_isp_format_table *fmt_table, u32 mcode)
+{
+ unsigned int i;
+
+ for (i = 0; i < fmt_table->nfmts; i++) {
+ if (fmt_table->fmts[i].code == mcode)
+ return &fmt_table->fmts[i];
+ }
+
+ return NULL;
+}
+
+int stf_isp_init(struct stfcamss *stfcamss)
+{
+ struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
+
+ isp_dev->stfcamss = stfcamss;
+ isp_dev->formats = isp_formats_st7110;
+ isp_dev->nformats = ARRAY_SIZE(isp_formats_st7110);
+ isp_dev->current_fmt = &isp_formats_source[0];
+
+ return 0;
+}
+
+static int isp_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
+ struct v4l2_subdev_state *sd_state;
+ struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_rect *crop;
+
+ sd_state = v4l2_subdev_lock_and_get_active_state(sd);
+ fmt = v4l2_subdev_get_pad_format(sd, sd_state, STF_ISP_PAD_SINK);
+ crop = v4l2_subdev_get_pad_crop(sd, sd_state, STF_ISP_PAD_SRC);
+
+ if (enable) {
+ stf_isp_reset(isp_dev);
+ stf_isp_init_cfg(isp_dev);
+ stf_isp_settings(isp_dev, crop, fmt->code);
+ stf_isp_stream_set(isp_dev);
+ }
+
+ v4l2_subdev_call(isp_dev->source_subdev, video, s_stream, enable);
+
+ v4l2_subdev_unlock_state(sd_state);
+ return 0;
+}
+
+static void isp_try_format(struct stf_isp_dev *isp_dev,
+ struct v4l2_subdev_state *state,
+ unsigned int pad,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ const struct stf_isp_format_table *formats;
+
+ if (pad >= STF_ISP_PAD_MAX) {
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ return;
+ }
+
+ if (pad == STF_ISP_PAD_SINK)
+ formats = &isp_dev->formats[SINK_FORMATS_INDEX];
+ else if (pad == STF_ISP_PAD_SRC)
+ formats = &isp_dev->formats[SOURCE_FORMATS_INDEX];
+
+ fmt->width = clamp_t(u32, fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
+ STFCAMSS_FRAME_MAX_WIDTH);
+ fmt->height = clamp_t(u32, fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
+ STFCAMSS_FRAME_MAX_HEIGHT);
+ fmt->height &= ~0x1;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ fmt->flags = 0;
+
+ if (!stf_g_fmt_by_mcode(formats, fmt->code))
+ fmt->code = formats->fmts[0].code;
+}
+
+static int isp_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
+ const struct stf_isp_format_table *formats;
+
+ if (code->pad == STF_ISP_PAD_SINK) {
+ formats = &isp_dev->formats[SINK_FORMATS_INDEX];
+ code->code = formats->fmts[code->index].code;
+ } else {
+ struct v4l2_mbus_framefmt *sink_fmt;
+
+ sink_fmt = v4l2_subdev_get_pad_format(sd, state,
+ STF_ISP_PAD_SRC);
+
+ code->code = sink_fmt->code;
+ if (!code->code)
+ return -EINVAL;
+ }
+ code->flags = 0;
+
+ return 0;
+}
+
+static int isp_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
+ struct v4l2_mbus_framefmt format;
+
+ if (fse->index != 0)
+ return -EINVAL;
+
+ format.code = fse->code;
+ format.width = 1;
+ format.height = 1;
+ isp_try_format(isp_dev, state, fse->pad, &format);
+ fse->min_width = STFCAMSS_FRAME_MIN_WIDTH;
+ fse->min_height = STFCAMSS_FRAME_MIN_HEIGHT;
+
+ if (format.code != fse->code)
+ return -EINVAL;
+
+ format.code = fse->code;
+ format.width = -1;
+ format.height = -1;
+ isp_try_format(isp_dev, state, fse->pad, &format);
+ fse->max_width = STFCAMSS_FRAME_MAX_WIDTH;
+ fse->max_height = STFCAMSS_FRAME_MAX_HEIGHT;
+
+ return 0;
+}
+
+static int isp_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
+ struct v4l2_mbus_framefmt *format;
+
+ format = v4l2_subdev_get_pad_format(sd, state, fmt->pad);
+ if (!format)
+ return -EINVAL;
+
+ isp_try_format(isp_dev, state, fmt->pad, &fmt->format);
+ *format = fmt->format;
+
+ isp_dev->current_fmt = stf_g_fmt_by_mcode(&isp_dev->formats[fmt->pad],
+ fmt->format.code);
+
+ /* Propagate to in crop */
+ if (fmt->pad == STF_ISP_PAD_SINK) {
+ struct v4l2_subdev_selection sel = { 0 };
+
+ /* Reset sink pad compose selection */
+ sel.which = fmt->which;
+ sel.pad = STF_ISP_PAD_SINK;
+ sel.target = V4L2_SEL_TGT_CROP;
+ sel.r.width = fmt->format.width;
+ sel.r.height = fmt->format.height;
+ isp_set_selection(sd, state, &sel);
+ }
+
+ return 0;
+}
+
+static const struct v4l2_rect stf_frame_min_crop = {
+ .width = STFCAMSS_FRAME_MIN_WIDTH,
+ .height = STFCAMSS_FRAME_MIN_HEIGHT,
+ .top = 0,
+ .left = 0,
+};
+
+static void isp_try_crop(struct stf_isp_dev *isp_dev,
+ struct v4l2_subdev_state *state,
+ struct v4l2_rect *crop)
+{
+ struct v4l2_mbus_framefmt *fmt =
+ v4l2_subdev_get_pad_format(&isp_dev->subdev, state,
+ STF_ISP_PAD_SINK);
+
+ const struct v4l2_rect bounds = {
+ .width = fmt->width,
+ .height = fmt->height,
+ .left = 0,
+ .top = 0,
+ };
+
+ v4l2_rect_set_min_size(crop, &stf_frame_min_crop);
+ v4l2_rect_map_inside(crop, &bounds);
+}
+
+static int isp_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_selection *sel)
+{
+ struct v4l2_subdev_format fmt = { 0 };
+ struct v4l2_rect *rect;
+
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ if (sel->pad == STF_ISP_PAD_SINK) {
+ fmt.format = *v4l2_subdev_get_pad_format(sd, state,
+ sel->pad);
+ sel->r.left = 0;
+ sel->r.top = 0;
+ sel->r.width = fmt.format.width;
+ sel->r.height = fmt.format.height;
+ } else if (sel->pad == STF_ISP_PAD_SRC) {
+ rect = v4l2_subdev_get_pad_crop(sd, state, sel->pad);
+ sel->r = *rect;
+ }
+ break;
+
+ case V4L2_SEL_TGT_CROP:
+ rect = v4l2_subdev_get_pad_crop(sd, state, sel->pad);
+ if (!rect)
+ return -EINVAL;
+
+ sel->r = *rect;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int isp_set_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_selection *sel)
+{
+ struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
+ struct v4l2_rect *rect;
+
+ if (sel->target != V4L2_SEL_TGT_CROP)
+ return -EINVAL;
+
+ if (sel->target == V4L2_SEL_TGT_CROP &&
+ sel->pad == STF_ISP_PAD_SINK) {
+ struct v4l2_subdev_selection crop = { 0 };
+
+ rect = v4l2_subdev_get_pad_crop(sd, state, sel->pad);
+ if (!rect)
+ return -EINVAL;
+
+ isp_try_crop(isp_dev, state, &sel->r);
+ *rect = sel->r;
+
+ /* Reset source crop selection */
+ crop.which = sel->which;
+ crop.pad = STF_ISP_PAD_SRC;
+ crop.target = V4L2_SEL_TGT_CROP;
+ crop.r = *rect;
+ isp_set_selection(sd, state, &crop);
+ } else if (sel->target == V4L2_SEL_TGT_CROP &&
+ sel->pad == STF_ISP_PAD_SRC) {
+ struct v4l2_subdev_format fmt = { 0 };
+
+ rect = v4l2_subdev_get_pad_crop(sd, state, sel->pad);
+ if (!rect)
+ return -EINVAL;
+
+ isp_try_crop(isp_dev, state, &sel->r);
+ *rect = sel->r;
+
+ /* Reset source pad format width and height */
+ fmt.which = sel->which;
+ fmt.pad = STF_ISP_PAD_SRC;
+ fmt.format.width = rect->width;
+ fmt.format.height = rect->height;
+ isp_set_format(sd, state, &fmt);
+ }
+
+ dev_dbg(isp_dev->stfcamss->dev, "pad: %d sel(%d,%d)/%dx%d\n",
+ sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
+
+ return 0;
+}
+
+static int isp_init_formats(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ struct v4l2_subdev_format format = {
+ .pad = STF_ISP_PAD_SINK,
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format = {
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .width = 1920,
+ .height = 1080
+ }
+ };
+
+ return isp_set_format(sd, sd_state, &format);
+}
+
+static const struct v4l2_subdev_video_ops isp_video_ops = {
+ .s_stream = isp_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops isp_pad_ops = {
+ .init_cfg = isp_init_formats,
+ .enum_mbus_code = isp_enum_mbus_code,
+ .enum_frame_size = isp_enum_frame_size,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = isp_set_format,
+ .get_selection = isp_get_selection,
+ .set_selection = isp_set_selection,
+};
+
+static const struct v4l2_subdev_ops isp_v4l2_ops = {
+ .video = &isp_video_ops,
+ .pad = &isp_pad_ops,
+};
+
+static const struct media_entity_operations isp_media_ops = {
+ .link_validate = v4l2_subdev_link_validate,
+};
+
+int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev)
+{
+ struct v4l2_subdev *sd = &isp_dev->subdev;
+ struct media_pad *pads = isp_dev->pads;
+ int ret;
+
+ v4l2_subdev_init(sd, &isp_v4l2_ops);
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(sd->name, ARRAY_SIZE(sd->name), "stf_isp");
+ v4l2_set_subdevdata(sd, isp_dev);
+
+ pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+ pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
+
+ sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
+ sd->entity.ops = &isp_media_ops;
+ ret = media_entity_pads_init(&sd->entity, STF_ISP_PAD_MAX, pads);
+ if (ret) {
+ dev_err(isp_dev->stfcamss->dev,
+ "Failed to init media entity: %d\n", ret);
+ return ret;
+ }
+
+ ret = v4l2_subdev_init_finalize(sd);
+ if (ret)
+ goto err_entity_cleanup;
+
+ ret = v4l2_device_register_subdev(v4l2_dev, sd);
+ if (ret) {
+ dev_err(isp_dev->stfcamss->dev,
+ "Failed to register subdev: %d\n", ret);
+ goto err_subdev_cleanup;
+ }
+
+ return 0;
+
+err_subdev_cleanup:
+ v4l2_subdev_cleanup(sd);
+err_entity_cleanup:
+ media_entity_cleanup(&sd->entity);
+ return ret;
+}
+
+int stf_isp_unregister(struct stf_isp_dev *isp_dev)
+{
+ v4l2_device_unregister_subdev(&isp_dev->subdev);
+ v4l2_subdev_cleanup(&isp_dev->subdev);
+ media_entity_cleanup(&isp_dev->subdev.entity);
+
+ return 0;
+}
diff --git a/drivers/staging/media/starfive/camss/stf-isp.h b/drivers/staging/media/starfive/camss/stf-isp.h
new file mode 100644
index 000000000000..955cbb048363
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-isp.h
@@ -0,0 +1,428 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * stf_isp.h
+ *
+ * StarFive Camera Subsystem - ISP Module
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#ifndef STF_ISP_H
+#define STF_ISP_H
+
+#include <media/v4l2-subdev.h>
+
+#include "stf-video.h"
+
+#define ISP_RAW_DATA_BITS 12
+#define SCALER_RATIO_MAX 1
+#define STF_ISP_REG_OFFSET_MAX 0x0fff
+#define STF_ISP_REG_DELAY_MAX 100
+
+/* isp registers */
+#define ISP_REG_CSI_INPUT_EN_AND_STATUS 0x000
+#define CSI_SCD_ERR BIT(6)
+#define CSI_ITU656_ERR BIT(4)
+#define CSI_ITU656_F BIT(3)
+#define CSI_SCD_DONE BIT(2)
+#define CSI_BUSY_S BIT(1)
+#define CSI_EN_S BIT(0)
+
+#define ISP_REG_CSIINTS 0x008
+#define CSI_INTS(n) ((n) << 16)
+#define CSI_SHA_M(n) ((n) << 0)
+#define CSI_INTS_MASK GENMASK(17, 16)
+
+#define ISP_REG_CSI_MODULE_CFG 0x010
+#define CSI_DUMP_EN BIT(19)
+#define CSI_VS_EN BIT(18)
+#define CSI_SC_EN BIT(17)
+#define CSI_OBA_EN BIT(16)
+#define CSI_AWB_EN BIT(7)
+#define CSI_LCCF_EN BIT(6)
+#define CSI_OECFHM_EN BIT(5)
+#define CSI_OECF_EN BIT(4)
+#define CSI_LCBQ_EN BIT(3)
+#define CSI_OBC_EN BIT(2)
+#define CSI_DEC_EN BIT(1)
+#define CSI_DC_EN BIT(0)
+
+#define ISP_REG_SENSOR 0x014
+#define DVP_SYNC_POL(n) ((n) << 2)
+#define ITU656_EN(n) ((n) << 1)
+#define IMAGER_SEL(n) ((n) << 0)
+
+#define ISP_REG_RAW_FORMAT_CFG 0x018
+#define SMY13(n) ((n) << 14)
+#define SMY12(n) ((n) << 12)
+#define SMY11(n) ((n) << 10)
+#define SMY10(n) ((n) << 8)
+#define SMY3(n) ((n) << 6)
+#define SMY2(n) ((n) << 4)
+#define SMY1(n) ((n) << 2)
+#define SMY0(n) ((n) << 0)
+
+#define ISP_REG_PIC_CAPTURE_START_CFG 0x01c
+#define VSTART_CAP(n) ((n) << 16)
+#define HSTART_CAP(n) ((n) << 0)
+
+#define ISP_REG_PIC_CAPTURE_END_CFG 0x020
+#define VEND_CAP(n) ((n) << 16)
+#define HEND_CAP(n) ((n) << 0)
+
+#define ISP_REG_DUMP_CFG_0 0x024
+#define ISP_REG_DUMP_CFG_1 0x028
+#define DUMP_ID(n) ((n) << 24)
+#define DUMP_SHT(n) ((n) << 20)
+#define DUMP_BURST_LEN(n) ((n) << 16)
+#define DUMP_SD(n) ((n) << 0)
+#define DUMP_BURST_LEN_MASK GENMASK(17, 16)
+#define DUMP_SD_MASK GENMASK(15, 0)
+
+#define ISP_REG_DEC_CFG 0x030
+#define DEC_V_KEEP(n) ((n) << 24)
+#define DEC_V_PERIOD(n) ((n) << 16)
+#define DEC_H_KEEP(n) ((n) << 8)
+#define DEC_H_PERIOD(n) ((n) << 0)
+
+#define ISP_REG_OBC_CFG 0x034
+#define OBC_W_H(y) ((y) << 4)
+#define OBC_W_W(x) ((x) << 0)
+
+#define ISP_REG_DC_CFG_1 0x044
+#define DC_AXI_ID(n) ((n) << 0)
+
+#define ISP_REG_LCCF_CFG_0 0x050
+#define Y_DISTANCE(y) ((y) << 16)
+#define X_DISTANCE(x) ((x) << 0)
+
+#define ISP_REG_LCCF_CFG_1 0x058
+#define LCCF_MAX_DIS(n) ((n) << 0)
+
+#define ISP_REG_LCBQ_CFG_0 0x074
+#define H_LCBQ(y) ((y) << 12)
+#define W_LCBQ(x) ((x) << 8)
+
+#define ISP_REG_LCBQ_CFG_1 0x07c
+#define Y_COOR(y) ((y) << 16)
+#define X_COOR(x) ((x) << 0)
+
+#define ISP_REG_LCCF_CFG_2 0x0e0
+#define ISP_REG_LCCF_CFG_3 0x0e4
+#define ISP_REG_LCCF_CFG_4 0x0e8
+#define ISP_REG_LCCF_CFG_5 0x0ec
+#define LCCF_F2_PAR(n) ((n) << 16)
+#define LCCF_F1_PAR(n) ((n) << 0)
+
+#define ISP_REG_OECF_X0_CFG0 0x100
+#define ISP_REG_OECF_X0_CFG1 0x104
+#define ISP_REG_OECF_X0_CFG2 0x108
+#define ISP_REG_OECF_X0_CFG3 0x10c
+#define ISP_REG_OECF_X0_CFG4 0x110
+#define ISP_REG_OECF_X0_CFG5 0x114
+#define ISP_REG_OECF_X0_CFG6 0x118
+#define ISP_REG_OECF_X0_CFG7 0x11c
+
+#define ISP_REG_OECF_Y3_CFG0 0x1e0
+#define ISP_REG_OECF_Y3_CFG1 0x1e4
+#define ISP_REG_OECF_Y3_CFG2 0x1e8
+#define ISP_REG_OECF_Y3_CFG3 0x1ec
+#define ISP_REG_OECF_Y3_CFG4 0x1f0
+#define ISP_REG_OECF_Y3_CFG5 0x1f4
+#define ISP_REG_OECF_Y3_CFG6 0x1f8
+#define ISP_REG_OECF_Y3_CFG7 0x1fc
+
+#define ISP_REG_OECF_S0_CFG0 0x200
+#define ISP_REG_OECF_S3_CFG7 0x27c
+#define OCEF_PAR_H(n) ((n) << 16)
+#define OCEF_PAR_L(n) ((n) << 0)
+
+#define ISP_REG_AWB_X0_CFG_0 0x280
+#define ISP_REG_AWB_X0_CFG_1 0x284
+#define ISP_REG_AWB_X1_CFG_0 0x288
+#define ISP_REG_AWB_X1_CFG_1 0x28c
+#define ISP_REG_AWB_X2_CFG_0 0x290
+#define ISP_REG_AWB_X2_CFG_1 0x294
+#define ISP_REG_AWB_X3_CFG_0 0x298
+#define ISP_REG_AWB_X3_CFG_1 0x29c
+#define AWB_X_SYMBOL_H(n) ((n) << 16)
+#define AWB_X_SYMBOL_L(n) ((n) << 0)
+
+#define ISP_REG_AWB_Y0_CFG_0 0x2a0
+#define ISP_REG_AWB_Y0_CFG_1 0x2a4
+#define ISP_REG_AWB_Y1_CFG_0 0x2a8
+#define ISP_REG_AWB_Y1_CFG_1 0x2ac
+#define ISP_REG_AWB_Y2_CFG_0 0x2b0
+#define ISP_REG_AWB_Y2_CFG_1 0x2b4
+#define ISP_REG_AWB_Y3_CFG_0 0x2b8
+#define ISP_REG_AWB_Y3_CFG_1 0x2bc
+#define AWB_Y_SYMBOL_H(n) ((n) << 16)
+#define AWB_Y_SYMBOL_L(n) ((n) << 0)
+
+#define ISP_REG_AWB_S0_CFG_0 0x2c0
+#define ISP_REG_AWB_S0_CFG_1 0x2c4
+#define ISP_REG_AWB_S1_CFG_0 0x2c8
+#define ISP_REG_AWB_S1_CFG_1 0x2cc
+#define ISP_REG_AWB_S2_CFG_0 0x2d0
+#define ISP_REG_AWB_S2_CFG_1 0x2d4
+#define ISP_REG_AWB_S3_CFG_0 0x2d8
+#define ISP_REG_AWB_S3_CFG_1 0x2dc
+#define AWB_S_SYMBOL_H(n) ((n) << 16)
+#define AWB_S_SYMBOL_L(n) ((n) << 0)
+
+#define ISP_REG_OBCG_CFG_0 0x2e0
+#define ISP_REG_OBCG_CFG_1 0x2e4
+#define ISP_REG_OBCG_CFG_2 0x2e8
+#define ISP_REG_OBCG_CFG_3 0x2ec
+#define ISP_REG_OBCO_CFG_0 0x2f0
+#define ISP_REG_OBCO_CFG_1 0x2f4
+#define ISP_REG_OBCO_CFG_2 0x2f8
+#define ISP_REG_OBCO_CFG_3 0x2fc
+#define GAIN_D_POINT(x) ((x) << 24)
+#define GAIN_C_POINT(x) ((x) << 16)
+#define GAIN_B_POINT(x) ((x) << 8)
+#define GAIN_A_POINT(x) ((x) << 0)
+#define OFFSET_D_POINT(x) ((x) << 24)
+#define OFFSET_C_POINT(x) ((x) << 16)
+#define OFFSET_B_POINT(x) ((x) << 8)
+#define OFFSET_A_POINT(x) ((x) << 0)
+
+#define ISP_REG_ISP_CTRL_0 0xa00
+#define ISPC_LINE BIT(27)
+#define ISPC_SC BIT(26)
+#define ISPC_CSI BIT(25)
+#define ISPC_ISP BIT(24)
+#define ISPC_ENUO BIT(20)
+#define ISPC_ENLS BIT(17)
+#define ISPC_ENSS1 BIT(12)
+#define ISPC_ENSS0 BIT(11)
+#define ISPC_RST BIT(1)
+#define ISPC_EN BIT(0)
+#define ISPC_RST_MASK BIT(1)
+#define ISPC_INT_ALL_MASK GENMASK(27, 24)
+
+#define ISP_REG_ISP_CTRL_1 0xa08
+#define CTRL_SAT(n) ((n) << 28)
+#define CTRL_DBC BIT(22)
+#define CTRL_CTC BIT(21)
+#define CTRL_YHIST BIT(20)
+#define CTRL_YCURVE BIT(19)
+#define CTRL_CTM BIT(18)
+#define CTRL_BIYUV BIT(17)
+#define CTRL_SCE BIT(8)
+#define CTRL_EE BIT(7)
+#define CTRL_CCE BIT(5)
+#define CTRL_RGE BIT(4)
+#define CTRL_CME BIT(3)
+#define CTRL_AE BIT(2)
+#define CTRL_CE BIT(1)
+#define CTRL_SAT_MASK GENMASK(31, 28)
+
+#define ISP_REG_PIPELINE_XY_SIZE 0xa0c
+#define H_ACT_CAP(n) ((n) << 16)
+#define W_ACT_CAP(n) ((n) << 0)
+
+#define ISP_REG_ICTC 0xa10
+#define GF_MODE(n) ((n) << 30)
+#define MAXGT(n) ((n) << 16)
+#define MINGT(n) ((n) << 0)
+
+#define ISP_REG_IDBC 0xa14
+#define BADGT(n) ((n) << 16)
+#define BADXT(n) ((n) << 0)
+
+#define ISP_REG_ICFAM 0xa1c
+#define CROSS_COV(n) ((n) << 4)
+#define HV_W(n) ((n) << 0)
+
+#define ISP_REG_CS_GAIN 0xa30
+#define CMAD(n) ((n) << 16)
+#define CMAB(n) ((n) << 0)
+
+#define ISP_REG_CS_THRESHOLD 0xa34
+#define CMD(n) ((n) << 16)
+#define CMB(n) ((n) << 0)
+
+#define ISP_REG_CS_OFFSET 0xa38
+#define VOFF(n) ((n) << 16)
+#define UOFF(n) ((n) << 0)
+
+#define ISP_REG_CS_HUE_F 0xa3c
+#define SIN(n) ((n) << 16)
+#define COS(n) ((n) << 0)
+
+#define ISP_REG_CS_SCALE 0xa40
+
+#define ISP_REG_IESHD 0xa50
+#define SHAD_UP_M BIT(1)
+#define SHAD_UP_EN BIT(0)
+
+#define ISP_REG_YADJ0 0xa54
+#define YOIR(n) ((n) << 16)
+#define YIMIN(n) ((n) << 0)
+
+#define ISP_REG_YADJ1 0xa58
+#define YOMAX(n) ((n) << 16)
+#define YOMIN(n) ((n) << 0)
+
+#define ISP_REG_Y_PLANE_START_ADDR 0xa80
+#define ISP_REG_UV_PLANE_START_ADDR 0xa84
+#define ISP_REG_STRIDE 0xa88
+
+#define ISP_REG_ITIIWSR 0xb20
+#define ITI_HSIZE(n) ((n) << 16)
+#define ITI_WSIZE(n) ((n) << 0)
+
+#define ISP_REG_ITIDWLSR 0xb24
+#define ISP_REG_ITIPDFR 0xb38
+#define ISP_REG_ITIDRLSR 0xb3C
+
+#define ISP_REG_DNYUV_YSWR0 0xc00
+#define ISP_REG_DNYUV_YSWR1 0xc04
+#define ISP_REG_DNYUV_CSWR0 0xc08
+#define ISP_REG_DNYUV_CSWR1 0xc0c
+#define YUVSW5(n) ((n) << 20)
+#define YUVSW4(n) ((n) << 16)
+#define YUVSW3(n) ((n) << 12)
+#define YUVSW2(n) ((n) << 8)
+#define YUVSW1(n) ((n) << 4)
+#define YUVSW0(n) ((n) << 0)
+
+#define ISP_REG_DNYUV_YDR0 0xc10
+#define ISP_REG_DNYUV_YDR1 0xc14
+#define ISP_REG_DNYUV_YDR2 0xc18
+#define ISP_REG_DNYUV_CDR0 0xc1c
+#define ISP_REG_DNYUV_CDR1 0xc20
+#define ISP_REG_DNYUV_CDR2 0xc24
+#define CURVE_D_H(n) ((n) << 16)
+#define CURVE_D_L(n) ((n) << 0)
+
+#define ISP_REG_ICAMD_0 0xc40
+#define ISP_REG_ICAMD_12 0xc70
+#define ISP_REG_ICAMD_20 0xc90
+#define ISP_REG_ICAMD_24 0xca0
+#define ISP_REG_ICAMD_25 0xca4
+#define DNRM_F(n) ((n) << 16)
+#define CCM_M_DAT(n) ((n) << 0)
+
+#define ISP_REG_GAMMA_VAL0 0xe00
+#define ISP_REG_GAMMA_VAL1 0xe04
+#define ISP_REG_GAMMA_VAL2 0xe08
+#define ISP_REG_GAMMA_VAL3 0xe0c
+#define ISP_REG_GAMMA_VAL4 0xe10
+#define ISP_REG_GAMMA_VAL5 0xe14
+#define ISP_REG_GAMMA_VAL6 0xe18
+#define ISP_REG_GAMMA_VAL7 0xe1c
+#define ISP_REG_GAMMA_VAL8 0xe20
+#define ISP_REG_GAMMA_VAL9 0xe24
+#define ISP_REG_GAMMA_VAL10 0xe28
+#define ISP_REG_GAMMA_VAL11 0xe2c
+#define ISP_REG_GAMMA_VAL12 0xe30
+#define ISP_REG_GAMMA_VAL13 0xe34
+#define ISP_REG_GAMMA_VAL14 0xe38
+#define GAMMA_S_VAL(n) ((n) << 16)
+#define GAMMA_VAL(n) ((n) << 0)
+
+#define ISP_REG_R2Y_0 0xe40
+#define ISP_REG_R2Y_1 0xe44
+#define ISP_REG_R2Y_2 0xe48
+#define ISP_REG_R2Y_3 0xe4c
+#define ISP_REG_R2Y_4 0xe50
+#define ISP_REG_R2Y_5 0xe54
+#define ISP_REG_R2Y_6 0xe58
+#define ISP_REG_R2Y_7 0xe5c
+#define ISP_REG_R2Y_8 0xe60
+
+#define ISP_REG_SHARPEN0 0xe80
+#define ISP_REG_SHARPEN1 0xe84
+#define ISP_REG_SHARPEN2 0xe88
+#define ISP_REG_SHARPEN3 0xe8c
+#define ISP_REG_SHARPEN4 0xe90
+#define ISP_REG_SHARPEN5 0xe94
+#define ISP_REG_SHARPEN6 0xe98
+#define ISP_REG_SHARPEN7 0xe9c
+#define ISP_REG_SHARPEN8 0xea0
+#define ISP_REG_SHARPEN9 0xea4
+#define ISP_REG_SHARPEN10 0xea8
+#define ISP_REG_SHARPEN11 0xeac
+#define ISP_REG_SHARPEN12 0xeb0
+#define ISP_REG_SHARPEN13 0xeb4
+#define ISP_REG_SHARPEN14 0xeb8
+#define S_DELTA(n) ((n) << 16)
+#define S_WEIGHT(n) ((n) << 8)
+
+#define ISP_REG_SHARPEN_FS0 0xebc
+#define ISP_REG_SHARPEN_FS1 0xec0
+#define ISP_REG_SHARPEN_FS2 0xec4
+#define ISP_REG_SHARPEN_FS3 0xec8
+#define ISP_REG_SHARPEN_FS4 0xecc
+#define ISP_REG_SHARPEN_FS5 0xed0
+#define S_FACTOR(n) ((n) << 24)
+#define S_SLOPE(n) ((n) << 0)
+
+#define ISP_REG_SHARPEN_WN 0xed4
+#define PDIRF(n) ((n) << 28)
+#define NDIRF(n) ((n) << 24)
+#define WSUM(n) ((n) << 0)
+
+#define ISP_REG_IUVS1 0xed8
+#define UVDIFF2(n) ((n) << 16)
+#define UVDIFF1(n) ((n) << 0)
+
+#define ISP_REG_IUVS2 0xedc
+#define UVF(n) ((n) << 24)
+#define UVSLOPE(n) ((n) << 0)
+
+#define ISP_REG_IUVCKS1 0xee0
+#define UVCKDIFF2(n) ((n) << 16)
+#define UVCKDIFF1(n) ((n) << 0)
+
+#define ISP_REG_IUVCKS2 0xee4
+
+#define ISP_REG_ISHRPET 0xee8
+#define TH(n) ((n) << 8)
+#define EN(n) ((n) << 0)
+
+#define ISP_REG_YCURVE_0 0xf00
+#define ISP_REG_YCURVE_63 0xffc
+
+#define IMAGE_MAX_WIDTH 1920
+#define IMAGE_MAX_HEIGH 1080
+
+/* pad id for media framework */
+enum stf_isp_pad_id {
+ STF_ISP_PAD_SINK = 0,
+ STF_ISP_PAD_SRC,
+ STF_ISP_PAD_MAX
+};
+
+struct stf_isp_format {
+ u32 code;
+ u8 bpp;
+};
+
+struct stf_isp_format_table {
+ const struct stf_isp_format *fmts;
+ int nfmts;
+};
+
+struct stf_isp_dev {
+ struct stfcamss *stfcamss;
+ struct v4l2_subdev subdev;
+ struct media_pad pads[STF_ISP_PAD_MAX];
+ const struct stf_isp_format_table *formats;
+ unsigned int nformats;
+ struct v4l2_subdev *source_subdev;
+ const struct stf_isp_format *current_fmt;
+};
+
+int stf_isp_reset(struct stf_isp_dev *isp_dev);
+void stf_isp_init_cfg(struct stf_isp_dev *isp_dev);
+void stf_isp_settings(struct stf_isp_dev *isp_dev,
+ struct v4l2_rect *crop, u32 mcode);
+void stf_isp_stream_set(struct stf_isp_dev *isp_dev);
+int stf_isp_init(struct stfcamss *stfcamss);
+int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev);
+int stf_isp_unregister(struct stf_isp_dev *isp_dev);
+
+#endif /* STF_ISP_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v9 6/8] media: staging: media: starfive: camss: Add capture driver
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
` (4 preceding siblings ...)
2023-09-14 3:16 ` [PATCH v9 5/8] media: staging: media: starfive: camss: Add ISP driver Jack Zhu
@ 2023-09-14 3:16 ` Jack Zhu
2023-09-14 3:16 ` [PATCH v9 7/8] media: staging: media: starfive: camss: Add interrupt handling Jack Zhu
` (2 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Jack Zhu @ 2023-09-14 3:16 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Robert Foss, Todor Tomov, bryan.odonoghue,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart, Hans Verkuil
Cc: linux-media, linux-kernel, devicetree, linux-staging, jack.zhu,
changhuang.liang
Add capture driver for StarFive Camera Subsystem. It contains two video
devices: capture_yuv and capture_raw.
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
drivers/staging/media/starfive/camss/Makefile | 1 +
.../staging/media/starfive/camss/stf-camss.h | 2 +
.../media/starfive/camss/stf-capture.c | 603 ++++++++++++++++++
.../media/starfive/camss/stf-capture.h | 87 +++
4 files changed, 693 insertions(+)
create mode 100644 drivers/staging/media/starfive/camss/stf-capture.c
create mode 100644 drivers/staging/media/starfive/camss/stf-capture.h
diff --git a/drivers/staging/media/starfive/camss/Makefile b/drivers/staging/media/starfive/camss/Makefile
index 97e1522b21ae..005790202e7b 100644
--- a/drivers/staging/media/starfive/camss/Makefile
+++ b/drivers/staging/media/starfive/camss/Makefile
@@ -5,6 +5,7 @@
starfive-camss-objs += \
stf-camss.o \
+ stf-capture.o \
stf-isp.o \
stf-isp-hw-ops.o \
stf-video.o
diff --git a/drivers/staging/media/starfive/camss/stf-camss.h b/drivers/staging/media/starfive/camss/stf-camss.h
index c7b0a34cd29b..e2b0cfb437bd 100644
--- a/drivers/staging/media/starfive/camss/stf-camss.h
+++ b/drivers/staging/media/starfive/camss/stf-camss.h
@@ -19,6 +19,7 @@
#include <media/v4l2-device.h>
#include "stf-isp.h"
+#include "stf-capture.h"
enum stf_port_num {
STF_PORT_DVP = 0,
@@ -52,6 +53,7 @@ struct stfcamss {
struct media_pipeline pipe;
struct device *dev;
struct stf_isp_dev isp_dev;
+ struct stf_capture captures[STF_CAPTURE_NUM];
struct v4l2_async_notifier notifier;
void __iomem *syscon_base;
void __iomem *isp_base;
diff --git a/drivers/staging/media/starfive/camss/stf-capture.c b/drivers/staging/media/starfive/camss/stf-capture.c
new file mode 100644
index 000000000000..70c24b050a1b
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-capture.c
@@ -0,0 +1,603 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * stf_capture.c
+ *
+ * StarFive Camera Subsystem - capture device
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#include "stf-camss.h"
+
+static const char * const stf_cap_names[] = {
+ "capture_raw",
+ "capture_yuv",
+};
+
+static const struct stfcamss_format_info stf_wr_fmts[] = {
+ {
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SRGGB10,
+ .planes = 1,
+ .vsub = { 1 },
+ .bpp = 10,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SGRBG10,
+ .planes = 1,
+ .vsub = { 1 },
+ .bpp = 10,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SGBRG10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SGBRG10,
+ .planes = 1,
+ .vsub = { 1 },
+ .bpp = 10,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SBGGR10,
+ .planes = 1,
+ .vsub = { 1 },
+ .bpp = 10,
+ },
+};
+
+static const struct stfcamss_format_info stf_isp_fmts[] = {
+ {
+ .code = MEDIA_BUS_FMT_YUYV8_1_5X8,
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ .planes = 2,
+ .vsub = { 1, 2 },
+ .bpp = 8,
+ },
+};
+
+static inline struct stf_capture *to_stf_capture(struct stfcamss_video *video)
+{
+ return container_of(video, struct stf_capture, video);
+}
+
+static void stf_set_raw_addr(struct stfcamss *stfcamss, dma_addr_t addr)
+{
+ stf_syscon_reg_write(stfcamss, VIN_START_ADDR_O, (long)addr);
+ stf_syscon_reg_write(stfcamss, VIN_START_ADDR_N, (long)addr);
+}
+
+static void stf_set_yuv_addr(struct stfcamss *stfcamss,
+ dma_addr_t y_addr, dma_addr_t uv_addr)
+{
+ stf_isp_reg_write(stfcamss, ISP_REG_Y_PLANE_START_ADDR, y_addr);
+ stf_isp_reg_write(stfcamss, ISP_REG_UV_PLANE_START_ADDR, uv_addr);
+}
+
+static void stf_init_addrs(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *output = &cap->buffers;
+ dma_addr_t addr0, addr1;
+
+ output->active_buf = 0;
+
+ if (!output->buf[0])
+ return;
+
+ addr0 = output->buf[0]->addr[0];
+ addr1 = output->buf[0]->addr[1];
+
+ if (cap->type == STF_CAPTURE_RAW)
+ stf_set_raw_addr(video->stfcamss, addr0);
+ else if (cap->type == STF_CAPTURE_YUV)
+ stf_set_yuv_addr(video->stfcamss, addr0, addr1);
+}
+
+static struct stfcamss_buffer *stf_buf_get_pending(struct stf_v_buf *output)
+{
+ struct stfcamss_buffer *buffer = NULL;
+
+ if (!list_empty(&output->pending_bufs)) {
+ buffer = list_first_entry(&output->pending_bufs,
+ struct stfcamss_buffer,
+ queue);
+ list_del(&buffer->queue);
+ }
+
+ return buffer;
+}
+
+static void stf_cap_s_cfg(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *output = &cap->buffers;
+ unsigned long flags;
+
+ spin_lock_irqsave(&output->lock, flags);
+
+ output->state = STF_OUTPUT_IDLE;
+ output->buf[0] = stf_buf_get_pending(output);
+
+ if (!output->buf[0] && output->buf[1]) {
+ output->buf[0] = output->buf[1];
+ output->buf[1] = NULL;
+ }
+
+ if (output->buf[0])
+ output->state = STF_OUTPUT_SINGLE;
+
+ output->sequence = 0;
+ stf_init_addrs(video);
+
+ spin_unlock_irqrestore(&output->lock, flags);
+}
+
+static int stf_cap_s_cleanup(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *output = &cap->buffers;
+ unsigned long flags;
+
+ spin_lock_irqsave(&output->lock, flags);
+
+ output->state = STF_OUTPUT_OFF;
+
+ spin_unlock_irqrestore(&output->lock, flags);
+
+ return 0;
+}
+
+static void stf_wr_data_en(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+
+ stf_syscon_reg_set_bit(stfcamss, VIN_CHANNEL_SEL_EN, U0_VIN_AXIWR0_EN);
+}
+
+static void stf_wr_irq_enable(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+
+ stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_M);
+}
+
+static void stf_wr_irq_disable(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+
+ stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
+ stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
+ stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_M);
+}
+
+static void stf_channel_set(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+ u32 val;
+
+ if (cap->type == STF_CAPTURE_RAW) {
+ val = stf_syscon_reg_read(stfcamss, VIN_CHANNEL_SEL_EN);
+ val &= ~U0_VIN_CHANNEL_SEL_MASK;
+ val |= CHANNEL(0);
+ stf_syscon_reg_write(stfcamss, VIN_CHANNEL_SEL_EN, val);
+
+ val = stf_syscon_reg_read(stfcamss, VIN_INRT_PIX_CFG);
+ val &= ~U0_VIN_PIX_CT_MASK;
+ val |= PIX_CT(1);
+
+ val &= ~U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS;
+ val |= PIXEL_HEIGH_BIT_SEL(0);
+
+ val &= ~U0_VIN_PIX_CNT_END_MASK;
+ val |= PIX_CNT_END(IMAGE_MAX_WIDTH / 4 - 1);
+
+ stf_syscon_reg_write(stfcamss, VIN_INRT_PIX_CFG, val);
+ } else if (cap->type == STF_CAPTURE_YUV) {
+ val = stf_syscon_reg_read(stfcamss, VIN_CFG_REG);
+ val &= ~U0_VIN_MIPI_BYTE_EN_ISP0_MASK;
+ val |= U0_VIN_MIPI_BYTE_EN_ISP0(0);
+
+ val &= ~U0_VIN_MIPI_CHANNEL_SEL0_MASK;
+ val |= U0_VIN_MIPI_CHANNEL_SEL0(0);
+
+ val &= ~U0_VIN_PIX_NUM_MASK;
+ val |= U0_VIN_PIX_NUM(0);
+
+ val &= ~U0_VIN_P_I_MIPI_HAEDER_EN0_MASK;
+ val |= U0_VIN_P_I_MIPI_HAEDER_EN0(1);
+
+ stf_syscon_reg_write(stfcamss, VIN_CFG_REG, val);
+ }
+}
+
+static void stf_capture_start(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+
+ stf_channel_set(video);
+ if (cap->type == STF_CAPTURE_RAW) {
+ stf_wr_irq_enable(video);
+ stf_wr_data_en(video);
+ }
+
+ stf_cap_s_cfg(video);
+}
+
+static void stf_capture_stop(struct stfcamss_video *video)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+
+ if (cap->type == STF_CAPTURE_RAW)
+ stf_wr_irq_disable(video);
+
+ stf_cap_s_cleanup(video);
+}
+
+static void stf_capture_init(struct stfcamss *stfcamss, struct stf_capture *cap)
+{
+ cap->buffers.state = STF_OUTPUT_OFF;
+ cap->buffers.buf[0] = NULL;
+ cap->buffers.buf[1] = NULL;
+ cap->buffers.active_buf = 0;
+ atomic_set(&cap->buffers.frame_skip, 4);
+ INIT_LIST_HEAD(&cap->buffers.pending_bufs);
+ INIT_LIST_HEAD(&cap->buffers.ready_bufs);
+ spin_lock_init(&cap->buffers.lock);
+
+ cap->video.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cap->video.stfcamss = stfcamss;
+ cap->video.bpl_alignment = 16 * 8;
+
+ if (cap->type == STF_CAPTURE_RAW) {
+ cap->video.formats = stf_wr_fmts;
+ cap->video.nformats = ARRAY_SIZE(stf_wr_fmts);
+ cap->video.bpl_alignment = 8;
+ } else if (cap->type == STF_CAPTURE_YUV) {
+ cap->video.formats = stf_isp_fmts;
+ cap->video.nformats = ARRAY_SIZE(stf_isp_fmts);
+ cap->video.bpl_alignment = 1;
+ }
+}
+
+static void stf_buf_add_ready(struct stf_v_buf *output,
+ struct stfcamss_buffer *buffer)
+{
+ INIT_LIST_HEAD(&buffer->queue);
+ list_add_tail(&buffer->queue, &output->ready_bufs);
+}
+
+static struct stfcamss_buffer *stf_buf_get_ready(struct stf_v_buf *output)
+{
+ struct stfcamss_buffer *buffer = NULL;
+
+ if (!list_empty(&output->ready_bufs)) {
+ buffer = list_first_entry(&output->ready_bufs,
+ struct stfcamss_buffer,
+ queue);
+ list_del(&buffer->queue);
+ }
+
+ return buffer;
+}
+
+static void stf_buf_add_pending(struct stf_v_buf *output,
+ struct stfcamss_buffer *buffer)
+{
+ INIT_LIST_HEAD(&buffer->queue);
+ list_add_tail(&buffer->queue, &output->pending_bufs);
+}
+
+static void stf_buf_update_on_last(struct stf_v_buf *output)
+{
+ switch (output->state) {
+ case STF_OUTPUT_CONTINUOUS:
+ output->state = STF_OUTPUT_SINGLE;
+ output->active_buf = !output->active_buf;
+ break;
+ case STF_OUTPUT_SINGLE:
+ output->state = STF_OUTPUT_STOPPING;
+ break;
+ default:
+ break;
+ }
+}
+
+static void stf_buf_update_on_next(struct stf_v_buf *output)
+{
+ switch (output->state) {
+ case STF_OUTPUT_CONTINUOUS:
+ output->active_buf = !output->active_buf;
+ break;
+ case STF_OUTPUT_SINGLE:
+ default:
+ break;
+ }
+}
+
+static void stf_buf_update_on_new(struct stfcamss_video *video,
+ struct stfcamss_buffer *new_buf)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *output = &cap->buffers;
+
+ switch (output->state) {
+ case STF_OUTPUT_SINGLE:
+ stf_buf_add_pending(output, new_buf);
+ break;
+ case STF_OUTPUT_IDLE:
+ if (!output->buf[0]) {
+ output->buf[0] = new_buf;
+ stf_init_addrs(video);
+ output->state = STF_OUTPUT_SINGLE;
+ } else {
+ stf_buf_add_pending(output, new_buf);
+ }
+ break;
+ case STF_OUTPUT_STOPPING:
+ if (output->last_buffer) {
+ output->buf[output->active_buf] = output->last_buffer;
+ output->last_buffer = NULL;
+ }
+
+ output->state = STF_OUTPUT_SINGLE;
+ stf_buf_add_pending(output, new_buf);
+ break;
+ case STF_OUTPUT_CONTINUOUS:
+ default:
+ stf_buf_add_pending(output, new_buf);
+ break;
+ }
+}
+
+static void stf_buf_flush(struct stf_v_buf *output, enum vb2_buffer_state state)
+{
+ struct stfcamss_buffer *buf;
+ struct stfcamss_buffer *t;
+
+ list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) {
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
+ list_del(&buf->queue);
+ }
+ list_for_each_entry_safe(buf, t, &output->ready_bufs, queue) {
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
+ list_del(&buf->queue);
+ }
+}
+
+static void stf_buf_done(struct stf_v_buf *output)
+{
+ struct stfcamss_buffer *ready_buf;
+ u64 ts = ktime_get_ns();
+ unsigned long flags;
+
+ if (output->state == STF_OUTPUT_OFF ||
+ output->state == STF_OUTPUT_RESERVED)
+ return;
+
+ spin_lock_irqsave(&output->lock, flags);
+
+ while ((ready_buf = stf_buf_get_ready(output))) {
+ ready_buf->vb.vb2_buf.timestamp = ts;
+ ready_buf->vb.sequence = output->sequence++;
+
+ vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ }
+
+ spin_unlock_irqrestore(&output->lock, flags);
+}
+
+static void stf_change_buffer(struct stf_v_buf *output)
+{
+ struct stf_capture *cap = container_of(output, struct stf_capture,
+ buffers);
+ struct stfcamss *stfcamss = cap->video.stfcamss;
+ struct stfcamss_buffer *ready_buf;
+ dma_addr_t *new_addr;
+ unsigned long flags;
+ u32 active_index;
+
+ if (output->state == STF_OUTPUT_OFF ||
+ output->state == STF_OUTPUT_STOPPING ||
+ output->state == STF_OUTPUT_RESERVED ||
+ output->state == STF_OUTPUT_IDLE)
+ return;
+
+ spin_lock_irqsave(&output->lock, flags);
+
+ active_index = output->active_buf;
+
+ ready_buf = output->buf[active_index];
+ if (!ready_buf) {
+ dev_dbg(stfcamss->dev, "missing ready buf %d %d.\n",
+ active_index, output->state);
+ active_index = !active_index;
+ ready_buf = output->buf[active_index];
+ if (!ready_buf) {
+ dev_dbg(stfcamss->dev,
+ "missing ready buf2 %d %d.\n",
+ active_index, output->state);
+ goto out_unlock;
+ }
+ }
+
+ /* Get next buffer */
+ output->buf[active_index] = stf_buf_get_pending(output);
+ if (!output->buf[active_index]) {
+ new_addr = ready_buf->addr;
+ stf_buf_update_on_last(output);
+ } else {
+ new_addr = output->buf[active_index]->addr;
+ stf_buf_update_on_next(output);
+ }
+
+ if (output->state == STF_OUTPUT_STOPPING) {
+ output->last_buffer = ready_buf;
+ } else {
+ if (cap->type == STF_CAPTURE_RAW)
+ stf_set_raw_addr(stfcamss, new_addr[0]);
+ else if (cap->type == STF_CAPTURE_YUV)
+ stf_set_yuv_addr(stfcamss, new_addr[0], new_addr[1]);
+
+ stf_buf_add_ready(output, ready_buf);
+ }
+
+out_unlock:
+ spin_unlock_irqrestore(&output->lock, flags);
+}
+
+irqreturn_t stf_wr_irq_handler(int irq, void *priv)
+{
+ struct stfcamss *stfcamss = priv;
+ struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_RAW];
+
+ if (atomic_dec_if_positive(&cap->buffers.frame_skip) < 0) {
+ stf_change_buffer(&cap->buffers);
+ stf_buf_done(&cap->buffers);
+ }
+
+ stf_syscon_reg_set_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
+ stf_syscon_reg_clear_bit(stfcamss, VIN_INRT_PIX_CFG, U0_VIN_INTR_CLEAN);
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t stf_isp_irq_handler(int irq, void *priv)
+{
+ struct stfcamss *stfcamss = priv;
+ struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_YUV];
+ u32 status;
+
+ status = stf_isp_reg_read(stfcamss, ISP_REG_ISP_CTRL_0);
+ if (status & ISPC_ISP) {
+ if (status & ISPC_ENUO)
+ stf_buf_done(&cap->buffers);
+
+ stf_isp_reg_write(stfcamss, ISP_REG_ISP_CTRL_0,
+ (status & ~ISPC_INT_ALL_MASK) |
+ ISPC_ISP | ISPC_CSI | ISPC_SC);
+ }
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t stf_line_irq_handler(int irq, void *priv)
+{
+ struct stfcamss *stfcamss = priv;
+ struct stf_capture *cap = &stfcamss->captures[STF_CAPTURE_YUV];
+ u32 status;
+
+ status = stf_isp_reg_read(stfcamss, ISP_REG_ISP_CTRL_0);
+ if (status & ISPC_LINE) {
+ if (atomic_dec_if_positive(&cap->buffers.frame_skip) < 0) {
+ if ((status & ISPC_ENUO))
+ stf_change_buffer(&cap->buffers);
+ }
+
+ stf_isp_reg_set_bit(stfcamss, ISP_REG_CSIINTS,
+ CSI_INTS_MASK, CSI_INTS(0x3));
+ stf_isp_reg_set_bit(stfcamss, ISP_REG_IESHD,
+ SHAD_UP_M | SHAD_UP_EN, 0x3);
+
+ stf_isp_reg_write(stfcamss, ISP_REG_ISP_CTRL_0,
+ (status & ~ISPC_INT_ALL_MASK) | ISPC_LINE);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int stf_queue_buffer(struct stfcamss_video *video,
+ struct stfcamss_buffer *buf)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *v_bufs = &cap->buffers;
+ unsigned long flags;
+
+ spin_lock_irqsave(&v_bufs->lock, flags);
+ stf_buf_update_on_new(video, buf);
+ spin_unlock_irqrestore(&v_bufs->lock, flags);
+
+ return 0;
+}
+
+static int stf_flush_buffers(struct stfcamss_video *video,
+ enum vb2_buffer_state state)
+{
+ struct stf_capture *cap = to_stf_capture(video);
+ struct stf_v_buf *v_bufs = &cap->buffers;
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&v_bufs->lock, flags);
+
+ stf_buf_flush(v_bufs, state);
+
+ for (i = 0; i < ARRAY_SIZE(v_bufs->buf); i++) {
+ if (v_bufs->buf[i])
+ vb2_buffer_done(&v_bufs->buf[i]->vb.vb2_buf, state);
+
+ v_bufs->buf[i] = NULL;
+ }
+
+ if (v_bufs->last_buffer) {
+ vb2_buffer_done(&v_bufs->last_buffer->vb.vb2_buf, state);
+ v_bufs->last_buffer = NULL;
+ }
+
+ spin_unlock_irqrestore(&v_bufs->lock, flags);
+ return 0;
+}
+
+static const struct stfcamss_video_ops stf_capture_ops = {
+ .queue_buffer = stf_queue_buffer,
+ .flush_buffers = stf_flush_buffers,
+ .start_streaming = stf_capture_start,
+ .stop_streaming = stf_capture_stop,
+};
+
+static void stf_capture_unregister_one(struct stf_capture *cap)
+{
+ if (!video_is_registered(&cap->video.vdev))
+ return;
+
+ media_entity_cleanup(&cap->video.vdev.entity);
+ vb2_video_unregister_device(&cap->video.vdev);
+}
+
+void stf_capture_unregister(struct stfcamss *stfcamss)
+{
+ struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
+ struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
+
+ stf_capture_unregister_one(cap_raw);
+ stf_capture_unregister_one(cap_yuv);
+}
+
+int stf_capture_register(struct stfcamss *stfcamss,
+ struct v4l2_device *v4l2_dev)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(stfcamss->captures); i++) {
+ struct stf_capture *capture = &stfcamss->captures[i];
+
+ capture->type = i;
+ capture->video.ops = &stf_capture_ops;
+ stf_capture_init(stfcamss, capture);
+
+ ret = stf_video_register(&capture->video, v4l2_dev,
+ stf_cap_names[i]);
+ if (ret < 0) {
+ dev_err(stfcamss->dev,
+ "Failed to register video node: %d\n", ret);
+ stf_capture_unregister(stfcamss);
+ return ret;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/media/starfive/camss/stf-capture.h b/drivers/staging/media/starfive/camss/stf-capture.h
new file mode 100644
index 000000000000..4a6c8f9b779b
--- /dev/null
+++ b/drivers/staging/media/starfive/camss/stf-capture.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * stf_capture.h
+ *
+ * Starfive Camera Subsystem driver
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ */
+
+#ifndef STF_CAPTURE_H
+#define STF_CAPTURE_H
+
+#include "stf-video.h"
+
+#define VIN_CHANNEL_SEL_EN 0x14
+#define VIN_START_ADDR_N 0x18
+#define VIN_INRT_PIX_CFG 0x1c
+#define VIN_START_ADDR_O 0x20
+#define VIN_CFG_REG 0x24
+
+#define U0_VIN_CNFG_AXI_DVP_EN BIT(2)
+
+#define U0_VIN_CHANNEL_SEL_MASK GENMASK(3, 0)
+#define U0_VIN_AXIWR0_EN BIT(4)
+#define CHANNEL(x) ((x) << 0)
+
+#define U0_VIN_INTR_CLEAN BIT(0)
+#define U0_VIN_INTR_M BIT(1)
+#define U0_VIN_PIX_CNT_END_MASK GENMASK(12, 2)
+#define U0_VIN_PIX_CT_MASK GENMASK(14, 13)
+#define U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS GENMASK(16, 15)
+
+#define PIX_CNT_END(x) ((x) << 2)
+#define PIX_CT(x) ((x) << 13)
+#define PIXEL_HEIGH_BIT_SEL(x) ((x) << 15)
+
+#define U0_VIN_CNFG_DVP_HS_POS BIT(1)
+#define U0_VIN_CNFG_DVP_SWAP_EN BIT(2)
+#define U0_VIN_CNFG_DVP_VS_POS BIT(3)
+#define U0_VIN_CNFG_GEN_EN_AXIRD BIT(4)
+#define U0_VIN_CNFG_ISP_DVP_EN0 BIT(5)
+#define U0_VIN_MIPI_BYTE_EN_ISP0(n) ((n) << 6)
+#define U0_VIN_MIPI_CHANNEL_SEL0(n) ((n) << 8)
+#define U0_VIN_P_I_MIPI_HAEDER_EN0(n) ((n) << 12)
+#define U0_VIN_PIX_NUM(n) ((n) << 13)
+#define U0_VIN_MIPI_BYTE_EN_ISP0_MASK GENMASK(7, 6)
+#define U0_VIN_MIPI_CHANNEL_SEL0_MASK GENMASK(11, 8)
+#define U0_VIN_P_I_MIPI_HAEDER_EN0_MASK BIT(12)
+#define U0_VIN_PIX_NUM_MASK GENMASK(16, 13)
+
+enum stf_v_state {
+ STF_OUTPUT_OFF,
+ STF_OUTPUT_RESERVED,
+ STF_OUTPUT_SINGLE,
+ STF_OUTPUT_CONTINUOUS,
+ STF_OUTPUT_IDLE,
+ STF_OUTPUT_STOPPING
+};
+
+struct stf_v_buf {
+ int active_buf;
+ struct stfcamss_buffer *buf[2];
+ struct stfcamss_buffer *last_buffer;
+ struct list_head pending_bufs;
+ struct list_head ready_bufs;
+ enum stf_v_state state;
+ unsigned int sequence;
+ /* protects the above member variables */
+ spinlock_t lock;
+ atomic_t frame_skip;
+};
+
+struct stf_capture {
+ struct stfcamss_video video;
+ struct stf_v_buf buffers;
+ enum stf_capture_type type;
+};
+
+irqreturn_t stf_wr_irq_handler(int irq, void *priv);
+irqreturn_t stf_isp_irq_handler(int irq, void *priv);
+irqreturn_t stf_line_irq_handler(int irq, void *priv);
+int stf_capture_register(struct stfcamss *stfcamss,
+ struct v4l2_device *v4l2_dev);
+void stf_capture_unregister(struct stfcamss *stfcamss);
+
+#endif
+
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v9 7/8] media: staging: media: starfive: camss: Add interrupt handling
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
` (5 preceding siblings ...)
2023-09-14 3:16 ` [PATCH v9 6/8] media: staging: media: starfive: camss: Add capture driver Jack Zhu
@ 2023-09-14 3:16 ` Jack Zhu
2023-09-14 3:16 ` [PATCH v9 8/8] media: staging: media: starfive: camss: Register devices Jack Zhu
2023-09-15 9:26 ` [PATCH v9 0/8] Add StarFive Camera Subsystem driver Hans Verkuil
8 siblings, 0 replies; 17+ messages in thread
From: Jack Zhu @ 2023-09-14 3:16 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Robert Foss, Todor Tomov, bryan.odonoghue,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart, Hans Verkuil
Cc: linux-media, linux-kernel, devicetree, linux-staging, jack.zhu,
changhuang.liang
Parse interrupt resources and register interrupt handlers.
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
.../staging/media/starfive/camss/stf-camss.c | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c
index f083bc0e6e97..373467322885 100644
--- a/drivers/staging/media/starfive/camss/stf-camss.c
+++ b/drivers/staging/media/starfive/camss/stf-camss.c
@@ -35,6 +35,12 @@ static const char * const stfcamss_resets[] = {
"rst_isp_top_axi",
};
+static const struct stf_isr_data stf_isrs[] = {
+ {"wr_irq", stf_wr_irq_handler},
+ {"isp_irq", stf_isp_irq_handler},
+ {"line_irq", stf_line_irq_handler},
+};
+
static int stfcamss_get_mem_res(struct stfcamss *stfcamss)
{
struct platform_device *pdev = to_platform_device(stfcamss->dev);
@@ -160,6 +166,21 @@ static int stfcamss_probe(struct platform_device *pdev)
stfcamss->dev = dev;
+ for (i = 0; i < ARRAY_SIZE(stf_isrs); ++i) {
+ int irq;
+
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_irq(stfcamss->dev, irq, stf_isrs[i].isr, 0,
+ stf_isrs[i].name, stfcamss);
+ if (ret) {
+ dev_err(dev, "request irq failed: %d\n", ret);
+ return ret;
+ }
+ }
+
stfcamss->nclks = ARRAY_SIZE(stfcamss->sys_clk);
for (i = 0; i < stfcamss->nclks; ++i)
stfcamss->sys_clk[i].id = stfcamss_clocks[i];
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v9 8/8] media: staging: media: starfive: camss: Register devices
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
` (6 preceding siblings ...)
2023-09-14 3:16 ` [PATCH v9 7/8] media: staging: media: starfive: camss: Add interrupt handling Jack Zhu
@ 2023-09-14 3:16 ` Jack Zhu
2023-09-15 9:26 ` [PATCH v9 0/8] Add StarFive Camera Subsystem driver Hans Verkuil
8 siblings, 0 replies; 17+ messages in thread
From: Jack Zhu @ 2023-09-14 3:16 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Robert Foss, Todor Tomov, bryan.odonoghue,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart, Hans Verkuil
Cc: linux-media, linux-kernel, devicetree, linux-staging, jack.zhu,
changhuang.liang
Register ISP sub-device and video devices for StarFive Camera
Subsystem.
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
.../staging/media/starfive/camss/stf-camss.c | 97 ++++++++++++++++++-
1 file changed, 96 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c
index 373467322885..b2e0f5b3c910 100644
--- a/drivers/staging/media/starfive/camss/stf-camss.c
+++ b/drivers/staging/media/starfive/camss/stf-camss.c
@@ -123,6 +123,85 @@ static int stfcamss_of_parse_ports(struct stfcamss *stfcamss)
return ret;
}
+static int stfcamss_register_devs(struct stfcamss *stfcamss)
+{
+ struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
+ struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
+ int ret;
+
+ ret = stf_isp_register(isp_dev, &stfcamss->v4l2_dev);
+ if (ret < 0) {
+ dev_err(stfcamss->dev,
+ "failed to register stf isp%d entity: %d\n", 0, ret);
+ return ret;
+ }
+
+ ret = stf_capture_register(stfcamss, &stfcamss->v4l2_dev);
+ if (ret < 0) {
+ dev_err(stfcamss->dev,
+ "failed to register capture: %d\n", ret);
+ goto err_isp_unregister;
+ }
+
+ ret = media_create_pad_link(&isp_dev->subdev.entity, STF_ISP_PAD_SRC,
+ &cap_yuv->video.vdev.entity, 0, 0);
+ if (ret)
+ goto err_cap_unregister;
+
+ cap_yuv->video.source_subdev = &isp_dev->subdev;
+
+ return ret;
+
+err_cap_unregister:
+ stf_capture_unregister(stfcamss);
+err_isp_unregister:
+ stf_isp_unregister(&stfcamss->isp_dev);
+
+ return ret;
+}
+
+static void stfcamss_unregister_devs(struct stfcamss *stfcamss)
+{
+ stf_isp_unregister(&stfcamss->isp_dev);
+ stf_capture_unregister(stfcamss);
+}
+
+static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async,
+ struct v4l2_subdev *subdev,
+ struct v4l2_async_connection *asc)
+{
+ struct stfcamss *stfcamss =
+ container_of(async, struct stfcamss, notifier);
+ struct stfcamss_async_subdev *csd =
+ container_of(asc, struct stfcamss_async_subdev, asd);
+ enum stf_port_num port = csd->port;
+ struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
+ struct stf_capture *cap_raw = &stfcamss->captures[STF_CAPTURE_RAW];
+ struct media_pad *pad;
+ int ret;
+
+ if (port == STF_PORT_CSI2RX) {
+ pad = &isp_dev->pads[STF_ISP_PAD_SINK];
+ } else {
+ dev_err(stfcamss->dev, "not support port %d\n", port);
+ return -EPERM;
+ }
+
+ ret = v4l2_create_fwnode_links_to_pad(subdev, pad, 0);
+ if (ret)
+ return ret;
+
+ ret = media_create_pad_link(&subdev->entity, 1,
+ &cap_raw->video.vdev.entity, 0, 0);
+ if (ret)
+ return ret;
+
+ isp_dev->source_subdev = subdev;
+ cap_raw->video.source_subdev = subdev;
+
+ return 0;
+}
+
static int stfcamss_subdev_notifier_complete(struct v4l2_async_notifier *ntf)
{
struct stfcamss *stfcamss =
@@ -133,6 +212,7 @@ static int stfcamss_subdev_notifier_complete(struct v4l2_async_notifier *ntf)
static const struct v4l2_async_notifier_operations
stfcamss_subdev_notifier_ops = {
+ .bound = stfcamss_subdev_notifier_bound,
.complete = stfcamss_subdev_notifier_complete,
};
@@ -217,6 +297,12 @@ static int stfcamss_probe(struct platform_device *pdev)
goto err_cleanup_notifier;
}
+ ret = stf_isp_init(stfcamss);
+ if (ret < 0) {
+ dev_err(dev, "Failed to init isp: %d\n", ret);
+ goto err_cleanup_notifier;
+ }
+
stfcamss_mc_init(pdev, stfcamss);
ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev);
@@ -231,6 +317,12 @@ static int stfcamss_probe(struct platform_device *pdev)
goto err_unregister_device;
}
+ ret = stfcamss_register_devs(stfcamss);
+ if (ret < 0) {
+ dev_err(dev, "Failed to register subdevice: %d\n", ret);
+ goto err_unregister_media_dev;
+ }
+
pm_runtime_enable(dev);
stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
@@ -239,11 +331,13 @@ static int stfcamss_probe(struct platform_device *pdev)
dev_err(dev, "Failed to register async subdev nodes: %d\n",
ret);
pm_runtime_disable(dev);
- goto err_unregister_media_dev;
+ goto err_unregister_subdevs;
}
return 0;
+err_unregister_subdevs:
+ stfcamss_unregister_devs(stfcamss);
err_unregister_media_dev:
media_device_unregister(&stfcamss->media_dev);
err_unregister_device:
@@ -265,6 +359,7 @@ static int stfcamss_remove(struct platform_device *pdev)
{
struct stfcamss *stfcamss = platform_get_drvdata(pdev);
+ stfcamss_unregister_devs(stfcamss);
v4l2_device_unregister(&stfcamss->v4l2_dev);
media_device_cleanup(&stfcamss->media_dev);
v4l2_async_nf_cleanup(&stfcamss->notifier);
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v9 0/8] Add StarFive Camera Subsystem driver
2023-09-14 3:15 [PATCH v9 0/8] Add StarFive Camera Subsystem driver Jack Zhu
` (7 preceding siblings ...)
2023-09-14 3:16 ` [PATCH v9 8/8] media: staging: media: starfive: camss: Register devices Jack Zhu
@ 2023-09-15 9:26 ` Hans Verkuil
2023-09-18 9:30 ` Jack Zhu
2023-09-28 8:12 ` Jack Zhu
8 siblings, 2 replies; 17+ messages in thread
From: Hans Verkuil @ 2023-09-15 9:26 UTC (permalink / raw)
To: Jack Zhu, Mauro Carvalho Chehab, Robert Foss, Todor Tomov,
bryan.odonoghue, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart
Cc: linux-media, linux-kernel, devicetree, linux-staging,
changhuang.liang
On 14/09/2023 05:15, Jack Zhu wrote:
> Hi,
>
> This series is the v9 series that attempts to support the Camera Subsystem
> found on StarFive JH7110 SoC.
>
> This series is based on top of the master branch of media_stage repository.
>
> The following are the media graph for the device and the v4l2-compliance
> output.
>
> ===========================================================================
> [the media graph]:
>
> digraph board {
> rankdir=TB
> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
> n00000001:port1 -> n00000008 [style=dashed]
> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
> n0000000e:port1 -> n00000001:port0 [style=dashed]
> n0000000e:port1 -> n00000004 [style=dashed]
> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
> n00000018:port0 -> n0000000e:port0 [style=bold]
> }
>
> [the device topology]:
>
> Media controller API version 6.5.0
>
> Media device information
> ------------------------
> driver starfive-camss
> model Starfive Camera Subsystem
> serial
> bus info platform:19840000.camss
> hw revision 0x0
> driver version 6.5.0
>
> Device topology
> - entity 1: stf_isp (2 pads, 2 links)
> type V4L2 subdev subtype Unknown flags 0
> device node name /dev/v4l-subdev0
> pad0: Sink
> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
> crop.bounds:(0,0)/1920x1080
> crop:(0,0)/1920x1080]
> <- "cdns_csi2rx.19800000.csi-bridge":1 []
> pad1: Source
> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
> crop.bounds:(0,0)/1920x1080
> crop:(0,0)/1920x1080]
> -> "capture_yuv":0 []
>
> - entity 4: capture_raw (1 pad, 1 link)
> type Node subtype V4L flags 0
> device node name /dev/video0
> pad0: Sink
> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>
> - entity 8: capture_yuv (1 pad, 1 link)
> type Node subtype V4L flags 0
> device node name /dev/video1
> pad0: Sink
> <- "stf_isp":1 []
>
> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
> type V4L2 subdev subtype Unknown flags 0
> pad0: Sink
> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
> pad1: Source
> -> "stf_isp":0 []
> -> "capture_raw":0 []
> pad2: Source
> pad3: Source
> pad4: Source
>
> - entity 24: imx219 6-0010 (1 pad, 1 link)
> type V4L2 subdev subtype Sensor flags 0
> device node name /dev/v4l-subdev1
> pad0: Source
> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
> crop.bounds:(8,8)/3280x2464
> crop:(8,8)/3280x2464]
> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>
> ===========================================================================
> [the v4l2-compliance output]:
>
> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
This v4l2-compliance version is from a distro. For driver acceptance you
must test with a v4l2-compliance compiled from the git repo (git://linuxtv.org/v4l-utils.git).
Also, since this driver uses the media controller, you must run v4l2-compliance
with the -m /dev/mediaX option. This will test the compliance of all devices
reported by the media controller.
>
> Compliance test for stf camss device /dev/video1:
>
> Driver Info:
> Driver name : stf camss
The module is called starfive-camss, so shouldn't the driver name reported here
be the same?
> Card type : Starfive Camera Subsystem
> Bus info : platform:19840000.camss
> Driver version : 6.5.0
> Capabilities : 0x84200001
> Video Capture
> Streaming
> Extended Pix Format
> Device Capabilities
> Device Caps : 0x04200001
> Video Capture
> Streaming
> Extended Pix Format
> Media Driver Info:
> Driver name : starfive-camss
It's correct in the media controller information.
> Model : Starfive Camera Subsystem
> Serial :
> Bus info : platform:19840000.camss
> Media version : 6.5.0
> Hardware revision: 0x00000000 (0)
> Driver version : 6.5.0
> Interface Info:
> ID : 0x0300000a
> Type : V4L Video
> Entity Info:
> ID : 0x00000008 (8)
> Name : capture_yuv
> Function : V4L2 I/O
> Pad 0x01000009 : 0: Sink
> Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
Hmm, this reports "Unknown Function". I bet that when you run v4l2-compliance
with the -m option it will fail on this. If not, then that's likely a bug in
the compliance test, please let me know if that's the case.
Regards,
Hans
>
> Required ioctls:
> test MC information (see 'Media Driver Info' above): OK
> test VIDIOC_QUERYCAP: OK
> test invalid ioctls: OK
>
> Allow for multiple opens:
> test second /dev/video1 open: OK
> test VIDIOC_QUERYCAP: OK
> test VIDIOC_G/S_PRIORITY: OK
> test for unlimited opens: OK
>
> Debug ioctls:
> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> test VIDIOC_LOG_STATUS: OK (Not Supported)
>
> Input ioctls:
> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> test VIDIOC_ENUMAUDIO: OK (Not Supported)
> test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDIO: OK (Not Supported)
> Inputs: 0 Audio Inputs: 0 Tuners: 0
>
> Output ioctls:
> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> Outputs: 0 Audio Outputs: 0 Modulators: 0
>
> Input/Output configuration ioctls:
> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> test VIDIOC_G/S_EDID: OK (Not Supported)
>
> Control ioctls:
> test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
> test VIDIOC_QUERYCTRL: OK (Not Supported)
> test VIDIOC_G/S_CTRL: OK (Not Supported)
> test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 0 Private Controls: 0
>
> Format ioctls:
> test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> test VIDIOC_G/S_PARM: OK (Not Supported)
> test VIDIOC_G_FBUF: OK (Not Supported)
> test VIDIOC_G_FMT: OK
> test VIDIOC_TRY_FMT: OK
> test VIDIOC_S_FMT: OK
> test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> test Cropping: OK (Not Supported)
> test Composing: OK (Not Supported)
> test Scaling: OK
>
> Codec ioctls:
> test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
> test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
>
> Buffer ioctls:
> test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> test VIDIOC_EXPBUF: OK
> test Requests: OK (Not Supported)
>
> Test input 0:
>
> Streaming ioctls:
> test read/write: OK (Not Supported)
> test blocking wait: OK
> test MMAP (no poll): OK
> test MMAP (select): OK
> test MMAP (epoll): OK
> test USERPTR (no poll): OK (Not Supported)
> test USERPTR (select): OK (Not Supported)
> test DMABUF: Cannot test, specify --expbuf-device
>
> Total for stf camss device /dev/video1: 53, Succeeded: 53, Failed: 0, Warnings: 0
>
> ===========================================================================
> Changes in v9:
> - Rebased on top of the master branch of media_stage repository.
> - Renamed file name.
> - Added of_node_put(node) in the error handling path of
> stfcamss_of_parse_ports().
>
> v8 link: https://lore.kernel.org/all/20230824080109.89613-1-jack.zhu@starfivetech.com/
>
> Changes in v8:
> - Rebased on v6.5-rc7.
> - Dropped VIN subdev.
> - Created two new video devices: capture_raw and capture_yuv, to replace
> the previous video devices.
> - Dropped VB2_READ io methods.
> - Recursively called .s_stream() on subdevs.
>
> v7 link: https://lore.kernel.org/all/20230619112838.19797-1-jack.zhu@starfivetech.com/
>
> Changes in v7:
> - HAS_DMA is used instead of DMA_CMA in Kconfig.
> - Dropped some non-essential member variables.
> - Used v4l2_async_nf_add_fwnode_remote() to simplify the relevant code.
> - Modified some Local variable types in the function.
> - Used v4l2_create_fwnode_links_to_pad() to simplify the relevant code.
> - Added error handling for clk_prepare_enable().
> - Simplified stfcamss_format_info struct and modified the relevant code.
> - Dropped enum_input, g_input and s_input.
> - Unified v4l2_ioctl_ops struct.
> - Used v4l2_fh_open()/vb2_fop_release to replace deprecated APIs.
> - Added a camss directory under the starfive directory and modified the
> patch title.
>
> v6 link: https://lore.kernel.org/all/20230525083202.67933-1-jack.zhu@starfivetech.com/
>
> Changes in v6:
> - Added 'bus-type' in bindings example.
> - Corrected spelling errors.
> - As reviewed by Bryan, used 'nclks' and 'nrsts' variables.
> - Added lccf config for ISP.
>
> v5 link: https://lore.kernel.org/all/20230512102844.51084-1-jack.zhu@starfivetech.com/
>
> Changes in v5:
> - Rebased on v6.4-rc1.
> - Added new patch.
> - Modified ISP driver.
>
> v4 link: https://lore.kernel.org/all/20230413035541.62129-1-jack.zhu@starfivetech.com/
>
> Previous cover letter from v4:
>
> This patch series adds support for the StarFive Camera Subsystem
> found on StarFive JH7110 SoC.
>
> The driver implements V4L2, Media controller and V4L2 subdev interfaces.
> Camera sensor using V4L2 subdev interface in the kernel is supported.
>
> The driver is tested on VisionFive V2 board with IMX219 camera sensor.
> GStreamer 1.18.5 with v4l2src plugin is supported.
>
> Previous version link, missing v1 version:
>
> v3: https://lore.kernel.org/all/20230331121826.96973-1-jack.zhu@starfivetech.com/
> v2: https://lore.kernel.org/all/20230310120553.60586-1-jack.zhu@starfivetech.com/
>
> Jack Zhu (8):
> media: dt-bindings: Add JH7110 Camera Subsystem
> media: admin-guide: Add starfive_camss.rst for Starfive Camera
> Subsystem
> media: staging: media: starfive: camss: Add core driver
> media: staging: media: starfive: camss: Add video driver
> media: staging: media: starfive: camss: Add ISP driver
> media: staging: media: starfive: camss: Add capture driver
> media: staging: media: starfive: camss: Add interrupt handling
> media: staging: media: starfive: camss: Register devices
>
> .../admin-guide/media/starfive_camss.rst | 72 +++
> .../media/starfive_camss_graph.dot | 12 +
> .../admin-guide/media/v4l-drivers.rst | 1 +
> .../bindings/media/starfive,jh7110-camss.yaml | 180 ++++++
> MAINTAINERS | 9 +
> drivers/staging/media/Kconfig | 2 +
> drivers/staging/media/Makefile | 1 +
> drivers/staging/media/starfive/Kconfig | 5 +
> drivers/staging/media/starfive/Makefile | 2 +
> drivers/staging/media/starfive/camss/Kconfig | 17 +
> drivers/staging/media/starfive/camss/Makefile | 13 +
> .../staging/media/starfive/camss/stf-camss.c | 436 +++++++++++++
> .../staging/media/starfive/camss/stf-camss.h | 134 ++++
> .../media/starfive/camss/stf-capture.c | 603 ++++++++++++++++++
> .../media/starfive/camss/stf-capture.h | 87 +++
> .../media/starfive/camss/stf-isp-hw-ops.c | 445 +++++++++++++
> .../staging/media/starfive/camss/stf-isp.c | 407 ++++++++++++
> .../staging/media/starfive/camss/stf-isp.h | 428 +++++++++++++
> .../staging/media/starfive/camss/stf-video.c | 571 +++++++++++++++++
> .../staging/media/starfive/camss/stf-video.h | 100 +++
> 20 files changed, 3525 insertions(+)
> create mode 100644 Documentation/admin-guide/media/starfive_camss.rst
> create mode 100644 Documentation/admin-guide/media/starfive_camss_graph.dot
> create mode 100644 Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
> create mode 100644 drivers/staging/media/starfive/Kconfig
> create mode 100644 drivers/staging/media/starfive/Makefile
> create mode 100644 drivers/staging/media/starfive/camss/Kconfig
> create mode 100644 drivers/staging/media/starfive/camss/Makefile
> create mode 100644 drivers/staging/media/starfive/camss/stf-camss.c
> create mode 100644 drivers/staging/media/starfive/camss/stf-camss.h
> create mode 100644 drivers/staging/media/starfive/camss/stf-capture.c
> create mode 100644 drivers/staging/media/starfive/camss/stf-capture.h
> create mode 100644 drivers/staging/media/starfive/camss/stf-isp-hw-ops.c
> create mode 100644 drivers/staging/media/starfive/camss/stf-isp.c
> create mode 100644 drivers/staging/media/starfive/camss/stf-isp.h
> create mode 100644 drivers/staging/media/starfive/camss/stf-video.c
> create mode 100644 drivers/staging/media/starfive/camss/stf-video.h
>
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH v9 0/8] Add StarFive Camera Subsystem driver
2023-09-15 9:26 ` [PATCH v9 0/8] Add StarFive Camera Subsystem driver Hans Verkuil
@ 2023-09-18 9:30 ` Jack Zhu
2023-09-20 12:37 ` Hans Verkuil
2023-09-28 8:12 ` Jack Zhu
1 sibling, 1 reply; 17+ messages in thread
From: Jack Zhu @ 2023-09-18 9:30 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Robert Foss, Todor Tomov,
bryan.odonoghue, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart
Cc: linux-media, linux-kernel, devicetree, linux-staging,
changhuang.liang
Hi Hans,
Thanks for your comment.
On 2023/9/15 17:26, Hans Verkuil wrote:
> On 14/09/2023 05:15, Jack Zhu wrote:
>> Hi,
>>
>> This series is the v9 series that attempts to support the Camera Subsystem
>> found on StarFive JH7110 SoC.
>>
>> This series is based on top of the master branch of media_stage repository.
>>
>> The following are the media graph for the device and the v4l2-compliance
>> output.
>>
>> ===========================================================================
>> [the media graph]:
>>
>> digraph board {
>> rankdir=TB
>> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
>> n00000001:port1 -> n00000008 [style=dashed]
>> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
>> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
>> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
>> n0000000e:port1 -> n00000001:port0 [style=dashed]
>> n0000000e:port1 -> n00000004 [style=dashed]
>> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
>> n00000018:port0 -> n0000000e:port0 [style=bold]
>> }
>>
>> [the device topology]:
>>
>> Media controller API version 6.5.0
>>
>> Media device information
>> ------------------------
>> driver starfive-camss
>> model Starfive Camera Subsystem
>> serial
>> bus info platform:19840000.camss
>> hw revision 0x0
>> driver version 6.5.0
>>
>> Device topology
>> - entity 1: stf_isp (2 pads, 2 links)
>> type V4L2 subdev subtype Unknown flags 0
>> device node name /dev/v4l-subdev0
>> pad0: Sink
>> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
>> crop.bounds:(0,0)/1920x1080
>> crop:(0,0)/1920x1080]
>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>> pad1: Source
>> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
>> crop.bounds:(0,0)/1920x1080
>> crop:(0,0)/1920x1080]
>> -> "capture_yuv":0 []
>>
>> - entity 4: capture_raw (1 pad, 1 link)
>> type Node subtype V4L flags 0
>> device node name /dev/video0
>> pad0: Sink
>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>
>> - entity 8: capture_yuv (1 pad, 1 link)
>> type Node subtype V4L flags 0
>> device node name /dev/video1
>> pad0: Sink
>> <- "stf_isp":1 []
>>
>> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
>> type V4L2 subdev subtype Unknown flags 0
>> pad0: Sink
>> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
>> pad1: Source
>> -> "stf_isp":0 []
>> -> "capture_raw":0 []
>> pad2: Source
>> pad3: Source
>> pad4: Source
>>
>> - entity 24: imx219 6-0010 (1 pad, 1 link)
>> type V4L2 subdev subtype Sensor flags 0
>> device node name /dev/v4l-subdev1
>> pad0: Source
>> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
>> crop.bounds:(8,8)/3280x2464
>> crop:(8,8)/3280x2464]
>> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>>
>> ===========================================================================
>> [the v4l2-compliance output]:
>>
>> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
>
> This v4l2-compliance version is from a distro. For driver acceptance you
> must test with a v4l2-compliance compiled from the git repo (git://linuxtv.org/v4l-utils.git).
>
It is compiled from buildroot, but its source code is also downloaded from the repo tag v4l-utils-1.24.1.
Do you mean I should use the latest stable version (stable-1.24) on the repo?
--
Regards,
Jack Zhu
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH v9 0/8] Add StarFive Camera Subsystem driver
2023-09-18 9:30 ` Jack Zhu
@ 2023-09-20 12:37 ` Hans Verkuil
0 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2023-09-20 12:37 UTC (permalink / raw)
To: Jack Zhu, Mauro Carvalho Chehab, Robert Foss, Todor Tomov,
bryan.odonoghue, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart
Cc: linux-media, linux-kernel, devicetree, linux-staging,
changhuang.liang
On 18/09/2023 11:30, Jack Zhu wrote:
> Hi Hans,
>
> Thanks for your comment.
>
> On 2023/9/15 17:26, Hans Verkuil wrote:
>> On 14/09/2023 05:15, Jack Zhu wrote:
>>> Hi,
>>>
>>> This series is the v9 series that attempts to support the Camera Subsystem
>>> found on StarFive JH7110 SoC.
>>>
>>> This series is based on top of the master branch of media_stage repository.
>>>
>>> The following are the media graph for the device and the v4l2-compliance
>>> output.
>>>
>>> ===========================================================================
>>> [the media graph]:
>>>
>>> digraph board {
>>> rankdir=TB
>>> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
>>> n00000001:port1 -> n00000008 [style=dashed]
>>> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
>>> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
>>> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
>>> n0000000e:port1 -> n00000001:port0 [style=dashed]
>>> n0000000e:port1 -> n00000004 [style=dashed]
>>> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
>>> n00000018:port0 -> n0000000e:port0 [style=bold]
>>> }
>>>
>>> [the device topology]:
>>>
>>> Media controller API version 6.5.0
>>>
>>> Media device information
>>> ------------------------
>>> driver starfive-camss
>>> model Starfive Camera Subsystem
>>> serial
>>> bus info platform:19840000.camss
>>> hw revision 0x0
>>> driver version 6.5.0
>>>
>>> Device topology
>>> - entity 1: stf_isp (2 pads, 2 links)
>>> type V4L2 subdev subtype Unknown flags 0
>>> device node name /dev/v4l-subdev0
>>> pad0: Sink
>>> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
>>> crop.bounds:(0,0)/1920x1080
>>> crop:(0,0)/1920x1080]
>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>> pad1: Source
>>> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
>>> crop.bounds:(0,0)/1920x1080
>>> crop:(0,0)/1920x1080]
>>> -> "capture_yuv":0 []
>>>
>>> - entity 4: capture_raw (1 pad, 1 link)
>>> type Node subtype V4L flags 0
>>> device node name /dev/video0
>>> pad0: Sink
>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>>
>>> - entity 8: capture_yuv (1 pad, 1 link)
>>> type Node subtype V4L flags 0
>>> device node name /dev/video1
>>> pad0: Sink
>>> <- "stf_isp":1 []
>>>
>>> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
>>> type V4L2 subdev subtype Unknown flags 0
>>> pad0: Sink
>>> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
>>> pad1: Source
>>> -> "stf_isp":0 []
>>> -> "capture_raw":0 []
>>> pad2: Source
>>> pad3: Source
>>> pad4: Source
>>>
>>> - entity 24: imx219 6-0010 (1 pad, 1 link)
>>> type V4L2 subdev subtype Sensor flags 0
>>> device node name /dev/v4l-subdev1
>>> pad0: Source
>>> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
>>> crop.bounds:(8,8)/3280x2464
>>> crop:(8,8)/3280x2464]
>>> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>>>
>>> ===========================================================================
>>> [the v4l2-compliance output]:
>>>
>>> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
>>
>> This v4l2-compliance version is from a distro. For driver acceptance you
>> must test with a v4l2-compliance compiled from the git repo (git://linuxtv.org/v4l-utils.git).
>>
>
> It is compiled from buildroot, but its source code is also downloaded from the repo tag v4l-utils-1.24.1.
> Do you mean I should use the latest stable version (stable-1.24) on the repo?
>
No, you want the latest version, period. So just the master branch of the v4l-utils git repo.
For the compliance tests you want the latest and greatest, since the stable tags are often
fairly old.
Regards,
Hans
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v9 0/8] Add StarFive Camera Subsystem driver
2023-09-15 9:26 ` [PATCH v9 0/8] Add StarFive Camera Subsystem driver Hans Verkuil
2023-09-18 9:30 ` Jack Zhu
@ 2023-09-28 8:12 ` Jack Zhu
2023-09-28 8:22 ` Hans Verkuil
1 sibling, 1 reply; 17+ messages in thread
From: Jack Zhu @ 2023-09-28 8:12 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Robert Foss, Todor Tomov,
bryan.odonoghue@linaro.org, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-staging@lists.linux.dev,
Changhuang Liang
On 2023/9/15 17:26, Hans Verkuil wrote:
> On 14/09/2023 05:15, Jack Zhu wrote:
>> Hi,
>>
>> This series is the v9 series that attempts to support the Camera Subsystem
>> found on StarFive JH7110 SoC.
>>
>> This series is based on top of the master branch of media_stage repository.
>>
>> The following are the media graph for the device and the v4l2-compliance
>> output.
>>
>> ===========================================================================
>> [the media graph]:
>>
>> digraph board {
>> rankdir=TB
>> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
>> n00000001:port1 -> n00000008 [style=dashed]
>> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
>> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
>> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
>> n0000000e:port1 -> n00000001:port0 [style=dashed]
>> n0000000e:port1 -> n00000004 [style=dashed]
>> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
>> n00000018:port0 -> n0000000e:port0 [style=bold]
>> }
>>
>> [the device topology]:
>>
>> Media controller API version 6.5.0
>>
>> Media device information
>> ------------------------
>> driver starfive-camss
>> model Starfive Camera Subsystem
>> serial
>> bus info platform:19840000.camss
>> hw revision 0x0
>> driver version 6.5.0
>>
>> Device topology
>> - entity 1: stf_isp (2 pads, 2 links)
>> type V4L2 subdev subtype Unknown flags 0
>> device node name /dev/v4l-subdev0
>> pad0: Sink
>> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
>> crop.bounds:(0,0)/1920x1080
>> crop:(0,0)/1920x1080]
>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>> pad1: Source
>> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
>> crop.bounds:(0,0)/1920x1080
>> crop:(0,0)/1920x1080]
>> -> "capture_yuv":0 []
>>
>> - entity 4: capture_raw (1 pad, 1 link)
>> type Node subtype V4L flags 0
>> device node name /dev/video0
>> pad0: Sink
>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>
>> - entity 8: capture_yuv (1 pad, 1 link)
>> type Node subtype V4L flags 0
>> device node name /dev/video1
>> pad0: Sink
>> <- "stf_isp":1 []
>>
>> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
>> type V4L2 subdev subtype Unknown flags 0
>> pad0: Sink
>> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
>> pad1: Source
>> -> "stf_isp":0 []
>> -> "capture_raw":0 []
>> pad2: Source
>> pad3: Source
>> pad4: Source
>>
>> - entity 24: imx219 6-0010 (1 pad, 1 link)
>> type V4L2 subdev subtype Sensor flags 0
>> device node name /dev/v4l-subdev1
>> pad0: Source
>> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
>> crop.bounds:(8,8)/3280x2464
>> crop:(8,8)/3280x2464]
>> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>>
>> ===========================================================================
>> [the v4l2-compliance output]:
>>
>> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
>
> This v4l2-compliance version is from a distro. For driver acceptance you
> must test with a v4l2-compliance compiled from the git repo (git://linuxtv.org/v4l-utils.git).
>
> Also, since this driver uses the media controller, you must run v4l2-compliance
> with the -m /dev/mediaX option. This will test the compliance of all devices
> reported by the media controller.
>
>>
>> Compliance test for stf camss device /dev/video1:
>>
>> Driver Info:
>> Driver name : stf camss
>
> The module is called starfive-camss, so shouldn't the driver name reported here
> be the same?
>
>> Card type : Starfive Camera Subsystem
>> Bus info : platform:19840000.camss
>> Driver version : 6.5.0
>> Capabilities : 0x84200001
>> Video Capture
>> Streaming
>> Extended Pix Format
>> Device Capabilities
>> Device Caps : 0x04200001
>> Video Capture
>> Streaming
>> Extended Pix Format
>> Media Driver Info:
>> Driver name : starfive-camss
>
> It's correct in the media controller information.
>
>> Model : Starfive Camera Subsystem
>> Serial :
>> Bus info : platform:19840000.camss
>> Media version : 6.5.0
>> Hardware revision: 0x00000000 (0)
>> Driver version : 6.5.0
>> Interface Info:
>> ID : 0x0300000a
>> Type : V4L Video
>> Entity Info:
>> ID : 0x00000008 (8)
>> Name : capture_yuv
>> Function : V4L2 I/O
>> Pad 0x01000009 : 0: Sink
>> Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
>
> Hmm, this reports "Unknown Function". I bet that when you run v4l2-compliance
> with the -m option it will fail on this. If not, then that's likely a bug in
> the compliance test, please let me know if that's the case.
>
Hi Hans,
The following is the latest test log, which does not report a failure, but
also reports "Unknown Function".
I make the following settings in the stf-isp.c file:
v4l2_subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
#
# v4l2-compliance -m /dev/media0
v4l2-compliance 1.25.0, 64 bits, 64-bit time_t
Compliance test for starfive-camss device /dev/media0:
Media Driver Info:
Driver name : starfive-camss
Model : Starfive Camera Subsystem
Serial :
Bus info : platform:19840000.camss
Media version : 6.5.0
Hardware revision: 0x00000000 (0)
Driver version : 6.5.0
Required ioctls:
test MEDIA_IOC_DEVICE_INFO: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/media0 open: OK
test MEDIA_IOC_DEVICE_INFO: OK
test for unlimited opens: OK
Media Controller ioctls:
test MEDIA_IOC_G_TOPOLOGY: OK
Entities: 5 Interfaces: 4 Pads: 10 Links: 8
test MEDIA_IOC_ENUM_ENTITIES/LINKS: OK
test MEDIA_IOC_SETUP_LINK: OK
Total for starfive-camss device /dev/media0: 8, Succeeded: 8, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for starfive-camss device /dev/video0:
Driver Info:
Driver name : starfive-camss
Card type : Starfive Camera Subsystem
Bus info : platform:19840000.camss
Driver version : 6.5.0
Capabilities : 0x84200001
Video Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04200001
Video Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : starfive-camss
Model : Starfive Camera Subsystem
Serial :
Bus info : platform:19840000.camss
Media version : 6.5.0
Hardware revision: 0x00000000 (0)
Driver version : 6.5.0
Interface Info:
ID : 0x03000006
Type : V4L Video
Entity Info:
ID : 0x00000004 (4)
Name : capture_raw
Function : V4L2 I/O
Pad 0x01000005 : 0: Sink
Link 0x02000016: from remote pad 0x1000010 of entity 'cdns_csi2rx.19800000.csi-bridge' (Video Interface Bridge): Data
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/video0 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK (Not Supported)
Total for starfive-camss device /dev/video0: 46, Succeeded: 46, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for starfive-camss device /dev/video1:
Driver Info:
Driver name : starfive-camss
Card type : Starfive Camera Subsystem
Bus info : platform:19840000.camss
Driver version : 6.5.0
Capabilities : 0x84200001
Video Capture
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04200001
Video Capture
Streaming
Extended Pix Format
Media Driver Info:
Driver name : starfive-camss
Model : Starfive Camera Subsystem
Serial :
Bus info : platform:19840000.camss
Media version : 6.5.0
Hardware revision: 0x00000000 (0)
Driver version : 6.5.0
Interface Info:
ID : 0x0300000a
Type : V4L Video
Entity Info:
ID : 0x00000008 (8)
Name : capture_yuv
Function : V4L2 I/O
Pad 0x01000009 : 0: Sink
Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/video1 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXstf_isp: ================= START STATUS =================
PBUF: OKtf_isp: ================== END STATUS ==================
m
test Requests: OK (Not Supported)
Total for starfive-camss device /dev/video1: 46, Succeeded: 46, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for starfive-camss device /dev/v4l-subdev0:
Driver Info:
Driver version : 6.5.0
Capabilities : 0x00000000
Media Driver Info:
Driver name : starfive-camss
Model : Starfive Camera Subsystem
Serial :
Bus info : platform:19840000.camss
Media version : 6.5.0
Hardware revision: 0x00000000 (0)
Driver version : 6.5.0
Interface Info:
ID : 0x0300001c
Type : V4L Sub-Device
Entity Info:
ID : 0x00000001 (1)
Name : stf_isp
Function : WARNING: Unknown Function (00004009), is v4l2-compliance out-of-date?
Pad 0x01000002 : 0: Sink
Link 0x02000014: from remote pad 0x1000010 of entity 'cdns_csi2rx.19800000.csi-bridge' (Video Interface Bridge): Data, Enabled
Pad 0x01000003 : 1: Source
Link 0x0200000c: to remote pad 0x1000009 of entity 'capture_yuv' (V4L2 I/O): Data, Enabled
Required ioctls:
test MC information (see 'Media Driver Info' above): OK
test VIDIOC_SUDBEV_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/v4l-subdev0 open: OK
test VIDIOC_SUBDEV_QUERYCAP: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Sub-Device ioctls (Sink Pad 0):
Try Stream 0
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
test Try VIDIOC_SUBDEV_G/S_FMT: OK
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK
Active Stream 0
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
test Active VIDIOC_SUBDEV_G/S_FMT: OK
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Sub-Device ioctls (Source Pad 1):
Try Stream 0
test Try VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
test Try VIDIOC_SUBDEV_G/S_FMT: OK
test Try VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK
Active Stream 0
test Active VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: OK
test Active VIDIOC_SUBDEV_G/S_FMT: OK
test Active VIDIOC_SUBDEV_G/S_SELECTION/CROP: OK
test VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEimx219 6-0010: ================= START STATUS =================
VENT: OKmx219 6-0010: ================== END STATUS ==================
m (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK (Not Supported)
test VIDIOC_TRY_FMT: OK (Not Supported)
test VIDIOC_S_FMT: OK (Not Supported)
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
test VIDIOC_EXPBUF: OK (Not Supported)
test Requests: OK (Not Supported)
Total for starfive-camss device /dev/v4l-subdev0: 58, Succeeded: 58, Failed: 0, Warnings: 0
--------------------------------------------------------------------------------
Compliance test for device /dev/v4l-subdev1:
Driver Info:
Driver version : 6.5.0
Capabilities : 0x00000000
Required ioctls:
test VIDIOC_SUDBEV_QUERYCAP: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/v4l-subdev1 open: OK
test VIDIOC_SUBDEV_QUERYCAP: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
test VIDIOC_QUERYCTRL: OK
test VIDIOC_G/S_CTRL: OK
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 20 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK (Not Supported)
test VIDIOC_TRY_FMT: OK (Not Supported)
test VIDIOC_S_FMT: OK (Not Supported)
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
test VIDIOC_EXPBUF: OK (Not Supported)
test Requests: OK (Not Supported)
Total for device /dev/v4l-subdev1: 43, Succeeded: 43, Failed: 0, Warnings: 0
Grand Total for starfive-camss device /dev/media0: 201, Succeeded: 201, Failed: 0, Warnings: 0
#
--
Regards,
Jack Zhu
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH v9 0/8] Add StarFive Camera Subsystem driver
2023-09-28 8:12 ` Jack Zhu
@ 2023-09-28 8:22 ` Hans Verkuil
2023-09-28 8:29 ` Hans Verkuil
2023-09-28 8:40 ` Jack Zhu
0 siblings, 2 replies; 17+ messages in thread
From: Hans Verkuil @ 2023-09-28 8:22 UTC (permalink / raw)
To: Jack Zhu, Mauro Carvalho Chehab, Robert Foss, Todor Tomov,
bryan.odonoghue@linaro.org, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-staging@lists.linux.dev,
Changhuang Liang
On 28/09/2023 10:12, Jack Zhu wrote:
>
>
> On 2023/9/15 17:26, Hans Verkuil wrote:
>> On 14/09/2023 05:15, Jack Zhu wrote:
>>> Hi,
>>>
>>> This series is the v9 series that attempts to support the Camera Subsystem
>>> found on StarFive JH7110 SoC.
>>>
>>> This series is based on top of the master branch of media_stage repository.
>>>
>>> The following are the media graph for the device and the v4l2-compliance
>>> output.
>>>
>>> ===========================================================================
>>> [the media graph]:
>>>
>>> digraph board {
>>> rankdir=TB
>>> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
>>> n00000001:port1 -> n00000008 [style=dashed]
>>> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
>>> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
>>> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
>>> n0000000e:port1 -> n00000001:port0 [style=dashed]
>>> n0000000e:port1 -> n00000004 [style=dashed]
>>> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
>>> n00000018:port0 -> n0000000e:port0 [style=bold]
>>> }
>>>
>>> [the device topology]:
>>>
>>> Media controller API version 6.5.0
>>>
>>> Media device information
>>> ------------------------
>>> driver starfive-camss
>>> model Starfive Camera Subsystem
>>> serial
>>> bus info platform:19840000.camss
>>> hw revision 0x0
>>> driver version 6.5.0
>>>
>>> Device topology
>>> - entity 1: stf_isp (2 pads, 2 links)
>>> type V4L2 subdev subtype Unknown flags 0
>>> device node name /dev/v4l-subdev0
>>> pad0: Sink
>>> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
>>> crop.bounds:(0,0)/1920x1080
>>> crop:(0,0)/1920x1080]
>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>> pad1: Source
>>> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
>>> crop.bounds:(0,0)/1920x1080
>>> crop:(0,0)/1920x1080]
>>> -> "capture_yuv":0 []
>>>
>>> - entity 4: capture_raw (1 pad, 1 link)
>>> type Node subtype V4L flags 0
>>> device node name /dev/video0
>>> pad0: Sink
>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>>
>>> - entity 8: capture_yuv (1 pad, 1 link)
>>> type Node subtype V4L flags 0
>>> device node name /dev/video1
>>> pad0: Sink
>>> <- "stf_isp":1 []
>>>
>>> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
>>> type V4L2 subdev subtype Unknown flags 0
>>> pad0: Sink
>>> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
>>> pad1: Source
>>> -> "stf_isp":0 []
>>> -> "capture_raw":0 []
>>> pad2: Source
>>> pad3: Source
>>> pad4: Source
>>>
>>> - entity 24: imx219 6-0010 (1 pad, 1 link)
>>> type V4L2 subdev subtype Sensor flags 0
>>> device node name /dev/v4l-subdev1
>>> pad0: Source
>>> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
>>> crop.bounds:(8,8)/3280x2464
>>> crop:(8,8)/3280x2464]
>>> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>>>
>>> ===========================================================================
>>> [the v4l2-compliance output]:
>>>
>>> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
>>
>> This v4l2-compliance version is from a distro. For driver acceptance you
>> must test with a v4l2-compliance compiled from the git repo (git://linuxtv.org/v4l-utils.git).
>>
>> Also, since this driver uses the media controller, you must run v4l2-compliance
>> with the -m /dev/mediaX option. This will test the compliance of all devices
>> reported by the media controller.
>>
>>>
>>> Compliance test for stf camss device /dev/video1:
>>>
>>> Driver Info:
>>> Driver name : stf camss
>>
>> The module is called starfive-camss, so shouldn't the driver name reported here
>> be the same?
>>
>>> Card type : Starfive Camera Subsystem
>>> Bus info : platform:19840000.camss
>>> Driver version : 6.5.0
>>> Capabilities : 0x84200001
>>> Video Capture
>>> Streaming
>>> Extended Pix Format
>>> Device Capabilities
>>> Device Caps : 0x04200001
>>> Video Capture
>>> Streaming
>>> Extended Pix Format
>>> Media Driver Info:
>>> Driver name : starfive-camss
>>
>> It's correct in the media controller information.
>>
>>> Model : Starfive Camera Subsystem
>>> Serial :
>>> Bus info : platform:19840000.camss
>>> Media version : 6.5.0
>>> Hardware revision: 0x00000000 (0)
>>> Driver version : 6.5.0
>>> Interface Info:
>>> ID : 0x0300000a
>>> Type : V4L Video
>>> Entity Info:
>>> ID : 0x00000008 (8)
>>> Name : capture_yuv
>>> Function : V4L2 I/O
>>> Pad 0x01000009 : 0: Sink
>>> Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
>>
>> Hmm, this reports "Unknown Function". I bet that when you run v4l2-compliance
>> with the -m option it will fail on this. If not, then that's likely a bug in
>> the compliance test, please let me know if that's the case.
>>
>
> Hi Hans,
>
> The following is the latest test log, which does not report a failure, but
> also reports "Unknown Function".
>
> I make the following settings in the stf-isp.c file:
> v4l2_subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
>
Can you post the output of:
v4l2-compliance --verbose -M /dev/media0
I am beginning to suspect that utils/common/media-info.cpp is out-of-date:
it is missing MEDIA_ENT_F_PROC_VIDEO_ISP.
But I don't understand why v4l2-compliance didn't fail on this.
Regards,
Hans
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH v9 0/8] Add StarFive Camera Subsystem driver
2023-09-28 8:22 ` Hans Verkuil
@ 2023-09-28 8:29 ` Hans Verkuil
2023-09-28 8:40 ` Jack Zhu
1 sibling, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2023-09-28 8:29 UTC (permalink / raw)
To: Jack Zhu, Mauro Carvalho Chehab, Robert Foss, Todor Tomov,
bryan.odonoghue@linaro.org, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-staging@lists.linux.dev,
Changhuang Liang
On 28/09/2023 10:22, Hans Verkuil wrote:
> On 28/09/2023 10:12, Jack Zhu wrote:
>>
>>
>> On 2023/9/15 17:26, Hans Verkuil wrote:
>>> On 14/09/2023 05:15, Jack Zhu wrote:
>>>> Hi,
>>>>
>>>> This series is the v9 series that attempts to support the Camera Subsystem
>>>> found on StarFive JH7110 SoC.
>>>>
>>>> This series is based on top of the master branch of media_stage repository.
>>>>
>>>> The following are the media graph for the device and the v4l2-compliance
>>>> output.
>>>>
>>>> ===========================================================================
>>>> [the media graph]:
>>>>
>>>> digraph board {
>>>> rankdir=TB
>>>> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
>>>> n00000001:port1 -> n00000008 [style=dashed]
>>>> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
>>>> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
>>>> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
>>>> n0000000e:port1 -> n00000001:port0 [style=dashed]
>>>> n0000000e:port1 -> n00000004 [style=dashed]
>>>> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
>>>> n00000018:port0 -> n0000000e:port0 [style=bold]
>>>> }
>>>>
>>>> [the device topology]:
>>>>
>>>> Media controller API version 6.5.0
>>>>
>>>> Media device information
>>>> ------------------------
>>>> driver starfive-camss
>>>> model Starfive Camera Subsystem
>>>> serial
>>>> bus info platform:19840000.camss
>>>> hw revision 0x0
>>>> driver version 6.5.0
>>>>
>>>> Device topology
>>>> - entity 1: stf_isp (2 pads, 2 links)
>>>> type V4L2 subdev subtype Unknown flags 0
>>>> device node name /dev/v4l-subdev0
>>>> pad0: Sink
>>>> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
>>>> crop.bounds:(0,0)/1920x1080
>>>> crop:(0,0)/1920x1080]
>>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>>> pad1: Source
>>>> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
>>>> crop.bounds:(0,0)/1920x1080
>>>> crop:(0,0)/1920x1080]
>>>> -> "capture_yuv":0 []
>>>>
>>>> - entity 4: capture_raw (1 pad, 1 link)
>>>> type Node subtype V4L flags 0
>>>> device node name /dev/video0
>>>> pad0: Sink
>>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>>>
>>>> - entity 8: capture_yuv (1 pad, 1 link)
>>>> type Node subtype V4L flags 0
>>>> device node name /dev/video1
>>>> pad0: Sink
>>>> <- "stf_isp":1 []
>>>>
>>>> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
>>>> type V4L2 subdev subtype Unknown flags 0
>>>> pad0: Sink
>>>> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
>>>> pad1: Source
>>>> -> "stf_isp":0 []
>>>> -> "capture_raw":0 []
>>>> pad2: Source
>>>> pad3: Source
>>>> pad4: Source
>>>>
>>>> - entity 24: imx219 6-0010 (1 pad, 1 link)
>>>> type V4L2 subdev subtype Sensor flags 0
>>>> device node name /dev/v4l-subdev1
>>>> pad0: Source
>>>> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
>>>> crop.bounds:(8,8)/3280x2464
>>>> crop:(8,8)/3280x2464]
>>>> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>>>>
>>>> ===========================================================================
>>>> [the v4l2-compliance output]:
>>>>
>>>> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
>>>
>>> This v4l2-compliance version is from a distro. For driver acceptance you
>>> must test with a v4l2-compliance compiled from the git repo (git://linuxtv.org/v4l-utils.git).
>>>
>>> Also, since this driver uses the media controller, you must run v4l2-compliance
>>> with the -m /dev/mediaX option. This will test the compliance of all devices
>>> reported by the media controller.
>>>
>>>>
>>>> Compliance test for stf camss device /dev/video1:
>>>>
>>>> Driver Info:
>>>> Driver name : stf camss
>>>
>>> The module is called starfive-camss, so shouldn't the driver name reported here
>>> be the same?
>>>
>>>> Card type : Starfive Camera Subsystem
>>>> Bus info : platform:19840000.camss
>>>> Driver version : 6.5.0
>>>> Capabilities : 0x84200001
>>>> Video Capture
>>>> Streaming
>>>> Extended Pix Format
>>>> Device Capabilities
>>>> Device Caps : 0x04200001
>>>> Video Capture
>>>> Streaming
>>>> Extended Pix Format
>>>> Media Driver Info:
>>>> Driver name : starfive-camss
>>>
>>> It's correct in the media controller information.
>>>
>>>> Model : Starfive Camera Subsystem
>>>> Serial :
>>>> Bus info : platform:19840000.camss
>>>> Media version : 6.5.0
>>>> Hardware revision: 0x00000000 (0)
>>>> Driver version : 6.5.0
>>>> Interface Info:
>>>> ID : 0x0300000a
>>>> Type : V4L Video
>>>> Entity Info:
>>>> ID : 0x00000008 (8)
>>>> Name : capture_yuv
>>>> Function : V4L2 I/O
>>>> Pad 0x01000009 : 0: Sink
>>>> Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
>>>
>>> Hmm, this reports "Unknown Function". I bet that when you run v4l2-compliance
>>> with the -m option it will fail on this. If not, then that's likely a bug in
>>> the compliance test, please let me know if that's the case.
>>>
>>
>> Hi Hans,
>>
>> The following is the latest test log, which does not report a failure, but
>> also reports "Unknown Function".
>>
>> I make the following settings in the stf-isp.c file:
>> v4l2_subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
>>
>
> Can you post the output of:
>
> v4l2-compliance --verbose -M /dev/media0
>
> I am beginning to suspect that utils/common/media-info.cpp is out-of-date:
> it is missing MEDIA_ENT_F_PROC_VIDEO_ISP.
Yes, this was missing. I've pushed a fix for this.
Regards,
Hans
>
> But I don't understand why v4l2-compliance didn't fail on this.
>
> Regards,
>
> Hans
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH v9 0/8] Add StarFive Camera Subsystem driver
2023-09-28 8:22 ` Hans Verkuil
2023-09-28 8:29 ` Hans Verkuil
@ 2023-09-28 8:40 ` Jack Zhu
2023-09-28 12:04 ` Hans Verkuil
1 sibling, 1 reply; 17+ messages in thread
From: Jack Zhu @ 2023-09-28 8:40 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Robert Foss, Todor Tomov,
bryan.odonoghue@linaro.org, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-staging@lists.linux.dev,
Changhuang Liang
On 2023/9/28 16:22, Hans Verkuil wrote:
> On 28/09/2023 10:12, Jack Zhu wrote:
>>
>>
>> On 2023/9/15 17:26, Hans Verkuil wrote:
>>> On 14/09/2023 05:15, Jack Zhu wrote:
>>>> Hi,
>>>>
>>>> This series is the v9 series that attempts to support the Camera Subsystem
>>>> found on StarFive JH7110 SoC.
>>>>
>>>> This series is based on top of the master branch of media_stage repository.
>>>>
>>>> The following are the media graph for the device and the v4l2-compliance
>>>> output.
>>>>
>>>> ===========================================================================
>>>> [the media graph]:
>>>>
>>>> digraph board {
>>>> rankdir=TB
>>>> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
>>>> n00000001:port1 -> n00000008 [style=dashed]
>>>> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
>>>> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
>>>> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
>>>> n0000000e:port1 -> n00000001:port0 [style=dashed]
>>>> n0000000e:port1 -> n00000004 [style=dashed]
>>>> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
>>>> n00000018:port0 -> n0000000e:port0 [style=bold]
>>>> }
>>>>
>>>> [the device topology]:
>>>>
>>>> Media controller API version 6.5.0
>>>>
>>>> Media device information
>>>> ------------------------
>>>> driver starfive-camss
>>>> model Starfive Camera Subsystem
>>>> serial
>>>> bus info platform:19840000.camss
>>>> hw revision 0x0
>>>> driver version 6.5.0
>>>>
>>>> Device topology
>>>> - entity 1: stf_isp (2 pads, 2 links)
>>>> type V4L2 subdev subtype Unknown flags 0
>>>> device node name /dev/v4l-subdev0
>>>> pad0: Sink
>>>> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
>>>> crop.bounds:(0,0)/1920x1080
>>>> crop:(0,0)/1920x1080]
>>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>>> pad1: Source
>>>> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
>>>> crop.bounds:(0,0)/1920x1080
>>>> crop:(0,0)/1920x1080]
>>>> -> "capture_yuv":0 []
>>>>
>>>> - entity 4: capture_raw (1 pad, 1 link)
>>>> type Node subtype V4L flags 0
>>>> device node name /dev/video0
>>>> pad0: Sink
>>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>>>
>>>> - entity 8: capture_yuv (1 pad, 1 link)
>>>> type Node subtype V4L flags 0
>>>> device node name /dev/video1
>>>> pad0: Sink
>>>> <- "stf_isp":1 []
>>>>
>>>> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
>>>> type V4L2 subdev subtype Unknown flags 0
>>>> pad0: Sink
>>>> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
>>>> pad1: Source
>>>> -> "stf_isp":0 []
>>>> -> "capture_raw":0 []
>>>> pad2: Source
>>>> pad3: Source
>>>> pad4: Source
>>>>
>>>> - entity 24: imx219 6-0010 (1 pad, 1 link)
>>>> type V4L2 subdev subtype Sensor flags 0
>>>> device node name /dev/v4l-subdev1
>>>> pad0: Source
>>>> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
>>>> crop.bounds:(8,8)/3280x2464
>>>> crop:(8,8)/3280x2464]
>>>> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>>>>
>>>> ===========================================================================
>>>> [the v4l2-compliance output]:
>>>>
>>>> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
>>>
>>> This v4l2-compliance version is from a distro. For driver acceptance you
>>> must test with a v4l2-compliance compiled from the git repo (git://linuxtv.org/v4l-utils.git).
>>>
>>> Also, since this driver uses the media controller, you must run v4l2-compliance
>>> with the -m /dev/mediaX option. This will test the compliance of all devices
>>> reported by the media controller.
>>>
>>>>
>>>> Compliance test for stf camss device /dev/video1:
>>>>
>>>> Driver Info:
>>>> Driver name : stf camss
>>>
>>> The module is called starfive-camss, so shouldn't the driver name reported here
>>> be the same?
>>>
>>>> Card type : Starfive Camera Subsystem
>>>> Bus info : platform:19840000.camss
>>>> Driver version : 6.5.0
>>>> Capabilities : 0x84200001
>>>> Video Capture
>>>> Streaming
>>>> Extended Pix Format
>>>> Device Capabilities
>>>> Device Caps : 0x04200001
>>>> Video Capture
>>>> Streaming
>>>> Extended Pix Format
>>>> Media Driver Info:
>>>> Driver name : starfive-camss
>>>
>>> It's correct in the media controller information.
>>>
>>>> Model : Starfive Camera Subsystem
>>>> Serial :
>>>> Bus info : platform:19840000.camss
>>>> Media version : 6.5.0
>>>> Hardware revision: 0x00000000 (0)
>>>> Driver version : 6.5.0
>>>> Interface Info:
>>>> ID : 0x0300000a
>>>> Type : V4L Video
>>>> Entity Info:
>>>> ID : 0x00000008 (8)
>>>> Name : capture_yuv
>>>> Function : V4L2 I/O
>>>> Pad 0x01000009 : 0: Sink
>>>> Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
>>>
>>> Hmm, this reports "Unknown Function". I bet that when you run v4l2-compliance
>>> with the -m option it will fail on this. If not, then that's likely a bug in
>>> the compliance test, please let me know if that's the case.
>>>
>>
>> Hi Hans,
>>
>> The following is the latest test log, which does not report a failure, but
>> also reports "Unknown Function".
>>
>> I make the following settings in the stf-isp.c file:
>> v4l2_subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
>>
>
> Can you post the output of:
>
> v4l2-compliance --verbose -M /dev/media0
>
Output log of the above command:
#
# v4l2-compliance --verbose -M /dev/media0
v4l2-compliance 1.25.0, 64 bits, 64-bit time_t
Compliance test for starfive-camss device /dev/media0:
Media Driver Info:
Driver name : starfive-camss
Model : Starfive Camera Subsystem
Serial :
Bus info : platform:19840000.camss
Media version : 6.5.0
Hardware revision: 0x00000000 (0)
Driver version : 6.5.0
Required ioctls:
test MEDIA_IOC_DEVICE_INFO: OK
test invalid ioctls: OK
Allow for multiple opens:
test second /dev/media0 open: OK
test MEDIA_IOC_DEVICE_INFO: OK
test for unlimited opens: OK
Media Controller ioctls:
Entity: 0x00000001 (Name: 'stf_isp', Function: Unknown Function (00004009))
Entity: 0x00000004 (Name: 'capture_raw', Function: V4L2 I/O)
Entity: 0x00000008 (Name: 'capture_yuv', Function: V4L2 I/O)
Entity: 0x0000000e (Name: 'cdns_csi2rx.19800000.csi-bridge', Function: Video Interface Bridge)
Entity: 0x00000018 (Name: 'imx219 6-0010', Function: Camera Sensor)
Interface: 0x03000006 (Type: V4L Video, DevPath: /dev/video0)
Interface: 0x0300000a (Type: V4L Video, DevPath: /dev/video1)
Interface: 0x0300001c (Type: V4L Sub-Device, DevPath: /dev/v4l-subdev0)
Interface: 0x0300001e (Type: V4L Sub-Device, DevPath: /dev/v4l-subdev1)
Pad: 0x01000002 (0, stf_isp, Sink)
Pad: 0x01000003 (1, stf_isp, Source)
Pad: 0x01000005 (0, capture_raw, Sink)
Pad: 0x01000009 (0, capture_yuv, Sink)
Pad: 0x0100000f (0, cdns_csi2rx.19800000.csi-bridge, Sink)
Pad: 0x01000010 (1, cdns_csi2rx.19800000.csi-bridge, Source)
Pad: 0x01000011 (2, cdns_csi2rx.19800000.csi-bridge, Source)
Pad: 0x01000012 (3, cdns_csi2rx.19800000.csi-bridge, Source)
Pad: 0x01000013 (4, cdns_csi2rx.19800000.csi-bridge, Source)
Pad: 0x01000019 (0, imx219 6-0010, Source)
Interface Link: 0x02000007 (capture_raw to /dev/video0)
Interface Link: 0x0200000b (capture_yuv to /dev/video1)
Data Link: 0x0200000c (stf_isp:1 -> capture_yuv:0, Data, Enabled)
Data Link: 0x02000014 (cdns_csi2rx.19800000.csi-bridge:1 -> stf_isp:0, Data, Enabled)
Data Link: 0x02000016 (cdns_csi2rx.19800000.csi-bridge:1 -> capture_raw:0, Data)
Data Link: 0x0200001a (imx219 6-0010:0 -> cdns_csi2rx.19800000.csi-bridge:0, Data, Enabled, Immutable)
Interface Link: 0x0200001d (stf_isp to /dev/v4l-subdev0)
Interface Link: 0x0200001f (imx219 6-0010 to /dev/v4l-subdev1)
test MEDIA_IOC_G_TOPOLOGY: OK
Entities: 5 Interfaces: 4 Pads: 10 Links: 8
Entity: 0x00000001 (Name: 'stf_isp', Type: Unknown V4L2 Sub-Device, DevPath: /dev/v4l-subdev0)
Entity: 0x00000004 (Name: 'capture_raw', Type: V4L2 I/O, DevPath: /dev/video0)
Entity: 0x00000008 (Name: 'capture_yuv', Type: V4L2 I/O, DevPath: /dev/video1)
Entity: 0x0000000e (Name: 'cdns_csi2rx.19800000.csi-bridge', Type: Unknown V4L2 Sub-Device)
Entity: 0x00000018 (Name: 'imx219 6-0010', Type: Camera Sensor, DevPath: /dev/v4l-subdev1)
test MEDIA_IOC_ENUM_ENTITIES/LINKS: OK
test MEDIA_IOC_SETUP_LINK: OK
Total for starfive-camss device /dev/media0: 8, Succeeded: 8, Failed: 0, Warnings: 0
#
--
Regards,
Jack Zhu
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH v9 0/8] Add StarFive Camera Subsystem driver
2023-09-28 8:40 ` Jack Zhu
@ 2023-09-28 12:04 ` Hans Verkuil
0 siblings, 0 replies; 17+ messages in thread
From: Hans Verkuil @ 2023-09-28 12:04 UTC (permalink / raw)
To: Jack Zhu, Mauro Carvalho Chehab, Robert Foss, Todor Tomov,
bryan.odonoghue@linaro.org, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Greg Kroah-Hartman, Philipp Zabel, Laurent Pinchart
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-staging@lists.linux.dev,
Changhuang Liang
Hi Jack,
On 28/09/2023 10:40, Jack Zhu wrote:
>
>
> On 2023/9/28 16:22, Hans Verkuil wrote:
>> On 28/09/2023 10:12, Jack Zhu wrote:
>>>
>>>
>>> On 2023/9/15 17:26, Hans Verkuil wrote:
>>>> On 14/09/2023 05:15, Jack Zhu wrote:
>>>>> Hi,
>>>>>
>>>>> This series is the v9 series that attempts to support the Camera Subsystem
>>>>> found on StarFive JH7110 SoC.
>>>>>
>>>>> This series is based on top of the master branch of media_stage repository.
>>>>>
>>>>> The following are the media graph for the device and the v4l2-compliance
>>>>> output.
>>>>>
>>>>> ===========================================================================
>>>>> [the media graph]:
>>>>>
>>>>> digraph board {
>>>>> rankdir=TB
>>>>> n00000001 [label="{{<port0> 0} | stf_isp\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
>>>>> n00000001:port1 -> n00000008 [style=dashed]
>>>>> n00000004 [label="capture_raw\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
>>>>> n00000008 [label="capture_yuv\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
>>>>> n0000000e [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
>>>>> n0000000e:port1 -> n00000001:port0 [style=dashed]
>>>>> n0000000e:port1 -> n00000004 [style=dashed]
>>>>> n00000018 [label="{{} | imx219 6-0010\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
>>>>> n00000018:port0 -> n0000000e:port0 [style=bold]
>>>>> }
>>>>>
>>>>> [the device topology]:
>>>>>
>>>>> Media controller API version 6.5.0
>>>>>
>>>>> Media device information
>>>>> ------------------------
>>>>> driver starfive-camss
>>>>> model Starfive Camera Subsystem
>>>>> serial
>>>>> bus info platform:19840000.camss
>>>>> hw revision 0x0
>>>>> driver version 6.5.0
>>>>>
>>>>> Device topology
>>>>> - entity 1: stf_isp (2 pads, 2 links)
>>>>> type V4L2 subdev subtype Unknown flags 0
>>>>> device node name /dev/v4l-subdev0
>>>>> pad0: Sink
>>>>> [fmt:SRGGB10_1X10/1920x1080 field:none colorspace:srgb
>>>>> crop.bounds:(0,0)/1920x1080
>>>>> crop:(0,0)/1920x1080]
>>>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>>>> pad1: Source
>>>>> [fmt:YUYV8_1_5X8/1920x1080 field:none colorspace:srgb
>>>>> crop.bounds:(0,0)/1920x1080
>>>>> crop:(0,0)/1920x1080]
>>>>> -> "capture_yuv":0 []
>>>>>
>>>>> - entity 4: capture_raw (1 pad, 1 link)
>>>>> type Node subtype V4L flags 0
>>>>> device node name /dev/video0
>>>>> pad0: Sink
>>>>> <- "cdns_csi2rx.19800000.csi-bridge":1 []
>>>>>
>>>>> - entity 8: capture_yuv (1 pad, 1 link)
>>>>> type Node subtype V4L flags 0
>>>>> device node name /dev/video1
>>>>> pad0: Sink
>>>>> <- "stf_isp":1 []
>>>>>
>>>>> - entity 14: cdns_csi2rx.19800000.csi-bridge (5 pads, 3 links)
>>>>> type V4L2 subdev subtype Unknown flags 0
>>>>> pad0: Sink
>>>>> <- "imx219 6-0010":0 [ENABLED,IMMUTABLE]
>>>>> pad1: Source
>>>>> -> "stf_isp":0 []
>>>>> -> "capture_raw":0 []
>>>>> pad2: Source
>>>>> pad3: Source
>>>>> pad4: Source
>>>>>
>>>>> - entity 24: imx219 6-0010 (1 pad, 1 link)
>>>>> type V4L2 subdev subtype Sensor flags 0
>>>>> device node name /dev/v4l-subdev1
>>>>> pad0: Source
>>>>> [fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
>>>>> crop.bounds:(8,8)/3280x2464
>>>>> crop:(8,8)/3280x2464]
>>>>> -> "cdns_csi2rx.19800000.csi-bridge":0 [ENABLED,IMMUTABLE]
>>>>>
>>>>> ===========================================================================
>>>>> [the v4l2-compliance output]:
>>>>>
>>>>> v4l2-compliance 1.24.1, 64 bits, 64-bit time_t
>>>>
>>>> This v4l2-compliance version is from a distro. For driver acceptance you
>>>> must test with a v4l2-compliance compiled from the git repo (git://linuxtv.org/v4l-utils.git).
>>>>
>>>> Also, since this driver uses the media controller, you must run v4l2-compliance
>>>> with the -m /dev/mediaX option. This will test the compliance of all devices
>>>> reported by the media controller.
>>>>
>>>>>
>>>>> Compliance test for stf camss device /dev/video1:
>>>>>
>>>>> Driver Info:
>>>>> Driver name : stf camss
>>>>
>>>> The module is called starfive-camss, so shouldn't the driver name reported here
>>>> be the same?
>>>>
>>>>> Card type : Starfive Camera Subsystem
>>>>> Bus info : platform:19840000.camss
>>>>> Driver version : 6.5.0
>>>>> Capabilities : 0x84200001
>>>>> Video Capture
>>>>> Streaming
>>>>> Extended Pix Format
>>>>> Device Capabilities
>>>>> Device Caps : 0x04200001
>>>>> Video Capture
>>>>> Streaming
>>>>> Extended Pix Format
>>>>> Media Driver Info:
>>>>> Driver name : starfive-camss
>>>>
>>>> It's correct in the media controller information.
>>>>
>>>>> Model : Starfive Camera Subsystem
>>>>> Serial :
>>>>> Bus info : platform:19840000.camss
>>>>> Media version : 6.5.0
>>>>> Hardware revision: 0x00000000 (0)
>>>>> Driver version : 6.5.0
>>>>> Interface Info:
>>>>> ID : 0x0300000a
>>>>> Type : V4L Video
>>>>> Entity Info:
>>>>> ID : 0x00000008 (8)
>>>>> Name : capture_yuv
>>>>> Function : V4L2 I/O
>>>>> Pad 0x01000009 : 0: Sink
>>>>> Link 0x0200000c: from remote pad 0x1000003 of entity 'stf_isp' (Unknown Function (00004009)): Data, Enabled
>>>>
>>>> Hmm, this reports "Unknown Function". I bet that when you run v4l2-compliance
>>>> with the -m option it will fail on this. If not, then that's likely a bug in
>>>> the compliance test, please let me know if that's the case.
>>>>
>>>
>>> Hi Hans,
>>>
>>> The following is the latest test log, which does not report a failure, but
>>> also reports "Unknown Function".
>>>
>>> I make the following settings in the stf-isp.c file:
>>> v4l2_subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
>>>
>>
>> Can you post the output of:
>>
>> v4l2-compliance --verbose -M /dev/media0
>>
>
> Output log of the above command:
>
> #
> # v4l2-compliance --verbose -M /dev/media0
> v4l2-compliance 1.25.0, 64 bits, 64-bit time_t
>
> Compliance test for starfive-camss device /dev/media0:
>
> Media Driver Info:
> Driver name : starfive-camss
> Model : Starfive Camera Subsystem
> Serial :
> Bus info : platform:19840000.camss
> Media version : 6.5.0
> Hardware revision: 0x00000000 (0)
> Driver version : 6.5.0
>
> Required ioctls:
> test MEDIA_IOC_DEVICE_INFO: OK
> test invalid ioctls: OK
>
> Allow for multiple opens:
> test second /dev/media0 open: OK
> test MEDIA_IOC_DEVICE_INFO: OK
> test for unlimited opens: OK
>
> Media Controller ioctls:
> Entity: 0x00000001 (Name: 'stf_isp', Function: Unknown Function (00004009))
> Entity: 0x00000004 (Name: 'capture_raw', Function: V4L2 I/O)
> Entity: 0x00000008 (Name: 'capture_yuv', Function: V4L2 I/O)
> Entity: 0x0000000e (Name: 'cdns_csi2rx.19800000.csi-bridge', Function: Video Interface Bridge)
> Entity: 0x00000018 (Name: 'imx219 6-0010', Function: Camera Sensor)
> Interface: 0x03000006 (Type: V4L Video, DevPath: /dev/video0)
> Interface: 0x0300000a (Type: V4L Video, DevPath: /dev/video1)
> Interface: 0x0300001c (Type: V4L Sub-Device, DevPath: /dev/v4l-subdev0)
> Interface: 0x0300001e (Type: V4L Sub-Device, DevPath: /dev/v4l-subdev1)
> Pad: 0x01000002 (0, stf_isp, Sink)
> Pad: 0x01000003 (1, stf_isp, Source)
> Pad: 0x01000005 (0, capture_raw, Sink)
> Pad: 0x01000009 (0, capture_yuv, Sink)
> Pad: 0x0100000f (0, cdns_csi2rx.19800000.csi-bridge, Sink)
> Pad: 0x01000010 (1, cdns_csi2rx.19800000.csi-bridge, Source)
> Pad: 0x01000011 (2, cdns_csi2rx.19800000.csi-bridge, Source)
> Pad: 0x01000012 (3, cdns_csi2rx.19800000.csi-bridge, Source)
> Pad: 0x01000013 (4, cdns_csi2rx.19800000.csi-bridge, Source)
> Pad: 0x01000019 (0, imx219 6-0010, Source)
> Interface Link: 0x02000007 (capture_raw to /dev/video0)
> Interface Link: 0x0200000b (capture_yuv to /dev/video1)
> Data Link: 0x0200000c (stf_isp:1 -> capture_yuv:0, Data, Enabled)
> Data Link: 0x02000014 (cdns_csi2rx.19800000.csi-bridge:1 -> stf_isp:0, Data, Enabled)
> Data Link: 0x02000016 (cdns_csi2rx.19800000.csi-bridge:1 -> capture_raw:0, Data)
> Data Link: 0x0200001a (imx219 6-0010:0 -> cdns_csi2rx.19800000.csi-bridge:0, Data, Enabled, Immutable)
> Interface Link: 0x0200001d (stf_isp to /dev/v4l-subdev0)
> Interface Link: 0x0200001f (imx219 6-0010 to /dev/v4l-subdev1)
> test MEDIA_IOC_G_TOPOLOGY: OK
> Entities: 5 Interfaces: 4 Pads: 10 Links: 8
> Entity: 0x00000001 (Name: 'stf_isp', Type: Unknown V4L2 Sub-Device, DevPath: /dev/v4l-subdev0)
> Entity: 0x00000004 (Name: 'capture_raw', Type: V4L2 I/O, DevPath: /dev/video0)
> Entity: 0x00000008 (Name: 'capture_yuv', Type: V4L2 I/O, DevPath: /dev/video1)
> Entity: 0x0000000e (Name: 'cdns_csi2rx.19800000.csi-bridge', Type: Unknown V4L2 Sub-Device)
> Entity: 0x00000018 (Name: 'imx219 6-0010', Type: Camera Sensor, DevPath: /dev/v4l-subdev1)
> test MEDIA_IOC_ENUM_ENTITIES/LINKS: OK
> test MEDIA_IOC_SETUP_LINK: OK
>
> Total for starfive-camss device /dev/media0: 8, Succeeded: 8, Failed: 0, Warnings: 0
Much appreciated. I found several logic bugs in v4l-utils that hid this failure.
It is now fixed in the v4l-utils git repo: https://git.linuxtv.org/v4l-utils.git/log/
This also adds the missing support for MEDIA_ENT_F_PROC_VIDEO_ISP.
If you compile v4l2-compliance from the git repo, then this should now work fine.
Regards,
Hans
^ permalink raw reply [flat|nested] 17+ messages in thread